diff options
author | Martin Jambor <mjambor@suse.cz> | 2009-11-24 11:56:14 +0100 |
---|---|---|
committer | Martin Jambor <jamborm@gcc.gnu.org> | 2009-11-24 11:56:14 +0100 |
commit | 09f0dc451db76a059e097c7cd115d65a86dff66e (patch) | |
tree | 0794dd3cad6d264dc0489fcc003758e493444d8f /gcc | |
parent | 6c03662614375d5b608d27a46861229f372f29bf (diff) | |
download | gcc-09f0dc451db76a059e097c7cd115d65a86dff66e.zip gcc-09f0dc451db76a059e097c7cd115d65a86dff66e.tar.gz gcc-09f0dc451db76a059e097c7cd115d65a86dff66e.tar.bz2 |
re PR tree-optimization/42154 (Wrong code from (early) SRA)
2009-11-24 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/42154
* tree-sra.c (struct access): Added comments.
(sra_modify_expr): Build references to the old aggregate with
build_ref_for_offset instead of reusing access->expr.
(load_assign_lhs_subreplacements): Likewise.
* testsuite/gcc.c-torture/execute/pr42154.c: New test.
From-SVN: r154493
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr42154.c | 18 | ||||
-rw-r--r-- | gcc/tree-sra.c | 33 |
4 files changed, 57 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8ed02bd..d05e456 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2009-11-24 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/42154 + * tree-sra.c (struct access): Added comments. + (sra_modify_expr): Build references to the old aggregate with + build_ref_for_offset instead of reusing access->expr. + (load_assign_lhs_subreplacements): Likewise. + 2009-11-24 Uros Bizjak <ubizjak@gmail.com> * config/i386/i386.md (add<mode>3_carry): Change insn pattern diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 50c588c..7ad8ae9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-11-24 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/42154 + * gcc.c-torture/execute/pr42154.c: New test. + 2009-11-24 Janus Weil <janus@gcc.gnu.org> PR fortran/42045 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr42154.c b/gcc/testsuite/gcc.c-torture/execute/pr42154.c new file mode 100644 index 0000000..f78919d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr42154.c @@ -0,0 +1,18 @@ +struct A { char x[1]; }; +extern void abort (void); +void __attribute__((noinline,noclone)) +foo (struct A a) +{ + if (a.x[0] != 'a') + abort (); +} +int main () +{ + struct A a; + int i; + for (i = 0; i < 1; ++i) + a.x[i] = 'a'; + foo (a); + return 0; +} + diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index fe82d98..5203685 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -125,7 +125,9 @@ struct access HOST_WIDE_INT size; tree base; - /* Expression. */ + /* Expression. It is context dependent so do not use it to create new + expressions to access the original aggregate. See PR 42154 for a + testcase. */ tree expr; /* Type. */ tree type; @@ -2113,10 +2115,17 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write, gcc.c-torture/compile/20011217-1.c. */ if (!is_gimple_reg_type (type)) { - gimple stmt; + tree ref = access->base; + bool ok; + + ok = build_ref_for_offset (&ref, TREE_TYPE (ref), + access->offset, access->type, false); + gcc_assert (ok); + if (write) { - tree ref = unshare_expr (access->expr); + gimple stmt; + if (access->grp_partial_lhs) ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE, false, GSI_NEW_STMT); @@ -2125,10 +2134,12 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write, } else { + gimple stmt; + if (access->grp_partial_lhs) repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE, true, GSI_SAME_STMT); - stmt = gimple_build_assign (unshare_expr (access->expr), repl); + stmt = gimple_build_assign (ref, repl); gsi_insert_before (gsi, stmt, GSI_SAME_STMT); } } @@ -2227,8 +2238,6 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc, } else { - bool repl_found; - /* No suitable access on the right hand side, need to load from the aggregate. See if we have to update it first... */ if (*refreshed == SRA_UDH_NONE) @@ -2236,9 +2245,19 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc, lhs, old_gsi); if (*refreshed == SRA_UDH_LEFT) - rhs = unshare_expr (lacc->expr); + { + bool repl_found; + + rhs = lacc->base; + repl_found = build_ref_for_offset (&rhs, TREE_TYPE (rhs), + lacc->offset, lacc->type, + false); + gcc_assert (repl_found); + } else { + bool repl_found; + rhs = top_racc->base; repl_found = build_ref_for_offset (&rhs, TREE_TYPE (top_racc->base), |