tree-vrp.c (simplify_min_or_max_using_ranges): New.
authorNathan Sidwell <nathan@acm.org>
Wed, 12 Aug 2015 13:08:23 +0000 (13:08 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Wed, 12 Aug 2015 13:08:23 +0000 (13:08 +0000)
* tree-vrp.c (simplify_min_or_max_using_ranges): New.
(simplify_stmt_using_ranges): Simplify MIN and MAX exprs.

testsuite/
* gcc.dg/vrp-min-max-1.c: New.
* gcc.dg/vrp-min-max-2.c: New.

From-SVN: r226809

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vrp-min-max-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vrp-min-max-2.c [new file with mode: 0644]
gcc/tree-vrp.c

index 2e94a8d43dfa2fdd97a067fa713c1b48df6334ee..3869f671cd3fbfe40e884d85c1c4d070af796e95 100644 (file)
@@ -1,3 +1,8 @@
+2015-08-12  Nathan Sidwell  <nathan@acm.org>
+
+       * tree-vrp.c (simplify_min_or_max_using_ranges): New.
+       (simplify_stmt_using_ranges): Simplify MIN and MAX exprs.
+
 2015-08-12  Simon Dardis  <simon.dardis@imgtec.com>
 
        * config/mips/mips.c (mips_store_data_bypass_p): Bring code into
index 7bb63a5f4ac2aee7f7c770a2383cb54527ac4a31..b712e5f0e8bc2ebaa9161e457b43a61816c1891e 100644 (file)
@@ -1,3 +1,8 @@
+2015-08-12  Nathan Sidwell  <nathan@acm.org>
+
+       * gcc.dg/vrp-min-max-1.c: New.
+       * gcc.dg/vrp-min-max-2.c: New.
+
 2015-08-12  Richard Biener  <rguenther@suse.de>
 
        * gcc.dg/tree-ssa/ssa-fre-43.c: Adjust.
diff --git a/gcc/testsuite/gcc.dg/vrp-min-max-1.c b/gcc/testsuite/gcc.dg/vrp-min-max-1.c
new file mode 100644 (file)
index 0000000..270f2bb
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-mergephi2" } */
+
+int bar (void);
+
+int foo1 (int x, int y)
+{
+  if (y < 10) return bar ();
+  if (x > 9) return bar ();
+
+  return x < y ? x : y;
+}
+
+int foo2 (int x, int y)
+{
+  if (y < 10) return bar ();
+  if (x > 9) return bar ();
+
+  return x > y ? x : y;
+}
+
+/* We expect to optimiz min/max in VRP*/
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "mergephi2" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "mergephi2" } } */
+/* { dg-final { scan-tree-dump-not "MIN_EXPR" "vrp1" } } */
+/* { dg-final { scan-tree-dump-not "MAX_EXPR" "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/vrp-min-max-2.c b/gcc/testsuite/gcc.dg/vrp-min-max-2.c
new file mode 100644 (file)
index 0000000..a3ccc66
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp2" } */
+
+int Foo (int X)
+{
+  if (X < 0)
+    X = 0;
+  if (X > 191)
+    X = 191;
+
+  return X << 23;
+}
+
+/* We expect this min/max pair to survive.  */
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "vrp2" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "vrp2" } } */
index d51acaa52fc5fcccbc935b9d03e15bf273896c54..0439272b97d59b56cade5e6647e5bc38832c3178 100644 (file)
@@ -7466,7 +7466,8 @@ compare_names (enum tree_code comp, tree n1, tree n2,
   return NULL_TREE;
 }
 
-/* Helper function for vrp_evaluate_conditional_warnv.  */
+/* Helper function for vrp_evaluate_conditional_warnv & other
+   optimizers.  */
 
 static tree
 vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code,
@@ -9145,6 +9146,54 @@ simplify_div_or_mod_using_ranges (gimple stmt)
   return false;
 }
 
+/* Simplify a min or max if the ranges of the two operands are
+   disjoint.   Return true if we do simplify.  */
+
+static bool
+simplify_min_or_max_using_ranges (gimple stmt)
+{
+  tree op0 = gimple_assign_rhs1 (stmt);
+  tree op1 = gimple_assign_rhs2 (stmt);
+  bool sop = false;
+  tree val;
+
+  val = (vrp_evaluate_conditional_warnv_with_ops_using_ranges
+        (LE_EXPR, op0, op1, &sop));
+  if (!val)
+    {
+      sop = false;
+      val = (vrp_evaluate_conditional_warnv_with_ops_using_ranges
+            (LT_EXPR, op0, op1, &sop));
+    }
+
+  if (val)
+    {
+      if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
+       {
+         location_t location;
+
+         if (!gimple_has_location (stmt))
+           location = input_location;
+         else
+           location = gimple_location (stmt);
+         warning_at (location, OPT_Wstrict_overflow,
+                     "assuming signed overflow does not occur when "
+                     "simplifying %<min/max (X,Y)%> to %<X%> or %<Y%>");
+       }
+
+      /* VAL == TRUE -> OP0 < or <= op1
+        VAL == FALSE -> OP0 > or >= op1.  */
+      tree res = ((gimple_assign_rhs_code (stmt) == MAX_EXPR)
+                 == integer_zerop (val)) ? op0 : op1;
+      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+      gimple_assign_set_rhs_from_tree (&gsi, res);
+      update_stmt (stmt);
+      return true;
+    }
+
+  return false;
+}
+
 /* If the operand to an ABS_EXPR is >= 0, then eliminate the
    ABS_EXPR.  If the operand is <= 0, then simplify the
    ABS_EXPR into a NEGATE_EXPR.  */
@@ -9987,6 +10036,11 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
            return simplify_float_conversion_using_ranges (gsi, stmt);
          break;
 
+       case MIN_EXPR:
+       case MAX_EXPR:
+         return simplify_min_or_max_using_ranges (stmt);
+         break;
+
        default:
          break;
        }