aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Chupin <pavel.v.chupin@intel.com>2012-11-01 16:11:23 +0400
committerPavel Chupin <pavel.v.chupin@intel.com>2012-11-01 17:40:38 +0400
commit6d08dc702e910635ad2a49e40b0b7e34f4f2090a (patch)
treef91fd07ee927d2a9d04f3fae7740f94ddf29f54e
parentefb5994e8cb17f9b2347baff9d731af0338e5d5e (diff)
downloadtoolchain_gcc-6d08dc702e910635ad2a49e40b0b7e34f4f2090a.tar.gz
toolchain_gcc-6d08dc702e910635ad2a49e40b0b7e34f4f2090a.tar.bz2
toolchain_gcc-6d08dc702e910635ad2a49e40b0b7e34f4f2090a.zip
Fix dom optimization which removes goto in dalvik dexopt
Can be seen in logcat by messages: E dalvikvm: Out-of-order map item: 0 then 0x70 E dalvikvm: ERROR: Byte swap + verify failed BZ: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54985 Backport r192745 and children r192746, r192754, r192852: 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. Change-Id: I45e0185b1b729de91749272d62d3d331fcf1cf71 Signed-off-by: Pavel Chupin <pavel.v.chupin@intel.com>
-rw-r--r--gcc-4.7/gcc/testsuite/gcc.c-torture/execute/pr54985.c36
-rw-r--r--gcc-4.7/gcc/tree-ssa-threadedge.c72
2 files changed, 89 insertions, 19 deletions
diff --git a/gcc-4.7/gcc/testsuite/gcc.c-torture/execute/pr54985.c b/gcc-4.7/gcc/testsuite/gcc.c-torture/execute/pr54985.c
new file mode 100644
index 000000000..678c9f47a
--- /dev/null
+++ b/gcc-4.7/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-4.7/gcc/tree-ssa-threadedge.c b/gcc-4.7/gcc/tree-ssa-threadedge.c
index 707c8df3e..81bf73de6 100644
--- a/gcc-4.7/gcc/tree-ssa-threadedge.c
+++ b/gcc-4.7/gcc/tree-ssa-threadedge.c
@@ -574,6 +574,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)
+{
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ gimple last = last_stmt(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
@@ -707,19 +745,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))
+ goto fail;
}
stmt_count = 0;
@@ -760,7 +787,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)))
{
/* We don't want to thread back to a block we have already
visited. This may be overly conservative. */
@@ -818,11 +847,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))
+ e2 = thread_around_empty_block (e3,
+ dummy_cond,
+ handle_dominating_asserts,
+ simplify,
+ visited);
+ else
+ e2 = NULL;
+
if (e2)
{
e3 = e2;