PRE and uninitialized variables
Marc Glisse
marc.glisse@inria.fr
Sun May 17 20:21:00 GMT 2015
Hello,
first, this patch is not ready (it doesn't even bootstrap), I am posting
it for comments. The idea is, when we do value numbering, while looking
for the current value of a local variable, we may hit a clobber or reach
the beginning of the function. In both cases, it seems to me that we could
use a default definition as the value of the variable. This later allows
the uninit pass to warn about the use of an uninitialized or clobbered
variable (some passes can also optimize the code better). The part about
clobbers passed regtesting, but the part about reaching the entry of the
function fails bootstrap with:
Existing SSA name for symbol marked for renaming: __d_14(D)
internal compiler error: SSA corruption
when execute_update_addresses_taken is called after SRA. In the case I
looked at, the new code was called on the lhs of an assignment (to check
if both sides had the same value number). Creating new ssa_names in the
middle of sccvn is probably a bad idea, although it doesn't help if I
create them beforehand, maybe creating the default definition and leaving
it unused means that no one feels responsible for cleaning it up?
(TODO_update_ssa doesn't help)
I am quite restrictive in the conditions for the code to apply:
is_gimple_reg_type, useless_type_conversion_p (uh? I forgot that one in
the "reached entry" case...), I am not sure what I can do if the local
variable is an aggregate and we are reading one field, maybe create an
artificial variable just for the purpose of using its default definition?
Mostly, I would like to know if the approach makes sense. Is storing the
default definition in SSA_VAL ok, or is there some way to use VN_TOP to
mark undefinedness? Any pointer would be welcome...
* tree-ssa-sccvn.c (vn_reference_lookup_2): Handle function entry.
(vn_reference_lookup_3): Handle clobbers.
(init_scc_vn): Default definitions are their own definition.
PS: the testsuite for libgomp is looong, it almost doubles the time for
the whole testsuite to complete on gcc112. It would be great if someone
could split it into a few pieces that run in parallel.
--
Marc Glisse
-------------- next part --------------
Index: gcc/testsuite/gcc.dg/uninit-clob.c
===================================================================
--- gcc/testsuite/gcc.dg/uninit-clob.c (revision 0)
+++ gcc/testsuite/gcc.dg/uninit-clob.c (working copy)
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized" } */
+
+int *p;
+
+int f(){
+ {
+ int q = 42;
+ p = &q;
+ }
+ return *p; /* { dg-warning "uninitialized" "warning" } */
+}
+
Index: gcc/testsuite/gcc.dg/uninit-sccvn.c
===================================================================
--- gcc/testsuite/gcc.dg/uninit-sccvn.c (revision 0)
+++ gcc/testsuite/gcc.dg/uninit-sccvn.c (working copy)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized" } */
+
+int g, h;
+void *p;
+int f(int x){
+ int a;
+ g = 42;
+ h = a;
+ p = &a;
+ return h; /* { dg-warning "uninitialized" "warning" } */
+}
Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c (revision 223269)
+++ gcc/tree-ssa-sccvn.c (working copy)
@@ -1553,26 +1553,33 @@ vn_reference_lookup_1 (vn_reference_t vr
*vnresult = (vn_reference_t)*slot;
return ((vn_reference_t)*slot)->result;
}
return NULL_TREE;
}
static tree *last_vuse_ptr;
static vn_lookup_kind vn_walk_kind;
static vn_lookup_kind default_vn_walk_kind;
+static vn_reference_t
+vn_reference_lookup_or_insert_for_pieces (tree vuse,
+ alias_set_type set,
+ tree type,
+ vec<vn_reference_op_s,
+ va_heap> operands,
+ tree value);
/* Callback for walk_non_aliased_vuses. Adjusts the vn_reference_t VR_
with the current VUSE and performs the expression lookup. */
static void *
-vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse,
+vn_reference_lookup_2 (ao_ref *ref, tree vuse,
unsigned int cnt, void *vr_)
{
vn_reference_t vr = (vn_reference_t)vr_;
vn_reference_s **slot;
hashval_t hash;
/* This bounds the stmt walks we perform on reference lookups
to O(1) instead of O(N) where N is the number of dominating
stores. */
if (cnt > (unsigned) PARAM_VALUE (PARAM_SCCVN_MAX_ALIAS_QUERIES_PER_ACCESS))
@@ -1587,20 +1594,39 @@ vn_reference_lookup_2 (ao_ref *op ATTRIB
vr->vuse = vuse_ssa_val (vuse);
if (vr->vuse)
vr->hashcode = vr->hashcode + SSA_NAME_VERSION (vr->vuse);
hash = vr->hashcode;
slot = current_info->references->find_slot_with_hash (vr, hash, NO_INSERT);
if (!slot && current_info == optimistic_info)
slot = valid_info->references->find_slot_with_hash (vr, hash, NO_INSERT);
if (slot)
return *slot;
+ if (gimple_nop_p (SSA_NAME_DEF_STMT (vuse)))
+ {
+ tree base = ao_ref_base (ref);
+ if (TREE_CODE (base) == VAR_DECL
+ && !is_global_var (base)
+ && is_gimple_reg_type (vr->type))
+ {
+ tree val = ssa_default_def (cfun, base);
+ if (!val)
+ {
+ val = get_or_create_ssa_default_def (cfun, base);
+ VN_INFO_GET (val)->valnum = val;
+ VN_INFO (val)->expr = NULL_TREE;
+ VN_INFO (val)->value_id = 0;
+ }
+ return vn_reference_lookup_or_insert_for_pieces
+ (vuse, vr->set, vr->type, vr->operands, val);
+ }
+ }
return NULL;
}
/* Lookup an existing or insert a new vn_reference entry into the
value table for the VUSE, SET, TYPE, OPERANDS reference which
has the value VALUE which is either a constant or an SSA name. */
static vn_reference_t
vn_reference_lookup_or_insert_for_pieces (tree vuse,
@@ -1712,21 +1738,40 @@ vn_reference_lookup_3 (ao_ref *ref, tree
offset = ref->offset;
maxsize = ref->max_size;
/* If we cannot constrain the size of the reference we cannot
test if anything kills it. */
if (maxsize == -1)
return (void *)-1;
/* We can't deduce anything useful from clobbers. */
if (gimple_clobber_p (def_stmt))
- return (void *)-1;
+ {
+ if (TREE_CODE (base) == VAR_DECL
+ && !is_global_var (base)
+ && operand_equal_p (base, gimple_assign_lhs (def_stmt), 0)
+ && is_gimple_reg_type (vr->type)
+ && useless_type_conversion_p (vr->type, TREE_TYPE (base)))
+ {
+ tree val = ssa_default_def (cfun, base);
+ if (!val)
+ {
+ val = get_or_create_ssa_default_def (cfun, base);
+ VN_INFO_GET (val)->valnum = val;
+ VN_INFO (val)->expr = NULL_TREE;
+ VN_INFO (val)->value_id = 0;
+ }
+ return vn_reference_lookup_or_insert_for_pieces
+ (vuse, vr->set, vr->type, vr->operands, val);
+ }
+ return (void *)-1;
+ }
/* def_stmt may-defs *ref. See if we can derive a value for *ref
from that definition.
1) Memset. */
if (is_gimple_reg_type (vr->type)
&& gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET)
&& integer_zerop (gimple_call_arg (def_stmt, 1))
&& tree_fits_uhwi_p (gimple_call_arg (def_stmt, 2))
&& TREE_CODE (gimple_call_arg (def_stmt, 0)) == ADDR_EXPR)
{
@@ -4190,21 +4235,22 @@ init_scc_vn (void)
VN_TOP = create_tmp_var_raw (void_type_node, "vn_top");
/* Create the VN_INFO structures, and initialize value numbers to
TOP. */
for (i = 0; i < num_ssa_names; i++)
{
tree name = ssa_name (i);
if (name)
{
- VN_INFO_GET (name)->valnum = VN_TOP;
+ VN_INFO_GET (name)->valnum = SSA_NAME_IS_DEFAULT_DEF (name) ? name
+ : VN_TOP;
VN_INFO (name)->expr = NULL_TREE;
VN_INFO (name)->value_id = 0;
}
}
renumber_gimple_stmt_uids ();
/* Create the valid and optimistic value numbering tables. */
valid_info = XCNEW (struct vn_tables_s);
allocate_vn_table (valid_info);
More information about the Gcc-patches
mailing list