This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PRE and uninitialized variables
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: Marc Glisse <marc dot glisse at inria dot fr>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 18 May 2015 12:32:07 +0200
- Subject: Re: PRE and uninitialized variables
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot DEB dot 2 dot 02 dot 1505172018530 dot 18574 at stedding dot saclay dot inria dot fr>
On Sun, May 17, 2015 at 9:11 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
> 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).
Yeah - the tail-merging code should now be stripped off using the VN as
now PRE fully propagates all values.
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...
You should use VN_TOP during VN. Otherwise you'll miss optimization
opportunities. Now the question is then what to use at eliminate() time.
To get useful warnings you'd need to distinguish which VN_TOP you
get?
Note that funneling in VN_TOP might be tricky ;)
Richard.
> * 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
> 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);
>