diff options
author | Richard Biener <rguenther@suse.de> | 2014-11-24 14:07:18 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2014-11-24 14:07:18 +0000 |
commit | 8403c2cf5f66758fc78a01a675b0d218fded0202 (patch) | |
tree | 67f5be1ec46132969be310c870c5591ebbadbab2 /gcc | |
parent | 34a4625c52673828ff9b1eac7f68b5d23b58c5f5 (diff) | |
download | gcc-8403c2cf5f66758fc78a01a675b0d218fded0202.zip gcc-8403c2cf5f66758fc78a01a675b0d218fded0202.tar.gz gcc-8403c2cf5f66758fc78a01a675b0d218fded0202.tar.bz2 |
re PR target/63679 ([AArch64] Failure to constant fold.)
2014-11-24 Richard Biener <rguenther@suse.de>
PR tree-optimization/63679
* tree-ssa-sccvn.c: Include ipa-ref.h, plugin-api.h and cgraph.h.
(copy_reference_ops_from_ref): Fix non-constant ADDR_EXPR case
to properly leave off at -1.
(fully_constant_vn_reference_p): Generalize folding from
constant initializers.
(vn_reference_lookup_3): When looking through aggregate copies
handle offsetted reads and try simplifying the result to
a constant.
* gimple-fold.h (fold_ctor_reference): Export.
* gimple-fold.c (fold_ctor_reference): Likewise.
* gcc.dg/tree-ssa/ssa-fre-42.c: New testcase.
* gcc.dg/tree-ssa/20030807-5.c: Avoid folding read from global to zero.
* gcc.target/i386/ssetype-1.c: Likewise.
* gcc.target/i386/ssetype-3.c: Likewise.
* gcc.target/i386/ssetype-5.c: Likewise.
From-SVN: r218019
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/gimple-fold.c | 6 | ||||
-rw-r--r-- | gcc/gimple-fold.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/20030807-5.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-42.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/ssetype-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/ssetype-3.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/ssetype-5.c | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.c | 116 |
10 files changed, 159 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e362f1d..cadd82f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2014-11-24 Richard Biener <rguenther@suse.de> + + PR tree-optimization/63679 + * tree-ssa-sccvn.c: Include ipa-ref.h, plugin-api.h and cgraph.h. + (copy_reference_ops_from_ref): Fix non-constant ADDR_EXPR case + to properly leave off at -1. + (fully_constant_vn_reference_p): Generalize folding from + constant initializers. + (vn_reference_lookup_3): When looking through aggregate copies + handle offsetted reads and try simplifying the result to + a constant. + * gimple-fold.h (fold_ctor_reference): Export. + * gimple-fold.c (fold_ctor_reference): Likewise. + 2014-11-24 Petr Murzin <petr.murzin@intel.com> * simplify-rtx.c (simplify_ternary_operation): Simplify diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 91b9b0c..98ec117 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -4788,10 +4788,6 @@ gimple_fold_stmt_to_constant (gimple stmt, tree (*valueize) (tree)) /* The following set of functions are supposed to fold references using their constant initializers. */ -static tree fold_ctor_reference (tree type, tree ctor, - unsigned HOST_WIDE_INT offset, - unsigned HOST_WIDE_INT size, tree); - /* See if we can find constructor defining value of BASE. When we know the consructor with constant offset (such as base is array[40] and we do know constructor of array), then @@ -5027,7 +5023,7 @@ fold_nonarray_ctor_reference (tree type, tree ctor, /* CTOR is value initializing memory, fold reference of type TYPE and size SIZE to the memory at bit OFFSET. */ -static tree +tree fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size, tree from_decl) { diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h index a38848f..7574de8 100644 --- a/gcc/gimple-fold.h +++ b/gcc/gimple-fold.h @@ -39,6 +39,8 @@ extern tree follow_single_use_edges (tree); extern tree gimple_fold_stmt_to_constant_1 (gimple, tree (*) (tree), tree (*) (tree) = no_follow_ssa_edges); extern tree gimple_fold_stmt_to_constant (gimple, tree (*) (tree)); +extern tree fold_ctor_reference (tree, tree, unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT, tree); extern tree fold_const_aggregate_ref_1 (tree, tree (*) (tree)); extern tree fold_const_aggregate_ref (tree); extern tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a9ac86b..7db895b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2014-11-24 Richard Biener <rguenther@suse.de> + + PR tree-optimization/63679 + * gcc.dg/tree-ssa/ssa-fre-42.c: New testcase. + * gcc.dg/tree-ssa/20030807-5.c: Avoid folding read from global to zero. + * gcc.target/i386/ssetype-1.c: Likewise. + * gcc.target/i386/ssetype-3.c: Likewise. + * gcc.target/i386/ssetype-5.c: Likewise. + 2014-11-24 Jonathan Wakely <jwakely@redhat.com> Paolo Carlini <paolo.carlini@oracle.com> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-5.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-5.c index 424b558..23976441 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20030807-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-5.c @@ -13,7 +13,7 @@ struct rtx_def unsigned int unchanging:1; }; -static rtx current_sym_addr; +rtx current_sym_addr; int foo () diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-42.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-42.c new file mode 100644 index 0000000..c90bb0d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-42.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-require-alias "" } */ +/* { dg-options "-O -fdump-tree-fre1" } */ + +extern void abort (void); + +struct X { int a[128]; }; +static const struct X a = { 0, 1, 2, 3 }; +/* Prevent gimplify_modify_expr_rhs / gimplify_init_constructor from + expanding the aggregate copy below inline. */ +static const struct X A __attribute__((alias("a"))); +struct X *q; +int __attribute__((noinline)) +foo () +{ + struct X b = A; + int *p = &b.a[2]; + /* Prevent SRA from decomposing b. */ + q = &b; + return *p; +} + +int main() +{ + if (foo() != 2) + abort (); + return 0; +} + +/* Verify the aggregate copy we want to look through is still in place. */ +/* { dg-final { scan-tree-dump "b = A;" "fre1" } } */ +/* Verify we have propagated the element read all the way to the return. */ +/* { dg-final { scan-tree-dump "return 2" "fre1" } } */ +/* { dg-final { cleanup-tree-dump "fre1" } } */ diff --git a/gcc/testsuite/gcc.target/i386/ssetype-1.c b/gcc/testsuite/gcc.target/i386/ssetype-1.c index 36dcaf6..34185dd 100644 --- a/gcc/testsuite/gcc.target/i386/ssetype-1.c +++ b/gcc/testsuite/gcc.target/i386/ssetype-1.c @@ -14,7 +14,7 @@ #include <xmmintrin.h> -static __m128d magic_a, magic_b; +__m128d magic_a, magic_b; __m128d t1(void) diff --git a/gcc/testsuite/gcc.target/i386/ssetype-3.c b/gcc/testsuite/gcc.target/i386/ssetype-3.c index d6887d5..c2eff2b 100644 --- a/gcc/testsuite/gcc.target/i386/ssetype-3.c +++ b/gcc/testsuite/gcc.target/i386/ssetype-3.c @@ -13,7 +13,7 @@ #include <xmmintrin.h> -static __m128 magic_a, magic_b; +__m128 magic_a, magic_b; __m128 t1(void) { diff --git a/gcc/testsuite/gcc.target/i386/ssetype-5.c b/gcc/testsuite/gcc.target/i386/ssetype-5.c index bc903f5..2dd2de4 100644 --- a/gcc/testsuite/gcc.target/i386/ssetype-5.c +++ b/gcc/testsuite/gcc.target/i386/ssetype-5.c @@ -13,7 +13,7 @@ /* Verify that we generate proper instruction with memory operand. */ #include <xmmintrin.h> -static __m128i magic_a, magic_b; +__m128i magic_a, magic_b; __m128i t1(void) { diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index aa155a8..8b3f2c7 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -65,6 +65,9 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-sccvn.h" #include "tree-cfg.h" #include "domwalk.h" +#include "ipa-ref.h" +#include "plugin-api.h" +#include "cgraph.h" /* This algorithm is based on the SCC algorithm presented by Keith Cooper and L. Taylor Simpson in "SCC-Based Value numbering" @@ -920,7 +923,7 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result) temp.op0 = ref; break; } - /* Fallthrough. */ + break; /* These are only interesting for their operands, their existence, and their type. They will never be the last ref in the chain of references (IE they require an @@ -1325,24 +1328,66 @@ fully_constant_vn_reference_p (vn_reference_t ref) } } - /* Simplify reads from constant strings. */ - else if (op->opcode == ARRAY_REF - && TREE_CODE (op->op0) == INTEGER_CST - && integer_zerop (op->op1) - && operands.length () == 2) + /* Simplify reads from constants or constant initializers. */ + else if (BITS_PER_UNIT == 8 + && is_gimple_reg_type (ref->type) + && (!INTEGRAL_TYPE_P (ref->type) + || TYPE_PRECISION (ref->type) % BITS_PER_UNIT == 0)) { - vn_reference_op_t arg0; - arg0 = &operands[1]; - if (arg0->opcode == STRING_CST - && (TYPE_MODE (op->type) - == TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0->op0)))) - && GET_MODE_CLASS (TYPE_MODE (op->type)) == MODE_INT - && GET_MODE_SIZE (TYPE_MODE (op->type)) == 1 - && tree_int_cst_sgn (op->op0) >= 0 - && compare_tree_int (op->op0, TREE_STRING_LENGTH (arg0->op0)) < 0) - return build_int_cst_type (op->type, - (TREE_STRING_POINTER (arg0->op0) - [TREE_INT_CST_LOW (op->op0)])); + HOST_WIDE_INT off = 0; + HOST_WIDE_INT size = tree_to_shwi (TYPE_SIZE (ref->type)); + if (size % BITS_PER_UNIT != 0 + || size > MAX_BITSIZE_MODE_ANY_MODE) + return NULL_TREE; + size /= BITS_PER_UNIT; + unsigned i; + for (i = 0; i < operands.length (); ++i) + { + if (operands[i].off == -1) + return NULL_TREE; + off += operands[i].off; + if (operands[i].opcode == MEM_REF) + { + ++i; + break; + } + } + vn_reference_op_t base = &operands[--i]; + tree ctor = error_mark_node; + tree decl = NULL_TREE; + if (TREE_CODE_CLASS (base->opcode) == tcc_constant) + ctor = base->op0; + else if (base->opcode == MEM_REF + && base[1].opcode == ADDR_EXPR + && (TREE_CODE (TREE_OPERAND (base[1].op0, 0)) == VAR_DECL + || TREE_CODE (TREE_OPERAND (base[1].op0, 0)) == CONST_DECL)) + { + decl = TREE_OPERAND (base[1].op0, 0); + ctor = ctor_for_folding (decl); + } + if (ctor == NULL_TREE) + return build_zero_cst (ref->type); + else if (ctor != error_mark_node) + { + if (decl) + { + tree res = fold_ctor_reference (ref->type, ctor, + off * BITS_PER_UNIT, + size * BITS_PER_UNIT, decl); + if (res) + { + STRIP_USELESS_TYPE_CONVERSION (res); + if (is_gimple_min_invariant (res)) + return res; + } + } + else + { + unsigned char buf[MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT]; + if (native_encode_expr (ctor, buf, size, off) > 0) + return native_interpret_expr (ref->type, buf, size); + } + } } return NULL_TREE; @@ -1850,11 +1895,20 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, may fail when comparing types for compatibility. But we really don't care here - further lookups with the rewritten operands will simply fail if we messed up types too badly. */ + HOST_WIDE_INT extra_off = 0; if (j == 0 && i >= 0 && lhs_ops[0].opcode == MEM_REF - && lhs_ops[0].off != -1 - && (lhs_ops[0].off == vr->operands[i].off)) - i--, j--; + && lhs_ops[0].off != -1) + { + if (lhs_ops[0].off == vr->operands[i].off) + i--, j--; + else if (vr->operands[i].opcode == MEM_REF + && vr->operands[i].off != -1) + { + extra_off = vr->operands[i].off - lhs_ops[0].off; + i--, j--; + } + } /* i now points to the first additional op. ??? LHS may not be completely contained in VR, one or more @@ -1865,6 +1919,20 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, /* Now re-write REF to be based on the rhs of the assignment. */ copy_reference_ops_from_ref (gimple_assign_rhs1 (def_stmt), &rhs); + + /* Apply an extra offset to the inner MEM_REF of the RHS. */ + if (extra_off != 0) + { + if (rhs.length () < 2 + || rhs[0].opcode != MEM_REF + || rhs[0].off == -1) + return (void *)-1; + rhs[0].off += extra_off; + rhs[0].op0 = int_const_binop (PLUS_EXPR, rhs[0].op0, + build_int_cst (TREE_TYPE (rhs[0].op0), + extra_off)); + } + /* We need to pre-pend vr->operands[0..i] to rhs. */ vec<vn_reference_op_s> old = vr->operands; if (i + 1 + rhs.length () > vr->operands.length ()) @@ -1882,6 +1950,12 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, shared_lookup_references = vr->operands; vr->hashcode = vn_reference_compute_hash (vr); + /* Try folding the new reference to a constant. */ + tree val = fully_constant_vn_reference_p (vr); + if (val) + return vn_reference_lookup_or_insert_for_pieces + (vuse, vr->set, vr->type, vr->operands, val); + /* Adjust *ref from the new operands. */ if (!ao_ref_init_from_vn_reference (&r, vr->set, vr->type, vr->operands)) return (void *)-1; |