This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [tree-ssa] fix *(&a[1] + 8B)
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: Richard Henderson <rth at twiddle dot net>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 2 Dec 2003 18:54:05 +0100
- Subject: Re: [tree-ssa] fix *(&a[1] + 8B)
- References: <20031202041748.GA8647@twiddle.net>
> The reason for the tree-dfa change is that, as discussed elsewhere,
> this case doesn't work. We don't create VDEFs for nested constructs
> when the INDIRECT_REF is on the lhs. But rather than fix that, we
> decided that these cases were in fact illegal.
>
> Removing that check produced one test suite regression that can show
> this kind of complex address construction: execute/20021120-1.c.
>
> The extra code in maybe_fold_stmt_plus assures that we reduce
>
> *(&a[1] + 4B)
> to
> a[2]
>
> as we expected. The change to use int_const_binop just means
> we don't create tree garbage when we don't have to.
Just curious, what happens to *(&a[1] + 3B)?
Thanks for working on this!
Honza
>
> Bootstrapped and tested with no regressions on i686-linux.
>
>
> r~
>
>
> * tree-dfa.c (get_expr_operands): Don't handle PLUS_EXPR inside
> INDIRECT_REF.
> * tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Use int_const_binop.
> (maybe_fold_offset_to_component_ref): Likewise.
> (maybe_fold_stmt_indirect): Likewise.
> (maybe_fold_stmt_plus): Expand ARRAY_REF when seen with addend.
> * fold-const.c (int_const_binop): Export.
> * tree.h (int_const_binop): Declare.
>
> Index: fold-const.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
> retrieving revision 1.213.2.64
> diff -u -p -r1.213.2.64 fold-const.c
> --- fold-const.c 24 Nov 2003 20:28:55 -0000 1.213.2.64
> +++ fold-const.c 2 Dec 2003 04:02:24 -0000
> @@ -65,7 +65,6 @@ static bool negate_expr_p (tree);
> static tree negate_expr (tree);
> static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
> static tree associate_trees (tree, tree, enum tree_code, tree);
> -static tree int_const_binop (enum tree_code, tree, tree, int);
> static tree const_binop (enum tree_code, tree, tree, int);
> static hashval_t size_htab_hash (const void *);
> static int size_htab_eq (const void *, const void *);
> @@ -1170,7 +1169,7 @@ associate_trees (tree t1, tree t2, enum
>
> If NOTRUNC is nonzero, do not truncate the result to fit the data type. */
>
> -static tree
> +tree
> int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
> {
> unsigned HOST_WIDE_INT int1l, int2l;
> Index: tree-dfa.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
> retrieving revision 1.1.4.190
> diff -u -p -r1.1.4.190 tree-dfa.c
> --- tree-dfa.c 28 Nov 2003 21:26:38 -0000 1.1.4.190
> +++ tree-dfa.c 2 Dec 2003 04:02:27 -0000
> @@ -394,19 +394,6 @@ get_expr_operands (tree stmt, tree *expr
> return;
> }
>
> - /* This single case might not have been folded to an array reference
> - if the immediate doesn't exactly divide the referenced type. This
> - case is likely to be undefined in C, but perhaps not others. */
> - else if (TREE_CODE (ptr) == PLUS_EXPR)
> - {
> - if (TREE_CODE (TREE_OPERAND (ptr, 1)) != INTEGER_CST)
> - abort ();
> - ptr = TREE_OPERAND (ptr, 0);
> - if (TREE_CODE (ptr) != ADDR_EXPR)
> - abort ();
> - pptr = &TREE_OPERAND (ptr, 0);
> - }
> -
> /* Everything else should have been folded elsewhere. */
> else
> abort ();
> Index: tree-ssa-ccp.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-ccp.c,v
> retrieving revision 1.1.2.118
> diff -u -p -r1.1.2.118 tree-ssa-ccp.c
> --- tree-ssa-ccp.c 27 Nov 2003 21:36:13 -0000 1.1.2.118
> +++ tree-ssa-ccp.c 2 Dec 2003 04:02:28 -0000
> @@ -1531,8 +1531,7 @@ maybe_fold_offset_to_array_ref (tree bas
> {
> idx = convert (TREE_TYPE (min_idx), idx);
> if (!integer_zerop (min_idx))
> - idx = fold (build (PLUS_EXPR, TREE_TYPE (min_idx),
> - idx, min_idx));
> + idx = int_const_binop (PLUS_EXPR, idx, min_idx, 1);
> }
> }
>
> @@ -1594,8 +1593,7 @@ maybe_fold_offset_to_component_ref (tree
> if (!DECL_SIZE_UNIT (f)
> || TREE_CODE (DECL_SIZE_UNIT (f)) != INTEGER_CST)
> continue;
> - t = fold (build (MINUS_EXPR, TREE_TYPE (offset),
> - offset, DECL_FIELD_OFFSET (f)));
> + t = int_const_binop (MINUS_EXPR, offset, DECL_FIELD_OFFSET (f), 1);
> if (!tree_int_cst_lt (t, DECL_SIZE_UNIT (f)))
> continue;
>
> @@ -1664,7 +1662,7 @@ maybe_fold_stmt_indirect (tree expr, tre
> return NULL_TREE;
> base = TREE_OPERAND (base, 0);
>
> - offset = fold (build (PLUS_EXPR, TREE_TYPE (offset), offset, offset2));
> + offset = int_const_binop (PLUS_EXPR, offset, offset2, 1);
> }
>
> if (TREE_CODE (base) == ADDR_EXPR)
> @@ -1760,8 +1758,45 @@ maybe_fold_stmt_plus (tree expr)
> /* The first operand should be an ADDR_EXPR. */
> if (TREE_CODE (op0) != ADDR_EXPR)
> return NULL_TREE;
> -
> op0 = TREE_OPERAND (op0, 0);
> +
> + /* If the first operand is an ARRAY_REF, expand it so that we can fold
> + the offset into it. */
> + while (TREE_CODE (op0) == ARRAY_REF)
> + {
> + tree array_obj = TREE_OPERAND (op0, 0);
> + tree array_idx = TREE_OPERAND (op0, 1);
> + tree elt_type = TREE_TYPE (op0);
> + tree elt_size = TYPE_SIZE_UNIT (elt_type);
> + tree min_idx;
> +
> + if (TREE_CODE (array_idx) != INTEGER_CST)
> + break;
> + if (TREE_CODE (elt_size) != INTEGER_CST)
> + break;
> +
> + /* Un-bias the index by the min index of the array type. */
> + min_idx = TYPE_DOMAIN (TREE_TYPE (array_obj));
> + if (min_idx)
> + {
> + min_idx = TYPE_MIN_VALUE (min_idx);
> + if (min_idx)
> + {
> + array_idx = convert (TREE_TYPE (min_idx), array_idx);
> + if (!integer_zerop (min_idx))
> + array_idx = int_const_binop (MINUS_EXPR, array_idx, min_idx, 0);
> + }
> + }
> +
> + /* Convert the index to a byte offset. */
> + array_idx = convert (sizetype, array_idx);
> + array_idx = int_const_binop (MULT_EXPR, array_idx, elt_size, 0);
> +
> + /* Update the operands for the next round, or for folding. */
> + op1 = int_const_binop (PLUS_EXPR, array_idx, op1, 0);
> + op0 = array_obj;
> + }
> +
> ptd_type = TREE_TYPE (ptr_type);
>
> /* At which point we can try some of the same things as for indirects. */
> Index: tree.h
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/tree.h,v
> retrieving revision 1.342.2.141
> diff -u -p -r1.342.2.141 tree.h
> --- tree.h 27 Nov 2003 04:01:03 -0000 1.342.2.141
> +++ tree.h 2 Dec 2003 04:02:32 -0000
> @@ -3307,6 +3307,7 @@ extern tree invert_truthvalue (tree);
> extern tree nondestructive_fold_unary_to_constant (enum tree_code, tree, tree);
> extern tree nondestructive_fold_binary_to_constant (enum tree_code, tree, tree, tree);
> extern tree fold_read_from_constant_string (tree);
> +extern tree int_const_binop (enum tree_code, tree, tree, int);
>
> /* In builtins.c */
> extern tree fold_builtin (tree);