tree-vrp.c (identify_jump_threads): Handle GIMPLE_SWITCH too.
authorJeff Law <law@redhat.com>
Mon, 25 Apr 2011 19:55:13 +0000 (13:55 -0600)
committerJeff Law <law@gcc.gnu.org>
Mon, 25 Apr 2011 19:55:13 +0000 (13:55 -0600)
* tree-vrp.c (identify_jump_threads): Handle GIMPLE_SWITCH too.

* gcc.dg/tree-ssa/vrp56.c: new test.

From-SVN: r172938

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/vrp56.c [new file with mode: 0644]
gcc/tree-vrp.c

index bc726797d340d2f721cf6f69e263e6b739f71dda..cacaee64891395ae8bf839944f618e872a7d6620 100644 (file)
@@ -1,3 +1,7 @@
+2011-04-25  Jeff Law  <law@redhat.com>
+
+       * tree-vrp.c (identify_jump_threads): Handle GIMPLE_SWITCH too.
+
 2011-04-25  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * system.h (ENUM_BITFIELD): Remove.
index 1f6640c2a31e4151ef204478b214d302cda0aae3..793c8266ca467485c247dbbb51b4f44feb436362 100644 (file)
@@ -1,3 +1,7 @@
+2011-04-25  Jeff Law <law@redhat.com>
+
+       * gcc.dg/tree-ssa/vrp56.c: new test.
+
 2011-04-25  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * go.test/go-test.exp (go-set-goarch): Accept mips*-*-*.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp56.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp56.c
new file mode 100644 (file)
index 0000000..80f0b69
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do compile } */ 
+/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+typedef struct basic_block_def *basic_block;
+struct basic_block_def;
+struct edge_def;
+typedef struct edge_def *edge;
+typedef struct VEC_edge_base
+{
+  unsigned num;
+} VEC_edge_base;
+typedef struct VEC_edge_none
+{
+  VEC_edge_base base;
+} VEC_edge_none;
+static __inline__ unsigned
+VEC_edge_base_length (VEC_edge_base * vec_)
+{
+  return vec_ ? vec_->num : 0;
+}
+
+typedef struct VEC_edge_gc
+{
+  VEC_edge_base base;
+} VEC_edge_gc;
+struct basic_block_def
+{
+  VEC_edge_gc *succs;
+};
+
+unsigned char
+cleanup_empty_eh (basic_block bb)
+{
+  edge e_out;
+  switch (VEC_edge_base_length (&bb->succs->base))
+    {
+    case 1:
+       foo ();
+    }
+}
+/* { dg-final { scan-tree-dump-times "Threaded" 2 "vrp1"} } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
+
index 466c3a0f0da23a4c0783fbf9f00a63e3e8f24e1d..2d0af8725da365aeacad14e7ec4a9304b113fc25 100644 (file)
@@ -7555,25 +7555,25 @@ identify_jump_threads (void)
         may be some value in handling SWITCH_EXPR here, I doubt it's
         terribly important.  */
       last = gsi_stmt (gsi_last_bb (bb));
-      if (gimple_code (last) != GIMPLE_COND)
-       continue;
 
-      /* We're basically looking for any kind of conditional with
+      /* We're basically looking for a switch or any kind of conditional with
         integral or pointer type arguments.  Note the type of the second
         argument will be the same as the first argument, so no need to
         check it explicitly.  */
-      if (TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME
-         && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last)))
-             || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (last))))
-         && (TREE_CODE (gimple_cond_rhs (last)) == SSA_NAME
-             || is_gimple_min_invariant (gimple_cond_rhs (last))))
+      if (gimple_code (last) == GIMPLE_SWITCH
+         || (gimple_code (last) == GIMPLE_COND
+             && TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME
+             && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last)))
+                 || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (last))))
+             && (TREE_CODE (gimple_cond_rhs (last)) == SSA_NAME
+                 || is_gimple_min_invariant (gimple_cond_rhs (last)))))
        {
          edge_iterator ei;
 
          /* We've got a block with multiple predecessors and multiple
-            successors which also ends in a suitable conditional.  For
-            each predecessor, see if we can thread it to a specific
-            successor.  */
+            successors which also ends in a suitable conditional or
+            switch statement.  For each predecessor, see if we can thread
+            it to a specific successor.  */
          FOR_EACH_EDGE (e, ei, bb->preds)
            {
              /* Do not thread across back edges or abnormal edges