re PR tree-optimization/61839 (More optimize opportunity for VRP)
authorKugan Vivekanandarajah <kuganv@linaro.org>
Sat, 20 Aug 2016 01:18:09 +0000 (01:18 +0000)
committerKugan Vivekanandarajah <kugan@gcc.gnu.org>
Sat, 20 Aug 2016 01:18:09 +0000 (01:18 +0000)
gcc/testsuite/ChangeLog:

2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>

PR tree-optimization/61839
* gcc.dg/tree-ssa/pr61839_1.c: New test.
* gcc.dg/tree-ssa/pr61839_2.c: New test.
* gcc.dg/tree-ssa/pr61839_3.c: New test.
* gcc.dg/tree-ssa/pr61839_4.c: New test.

gcc/ChangeLog:

2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>

PR tree-optimization/61839
* tree-vrp.c (two_valued_val_range_p): New.
(simplify_stmt_using_ranges): Convert CST BINOP VAR where VAR is
two-valued to VAR == VAL1 ? (CST BINOP VAL1) : (CST BINOP VAL2).
Also Convert VAR BINOP CST where VAR is two-valued to
VAR == VAL1 ? (VAL1 BINOP CST) : (VAL2 BINOP CST).

From-SVN: r239637

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c [new file with mode: 0644]
gcc/tree-vrp.c

index 02c85f893f87942201331b88f753903b75034a0e..a9946a9134bd0a2ac0826a0ccdd73978133dcd26 100644 (file)
@@ -1,3 +1,12 @@
+2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>
+
+       PR tree-optimization/61839
+       * tree-vrp.c (two_valued_val_range_p): New.
+       (simplify_stmt_using_ranges): Convert CST BINOP VAR where VAR is
+       two-valued to VAR == VAL1 ? (CST BINOP VAL1) : (CST BINOP VAL2).
+       Also Convert VAR BINOP CST where VAR is two-valued to
+       VAR == VAL1 ? (VAL1 BINOP CST) : (VAL2 BINOP CST).
+
 2016-08-19  David Malcolm  <dmalcolm@redhat.com>
 
        * diagnostic-show-locus.c
