aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2012-10-23 14:33:49 -0600
committerJeff Law <law@gcc.gnu.org>2012-10-23 14:33:49 -0600
commitc0258754e4161f2603043d7dd17c397ce2a56d41 (patch)
tree51b0fc7c3eb6fb713379ff7a3369def5e9535c04 /gcc
parent44b94bdb07afe93c07763c89e8b8ed025fbbd200 (diff)
downloadgcc-c0258754e4161f2603043d7dd17c397ce2a56d41.zip
gcc-c0258754e4161f2603043d7dd17c397ce2a56d41.tar.gz
gcc-c0258754e4161f2603043d7dd17c397ce2a56d41.tar.bz2
re PR tree-optimization/54985 (dom optimization erroneous remove conditional goto.)
PR tree-optimization/54985 * tree-ssa-threadedge.c (cond_arg_set_in_bb): New function * extracted from thread_across_edge. (thread_across_edge): Use it in all cases where we might thread across a back edge. * gcc.c-torture/execute/pr54985.c: New test. From-SVN: r192745
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr54985.c36
-rw-r--r--gcc/tree-ssa-threadedge.c72
4 files changed, 101 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 89578c3..f75665e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2012-10-23 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/54985
+ * tree-ssa-threadedge.c (cond_arg_set_in_bb): New function extracted
+ from thread_across_edge.
+ (thread_across_edge): Use it in all cases where we might thread
+ across a back edge.
+
2012-10-23 Vladimir Makarov <vmakarov@redhat.com>
* lra-constraints.c (update_ebb_live_info): Process empty blocks.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 79ccb54..b9bee3f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2012-10-23 Jeff Law <law@redhat.com>
+
+ * gcc.c-torture/execute/pr54985.c: New test.
+
2012-10-23 Paul Koning <ni1d@arrl.net>
PR debug/54508
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr54985.c b/gcc/testsuite/gcc.c-torture/execute/pr54985.c
new file mode 100644
index 0000000..678c9f4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr54985.c
@@ -0,0 +1,36 @@
+
+typedef struct st {
+ int a;
+} ST;
+
+int __attribute__((noinline,noclone))
+foo(ST *s, int c)
+{
+ int first = 1;
+ int count = c;
+ ST *item = s;
+ int a = s->a;
+ int x;
+
+ while (count--)
+ {
+ x = item->a;
+ if (first)
+ first = 0;
+ else if (x >= a)
+ return 1;
+ a = x;
+ item++;
+ }
+ return 0;
+}
+
+extern void abort (void);
+
+int main ()
+{
+ ST _1[2] = {{2}, {1}};
+ if (foo(_1, 2) != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 105e3ab..1ffacae 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -572,6 +572,44 @@ simplify_control_stmt_condition (edge e,
return cached_lhs;
}
+/* Return TRUE if the statement at the end of e->dest depends on
+ the output of any statement in BB. Otherwise return FALSE.
+
+ This is used when we are threading a backedge and need to ensure
+ that temporary equivalences from BB do not affect the condition
+ in e->dest. */
+
+static bool
+cond_arg_set_in_bb (edge e, basic_block bb, int n)
+{
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ gimple last = gsi_stmt (gsi_last_bb (e->dest));
+
+ /* E->dest does not have to end with a control transferring
+ instruction. This can occurr when we try to extend a jump
+ threading opportunity deeper into the CFG. In that case
+ it is safe for this check to return false. */
+ if (!last)
+ return false;
+
+ if (gimple_code (last) != GIMPLE_COND
+ && gimple_code (last) != GIMPLE_GOTO
+ && gimple_code (last) != GIMPLE_SWITCH)
+ return false;
+
+ FOR_EACH_SSA_USE_OPERAND (use_p, last, iter, SSA_OP_USE | SSA_OP_VUSE)
+ {
+ tree use = USE_FROM_PTR (use_p);
+
+ if (TREE_CODE (use) == SSA_NAME
+ && gimple_code (SSA_NAME_DEF_STMT (use)) != GIMPLE_PHI
+ && gimple_bb (SSA_NAME_DEF_STMT (use)) == bb)
+ return true;
+ }
+ return false;
+}
+
/* TAKEN_EDGE represents the an edge taken as a result of jump threading.
See if we can thread around TAKEN_EDGE->dest as well. If so, return
the edge out of TAKEN_EDGE->dest that we can statically compute will be
@@ -705,19 +743,8 @@ thread_across_edge (gimple dummy_cond,
safe to thread this edge. */
if (e->flags & EDGE_DFS_BACK)
{
- ssa_op_iter iter;
- use_operand_p use_p;
- gimple last = gsi_stmt (gsi_last_bb (e->dest));
-
- FOR_EACH_SSA_USE_OPERAND (use_p, last, iter, SSA_OP_USE | SSA_OP_VUSE)
- {
- tree use = USE_FROM_PTR (use_p);
-
- if (TREE_CODE (use) == SSA_NAME
- && gimple_code (SSA_NAME_DEF_STMT (use)) != GIMPLE_PHI
- && gimple_bb (SSA_NAME_DEF_STMT (use)) == e->dest)
- goto fail;
- }
+ if (cond_arg_set_in_bb (e, e->dest, 1))
+ goto fail;
}
stmt_count = 0;
@@ -758,7 +785,9 @@ thread_across_edge (gimple dummy_cond,
address. If DEST is not null, then see if we can thread
through it as well, this helps capture secondary effects
of threading without having to re-run DOM or VRP. */
- if (dest)
+ if (dest
+ && ((e->flags & EDGE_DFS_BACK) == 0
+ || ! cond_arg_set_in_bb (taken_edge, e->dest, 2)))
{
/* We don't want to thread back to a block we have already
visited. This may be overly conservative. */
@@ -816,11 +845,16 @@ thread_across_edge (gimple dummy_cond,
e3 = taken_edge;
do
{
- e2 = thread_around_empty_block (e3,
- dummy_cond,
- handle_dominating_asserts,
- simplify,
- visited);
+ if ((e->flags & EDGE_DFS_BACK) == 0
+ || ! cond_arg_set_in_bb (e3, e->dest, 3))
+ e2 = thread_around_empty_block (e3,
+ dummy_cond,
+ handle_dominating_asserts,
+ simplify,
+ visited);
+ else
+ e2 = NULL;
+
if (e2)
{
e3 = e2;