]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-ssa-forwprop.c (simplify_gimple_switch): Enhance check for which sign-changes...
authorRichard Biener <rguenther@suse.de>
Mon, 14 Apr 2014 13:53:35 +0000 (13:53 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 14 Apr 2014 13:53:35 +0000 (13:53 +0000)
2014-04-14  Richard Biener  <rguenther@suse.de>

* tree-ssa-forwprop.c (simplify_gimple_switch): Enhance
check for which sign-changes we allow when forwarding
a converted value into a switch.

* g++.dg/tree-ssa/forwprop-switch.C: New testcase.

From-SVN: r209372

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C [new file with mode: 0644]
gcc/tree-ssa-forwprop.c

index 0bec304d1f7dce523b5fc8e051f950f847567109..724c5f532a0bac657c6c7317980be2a49935af6b 100644 (file)
@@ -1,3 +1,9 @@
+2014-04-14  Richard Biener  <rguenther@suse.de>
+
+       * tree-ssa-forwprop.c (simplify_gimple_switch): Enhance
+       check for which sign-changes we allow when forwarding
+       a converted value into a switch.
+
 2014-04-14  Eric Botcazou  <ebotcazou@adacore.com>
 
        * stor-layout.c (place_field): Finalize non-constant offset for the
index eb30db9ca01a37d793eef6a6662330a442681bfd..0a741fb0b68cfd5dabc32ac1dfd69f696601170c 100644 (file)
@@ -1,3 +1,7 @@
+2014-04-14  Richard Biener  <rguenther@suse.de>
+
+       * g++.dg/tree-ssa/forwprop-switch.C: New testcase.
+
 2014-04-14  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * gcc.dg/lto/pr55113_0.c: Skip on i?86-*-solaris2.1[0-1]*.
diff --git a/gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C b/gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C
new file mode 100644 (file)
index 0000000..c3f12ac
--- /dev/null
@@ -0,0 +1,24 @@
+// { dg-do compile }
+// { dg-options "-O -fdump-tree-cddce1" }
+
+enum Scale  { E1, E2, E3, E4, E5, E6, E7, E8 };
+
+int Test(Scale s)
+{ 
+  switch(s)
+    {
+      case E1: return 12;
+      case E2: return 17;
+      case E3: return 22;
+      case E4: return 42;
+      default:  break;
+    }
+  return 0;
+}
+
+// tree forwprop should have eliminated the (int) s cast for the
+// switch value and directly switch on the 's' parameter
+
+// { dg-final { scan-tree-dump-not "\\\(int\\\)" "cddce1" } }
+// { dg-final { scan-tree-dump "switch \\\(s_.\\\(D\\\)\\\)" "cddce1" } }
+// { dg-final { cleanup-tree-dump "cddce1" } }
index b2294290077875416eea378af5a60e0ee294cc10..b6bedfea6d7f6d39d2a517538656ddf386817029 100644 (file)
@@ -1356,43 +1356,38 @@ simplify_gimple_switch_label_vec (gimple stmt, tree index_type)
 static bool
 simplify_gimple_switch (gimple stmt)
 {
-  tree cond = gimple_switch_index (stmt);
-  tree def, to, ti;
-  gimple def_stmt;
-
   /* The optimization that we really care about is removing unnecessary
      casts.  That will let us do much better in propagating the inferred
      constant at the switch target.  */
+  tree cond = gimple_switch_index (stmt);
   if (TREE_CODE (cond) == SSA_NAME)
     {
-      def_stmt = SSA_NAME_DEF_STMT (cond);
-      if (is_gimple_assign (def_stmt))
+      gimple def_stmt = SSA_NAME_DEF_STMT (cond);
+      if (gimple_assign_cast_p (def_stmt))
        {
-         if (gimple_assign_rhs_code (def_stmt) == NOP_EXPR)
-           {
-             int need_precision;
-             bool fail;
-
-             def = gimple_assign_rhs1 (def_stmt);
-
-             to = TREE_TYPE (cond);
-             ti = TREE_TYPE (def);
-
-             /* If we have an extension that preserves value, then we
-                can copy the source value into the switch.  */
-
-             need_precision = TYPE_PRECISION (ti);
-             fail = false;
-             if (! INTEGRAL_TYPE_P (ti))
-               fail = true;
-             else if (TYPE_UNSIGNED (to) && !TYPE_UNSIGNED (ti))
-               fail = true;
-             else if (!TYPE_UNSIGNED (to) && TYPE_UNSIGNED (ti))
-               need_precision += 1;
-             if (TYPE_PRECISION (to) < need_precision)
-               fail = true;
+         tree def = gimple_assign_rhs1 (def_stmt);
+         if (TREE_CODE (def) != SSA_NAME)
+           return false;
 
-             if (!fail)
+         /* If we have an extension or sign-change that preserves the
+            values we check against then we can copy the source value into
+            the switch.  */
+         tree ti = TREE_TYPE (def);
+         if (INTEGRAL_TYPE_P (ti)
+             && TYPE_PRECISION (ti) <= TYPE_PRECISION (TREE_TYPE (cond)))
+           {
+             size_t n = gimple_switch_num_labels (stmt);
+             tree min = NULL_TREE, max = NULL_TREE;
+             if (n > 1)
+               {
+                 min = CASE_LOW (gimple_switch_label (stmt, 1));
+                 if (CASE_HIGH (gimple_switch_label (stmt, n - 1)))
+                   max = CASE_HIGH (gimple_switch_label (stmt, n - 1));
+                 else
+                   max = CASE_LOW (gimple_switch_label (stmt, n - 1));
+               }
+             if ((!min || int_fits_type_p (min, ti))
+                 && (!max || int_fits_type_p (max, ti)))
                {
                  gimple_switch_set_index (stmt, def);
                  simplify_gimple_switch_label_vec (stmt, ti);