index 91ea2788d4c1b8a70f4d98138be94caa285257bd..6201e0cf82d736dabbc3bf14a6abdda2852d2b2f 100644 (file)
@@ -1,3 +1,11 @@
+2016-08-20  Kugan Vivekanandarajah  <kuganv@linaro.org>
+
+       PR tree-optimization/61839
+       * gcc.dg/tree-ssa/pr61839_1.c: New test.
+       * gcc.dg/tree-ssa/pr61839_2.c: New test.
+       * gcc.dg/tree-ssa/pr61839_3.c: New test.
+       * gcc.dg/tree-ssa/pr61839_4.c: New test.
+
 2016-08-19  Joseph Myers  <joseph@codesourcery.com>
 
        PR c/32187
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c
new file mode 100644 (file)
index 0000000..9f8168a
--- /dev/null
@@ -0,0 +1,44 @@
+/* PR tree-optimization/61839.  */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized" } */
+/* { dg-require-effective-target int32plus } */
+
+__attribute__ ((noinline))
+int foo ()
+{
+  int a = -1;
+  volatile unsigned b = 1U;
+  int c = 1;
+  c = (a + 972195718) >> (1LU <= b);
+  if (c == 486097858)
+    ;
+  else
+    __builtin_abort ();
+  return 0;
+}
+
+__attribute__ ((noinline))
+int bar ()
+{
+  int a = -1;
+  volatile unsigned b = 1U;
+  int c = 1;
+  c = (a + 972195718) >> (b ? 2 : 3);
+  if (c == 243048929)
+    ;
+  else
+    __builtin_abort ();
+  return 0;
+}
+
+int main ()
+{
+  foo ();
+  bar ();
+}
+
+/* Scan for c = 972195717) >> [0, 1] in function foo.  */
+/* { dg-final { scan-tree-dump-times "486097858 : 972195717" 1  "vrp1" } } */
+/* Scan for c = 972195717) >> [2, 3] in function bar.  */
+/* { dg-final { scan-tree-dump-times "243048929 : 121524464" 2  "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "486097858" 0  "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c
new file mode 100644 (file)
index 0000000..ffa00a7
--- /dev/null
@@ -0,0 +1,54 @@
+/* PR tree-optimization/61839.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-require-effective-target int32plus } */
+
+__attribute__ ((noinline))
+int foo ()
+{
+  int a = -1;
+  volatile unsigned b = 1U;
+  int c = 1;
+  c = (a + 972195718) / (b ? 1 : 0);
+  if (c == 972195717)
+    ;
+  else
+    __builtin_abort ();
+  return 0;
+}
+
+__attribute__ ((noinline))
+int bar ()
+{
+  int a = -1;
+  volatile unsigned b = 1U;
+  int c = 1;
+  c = (a + 972195718) % (b ? 1 : 0);
+  if (c == 972195717)
+    ;
+  else
+    __builtin_abort ();
+  return 0;
+}
+
+__attribute__ ((noinline))
+int bar2 ()
+{
+  int a = -1;
+  volatile unsigned b = 1U;
+  int c = 1;
+  c = (a + 972195716) % (b ? 1 : 2);
+  if (c == 972195715)
+    ;
+  else
+    __builtin_abort ();
+  return 0;
+}
+
+
+/* Dont optimize 972195717 / 0 in function foo.  */
+/* { dg-final { scan-tree-dump-times "972195717 / _" 1  "vrp1" } } */
+/* Dont optimize 972195717 % 0 in function bar.  */
+/* { dg-final { scan-tree-dump-times "972195717 % _" 1 "vrp1" } } */
+/* Optimize in function bar2.  */
+/* { dg-final { scan-tree-dump-times "972195715 % _" 0 "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c
new file mode 100644 (file)
index 0000000..5ceb073
--- /dev/null
@@ -0,0 +1,26 @@
+/* PR tree-optimization/61839.  */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized" } */
+
+__attribute__ ((noinline))
+int foo (int a, unsigned b)
+{
+  int c = 1;
+  b =  a ? 12 : 13;
+  c = b << 8;
+  if (c == 3072)
+    ;
+  else
+    __builtin_abort ();
+  return 0;
+}
+
+int main ()
+{
+  volatile unsigned b = 1U;
+  foo (-1, b);
+}
+
+/* Scan for c [12, 13] << 8 in function foo.  */
+/* { dg-final { scan-tree-dump-times "3072 : 3328" 2  "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "3072" 0  "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c
new file mode 100644 (file)
index 0000000..5c026c8
--- /dev/null
@@ -0,0 +1,28 @@
+/* PR tree-optimization/61839.  */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized" } */
+/* { dg-require-effective-target int32plus } */
+
+__attribute__ ((noinline))
+int foo (int a, unsigned b)
+{
+  unsigned c = 1;
+  if (b >= 1 && b <= ((unsigned)(-1) - 1))
+    return 0;
+  c = b >> 4;
+  if (c == 268435455)
+    ;
+  else
+    __builtin_abort ();
+  return 0;
+}
+
+int main ()
+{
+  volatile unsigned b = (unsigned)(-1);
+  foo (-1, b);
+}
+
+/* Scan for ~[1, 4294967294] >> 4 in function foo.  */
+/* { dg-final { scan-tree-dump-times "0 : 268435455" 1  "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "268435455" 0  "optimized" } } */
index a8810134b317211f64f722b70cb0a894401da06a..d350a86c50cc314ad5ea3c09da18b4db45ad0696 100644 (file)
@@ -10036,6 +10036,40 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
   return true;
 }
 
