summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-uninit.c
diff options
context:
space:
mode:
authordavidxl <davidxl@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-15 23:16:59 +0000
committerdavidxl <davidxl@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-15 23:16:59 +0000
commit4028020e9f517e272f3f9889d35f74cac6bbbb29 (patch)
tree410cb95a75eba97ac187d4846c518ab3ab669b4e /gcc/tree-ssa-uninit.c
parentb7e7fbc12445264857d83f3fa321c2a4d7e9cb79 (diff)
downloadgcc-4028020e9f517e272f3f9889d35f74cac6bbbb29.tar.gz
uninit var analysis enhancement
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165530 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-uninit.c')
-rw-r--r--gcc/tree-ssa-uninit.c187
1 files changed, 145 insertions, 42 deletions
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 78b88e9bd93..01ff43165d3 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -785,6 +785,139 @@ is_use_properly_guarded (gimple use_stmt,
unsigned uninit_opnds,
struct pointer_set_t *visited_phis);
+/* Returns true if all uninitialized opnds are pruned. Returns false
+ otherwise. PHI is the phi node with uninitialized operands,
+ UNINIT_OPNDS is the bitmap of the uninitialize operand positions,
+ FLAG_DEF is the statement defining the flag guarding the use of the
+ PHI output, BOUNDARY_CST is the const value used in the predicate
+ associated with the flag, CMP_CODE is the comparison code used in
+ the predicate, VISITED_PHIS is the pointer set of phis visited, and
+ VISITED_FLAG_PHIS is the pointer to the pointer set of flag definitions
+ that are also phis.
+
+ Example scenario:
+
+ BB1:
+ flag_1 = phi <0, 1> // (1)
+ var_1 = phi <undef, some_val>
+
+
+ BB2:
+ flag_2 = phi <0, flag_1, flag_1> // (2)
+ var_2 = phi <undef, var_1, var_1>
+ if (flag_2 == 1)
+ goto BB3;
+
+ BB3:
+ use of var_2 // (3)
+
+ Because some flag arg in (1) is not constant, if we do not look into the
+ flag phis recursively, it is conservatively treated as unknown and var_1
+ is thought to be flowed into use at (3). Since var_1 is potentially uninitialized
+ a false warning will be emitted. Checking recursively into (1), the compiler can
+ find out that only some_val (which is defined) can flow into (3) which is OK.
+
+*/
+
+static bool
+prune_uninit_phi_opnds_in_unrealizable_paths (
+ gimple phi, unsigned uninit_opnds,
+ gimple flag_def, tree boundary_cst,
+ enum tree_code cmp_code,
+ struct pointer_set_t *visited_phis,
+ bitmap *visited_flag_phis)
+{
+ unsigned i;
+
+ for (i = 0; i < MIN (32, gimple_phi_num_args (flag_def)); i++)
+ {
+ tree flag_arg;
+
+ if (!MASK_TEST_BIT (uninit_opnds, i))
+ continue;
+
+ flag_arg = gimple_phi_arg_def (flag_def, i);
+ if (!is_gimple_constant (flag_arg))
+ {
+ gimple flag_arg_def, phi_arg_def;
+ tree phi_arg;
+ unsigned uninit_opnds_arg_phi;
+
+ if (TREE_CODE (flag_arg) != SSA_NAME)
+ return false;
+ flag_arg_def = SSA_NAME_DEF_STMT (flag_arg);
+ if (gimple_code (flag_arg_def) != GIMPLE_PHI)
+ return false;
+
+ phi_arg = gimple_phi_arg_def (phi, i);
+ if (TREE_CODE (phi_arg) != SSA_NAME)
+ return false;
+
+ phi_arg_def = SSA_NAME_DEF_STMT (phi_arg);
+ if (gimple_code (phi_arg_def) != GIMPLE_PHI)
+ return false;
+
+ if (gimple_bb (phi_arg_def) != gimple_bb (flag_arg_def))
+ return false;
+
+ if (!*visited_flag_phis)
+ *visited_flag_phis = BITMAP_ALLOC (NULL);
+
+ if (bitmap_bit_p (*visited_flag_phis,
+ SSA_NAME_VERSION (gimple_phi_result (flag_arg_def))))
+ return false;
+
+ bitmap_set_bit (*visited_flag_phis,
+ SSA_NAME_VERSION (gimple_phi_result (flag_arg_def)));
+
+ /* Now recursively prune the uninitialized phi args. */
+ uninit_opnds_arg_phi = compute_uninit_opnds_pos (phi_arg_def);
+ if (!prune_uninit_phi_opnds_in_unrealizable_paths (
+ phi_arg_def, uninit_opnds_arg_phi,
+ flag_arg_def, boundary_cst, cmp_code,
+ visited_phis, visited_flag_phis))
+ return false;
+
+ bitmap_clear_bit (*visited_flag_phis,
+ SSA_NAME_VERSION (gimple_phi_result (flag_arg_def)));
+ continue;
+ }
+
+ /* Now check if the constant is in the guarded range. */
+ if (is_value_included_in (flag_arg, boundary_cst, cmp_code))
+ {
+ tree opnd;
+ gimple opnd_def;
+
+ /* Now that we know that this undefined edge is not
+ pruned. If the operand is defined by another phi,
+ we can further prune the incoming edges of that
+ phi by checking the predicates of this operands. */
+
+ opnd = gimple_phi_arg_def (phi, i);
+ opnd_def = SSA_NAME_DEF_STMT (opnd);
+ if (gimple_code (opnd_def) == GIMPLE_PHI)
+ {
+ edge opnd_edge;
+ unsigned uninit_opnds2
+ = compute_uninit_opnds_pos (opnd_def);
+ gcc_assert (!MASK_EMPTY (uninit_opnds2));
+ opnd_edge = gimple_phi_arg_edge (phi, i);
+ if (!is_use_properly_guarded (phi,
+ opnd_edge->src,
+ opnd_def,
+ uninit_opnds2,
+ visited_phis))
+ return false;
+ }
+ else
+ return false;
+ }
+ }
+
+ return true;
+}
+
/* A helper function that determines if the predicate set
of the use is not overlapping with that of the uninit paths.
The most common senario of guarded use is in Example 1:
@@ -873,6 +1006,8 @@ use_pred_not_overlap_with_undef_path_pred (
bool swap_cond = false;
bool invert = false;
VEC(use_pred_info_t, heap) *the_pred_chain;
+ bitmap visited_flag_phis = NULL;
+ bool all_pruned = false;
gcc_assert (num_preds > 0);
/* Find within the common prefix of multiple predicate chains
@@ -935,50 +1070,18 @@ use_pred_not_overlap_with_undef_path_pred (
if (cmp_code == ERROR_MARK)
return false;
- for (i = 0; i < sizeof (unsigned); i++)
- {
- tree flag_arg;
-
- if (!MASK_TEST_BIT (uninit_opnds, i))
- continue;
-
- flag_arg = gimple_phi_arg_def (flag_def, i);
- if (!is_gimple_constant (flag_arg))
- return false;
-
- /* Now check if the constant is in the guarded range. */
- if (is_value_included_in (flag_arg, boundary_cst, cmp_code))
- {
- tree opnd;
- gimple opnd_def;
-
- /* Now that we know that this undefined edge is not
- pruned. If the operand is defined by another phi,
- we can further prune the incoming edges of that
- phi by checking the predicates of this operands. */
+ all_pruned = prune_uninit_phi_opnds_in_unrealizable_paths (phi,
+ uninit_opnds,
+ flag_def,
+ boundary_cst,
+ cmp_code,
+ visited_phis,
+ &visited_flag_phis);
- opnd = gimple_phi_arg_def (phi, i);
- opnd_def = SSA_NAME_DEF_STMT (opnd);
- if (gimple_code (opnd_def) == GIMPLE_PHI)
- {
- edge opnd_edge;
- unsigned uninit_opnds2
- = compute_uninit_opnds_pos (opnd_def);
- gcc_assert (!MASK_EMPTY (uninit_opnds2));
- opnd_edge = gimple_phi_arg_edge (phi, i);
- if (!is_use_properly_guarded (phi,
- opnd_edge->src,
- opnd_def,
- uninit_opnds2,
- visited_phis))
- return false;
- }
- else
- return false;
- }
- }
+ if (visited_flag_phis)
+ BITMAP_FREE (visited_flag_phis);
- return true;
+ return all_pruned;
}
/* Returns true if TC is AND or OR */