+/* Return true if VAR is a two-valued variable.  Set a and b with the
+   two-values when it is true.  Return false otherwise.  */
+
+static bool
+two_valued_val_range_p (tree var, tree *a, tree *b)
+{
+  value_range *vr = get_value_range (var);
+  if ((vr->type != VR_RANGE
+       && vr->type != VR_ANTI_RANGE)
+      || TREE_CODE (vr->min) != INTEGER_CST
+      || TREE_CODE (vr->max) != INTEGER_CST)
+    return false;
+
+  if (vr->type == VR_RANGE
+      && wi::sub (vr->max, vr->min) == 1)
+    {
+      *a = vr->min;
+      *b = vr->max;
+      return true;
+    }
+
+  /* ~[TYPE_MIN + 1, TYPE_MAX - 1] */
+  if (vr->type == VR_ANTI_RANGE
+      && wi::sub (vr->min, vrp_val_min (TREE_TYPE (var))) == 1
+      && wi::sub (vrp_val_max (TREE_TYPE (var)), vr->max) == 1)
+    {
+      *a = vrp_val_min (TREE_TYPE (var));
+      *b = vrp_val_max (TREE_TYPE (var));
+      return true;
+    }
+
+  return false;
+}
+
 /* Simplify STMT using ranges if possible.  */
 
 static bool
@@ -10046,6 +10080,68 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
     {
       enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
       tree rhs1 = gimple_assign_rhs1 (stmt);
+      tree rhs2 = gimple_assign_rhs2 (stmt);
+      tree lhs = gimple_assign_lhs (stmt);
+      tree val1 = NULL_TREE, val2 = NULL_TREE;
+      use_operand_p use_p;
+      gimple *use_stmt;
+
+      /* Convert:
+        LHS = CST BINOP VAR
+        Where VAR is two-valued and LHS is used in GIMPLE_COND only
+        To:
+        LHS = VAR == VAL1 ? (CST BINOP VAL1) : (CST BINOP VAL2)
+
+        Also handles:
+        LHS = VAR BINOP CST
+        Where VAR is two-valued and LHS is used in GIMPLE_COND only
+        To:
+        LHS = VAR == VAL1 ? (VAL1 BINOP CST) : (VAL2 BINOP CST) */
+
+      if (TREE_CODE_CLASS (rhs_code) == tcc_binary
+         && INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+         && ((TREE_CODE (rhs1) == INTEGER_CST
+              && TREE_CODE (rhs2) == SSA_NAME)
+             || (TREE_CODE (rhs2) == INTEGER_CST
+                 && TREE_CODE (rhs1) == SSA_NAME))
+         && single_imm_use (lhs, &use_p, &use_stmt)
+         && gimple_code (use_stmt) == GIMPLE_COND)
+
+       {
+         tree new_rhs1 = NULL_TREE;
+         tree new_rhs2 = NULL_TREE;
+         tree cmp_var = NULL_TREE;
+
+         if (TREE_CODE (rhs2) == SSA_NAME
+             && two_valued_val_range_p (rhs2, &val1, &val2))
+           {
+             /* Optimize RHS1 OP [VAL1, VAL2].  */
+             new_rhs1 = int_const_binop (rhs_code, rhs1, val1);
+             new_rhs2 = int_const_binop (rhs_code, rhs1, val2);
+             cmp_var = rhs2;
+           }
+         else if (TREE_CODE (rhs1) == SSA_NAME
+                  && two_valued_val_range_p (rhs1, &val1, &val2))
+           {
+             /* Optimize [VAL1, VAL2] OP RHS2.  */
+             new_rhs1 = int_const_binop (rhs_code, val1, rhs2);
+             new_rhs2 = int_const_binop (rhs_code, val2, rhs2);
+             cmp_var = rhs1;
+           }
+
+         /* If we could not find two-vals or the optimzation is invalid as
+            in divide by zero, new_rhs1 / new_rhs will be NULL_TREE.  */
+         if (new_rhs1 && new_rhs2)
+           {
+             tree cond = build2 (EQ_EXPR, TREE_TYPE (cmp_var), cmp_var, val1);
+             gimple_assign_set_rhs_with_ops (gsi,
+                                             COND_EXPR, cond,
+                                             new_rhs1,
+                                             new_rhs2);
+             update_stmt (gsi_stmt (*gsi));
+             return true;
+           }
+       }
 
       switch (rhs_code)
        {