re PR middle-end/82062 (simple conditional expressions no longer folded)
authorEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 25 Oct 2017 21:53:21 +0000 (21:53 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 25 Oct 2017 21:53:21 +0000 (21:53 +0000)
PR middle-end/82062
* fold-const.c (operand_equal_for_comparison_p): Also return true
if ARG0 is a simple variant of ARG1 with narrower precision.
(fold_ternary_loc): Always pass unstripped operands to the predicate.

From-SVN: r254089

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/fold-cond-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/fold-cond-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/fold-cond_expr-1.c [deleted file]

index 5985d9ed8c9bd692c82589af349a6e1c3528c393..796a7e8cee9384823cd1500724f26f0288f85e99 100644 (file)
@@ -1,4 +1,11 @@
-2017-10-23  Jan Hubicka  <hubicka@ucw.cz>
+2017-10-25  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR middle-end/82062
+       * fold-const.c (operand_equal_for_comparison_p): Also return true
+       if ARG0 is a simple variant of ARG1 with narrower precision.
+       (fold_ternary_loc): Always pass unstripped operands to the predicate.
+
+2017-10-25  Jan Hubicka  <hubicka@ucw.cz>
 
        * i386.c (ix86_builtin_vectorization_cost): Compute scatter/gather
        cost correctly.
index c16959b84ace943d5be3ce18cca7df8f98f2e347..9db5aeb842583854fa5f85aba0d4f97d28f774e3 100644 (file)
@@ -3366,7 +3366,8 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 #undef OP_SAME_WITH_NULL
 }
 \f
-/* Similar to operand_equal_p, but strip nops first.  */
+/* Similar to operand_equal_p, but see if ARG0 might be a variant of ARG1
+   with a different signedness or a narrower precision.  */
 
 static bool
 operand_equal_for_comparison_p (tree arg0, tree arg1)
@@ -3381,9 +3382,20 @@ operand_equal_for_comparison_p (tree arg0, tree arg1)
   /* Discard any conversions that don't change the modes of ARG0 and ARG1
      and see if the inner values are the same.  This removes any
      signedness comparison, which doesn't matter here.  */
-  STRIP_NOPS (arg0);
-  STRIP_NOPS (arg1);
-  if (operand_equal_p (arg0, arg1, 0))
+  tree op0 = arg0;
+  tree op1 = arg1;
+  STRIP_NOPS (op0);
+  STRIP_NOPS (op1);
+  if (operand_equal_p (op0, op1, 0))
+    return true;
+
+  /* Discard a single widening conversion from ARG1 and see if the inner
+     value is the same as ARG0.  */
+  if (CONVERT_EXPR_P (arg1)
+      && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0)))
+      && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0)))
+         < TYPE_PRECISION (TREE_TYPE (arg1))
+      && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
     return true;
 
   return false;
@@ -11169,8 +11181,8 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
 
          Also try swapping the arguments and inverting the conditional.  */
       if (COMPARISON_CLASS_P (arg0)
-         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), arg1)
-         && !HONOR_SIGNED_ZEROS (element_mode (arg1)))
+         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), op1)
+         && !HONOR_SIGNED_ZEROS (element_mode (op1)))
        {
          tem = fold_cond_expr_with_comparison (loc, type, arg0, op1, op2);
          if (tem)
index 0e38439e12b84a0a5c0cc3159f58a93edd3beaed..443e7c7df0675d89d6fb93b5f518f4ac521a94ad 100644 (file)
@@ -1,3 +1,9 @@
+2017-10-25  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.dg/fold-cond_expr-1.c: Rename to...
+       * gcc.dg/fold-cond-2.c: ...this.
+       * gcc.dg/fold-cond-3.c: New test.
+
 2017-10-25  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/82436
diff --git a/gcc/testsuite/gcc.dg/fold-cond-2.c b/gcc/testsuite/gcc.dg/fold-cond-2.c
new file mode 100644 (file)
index 0000000..68ec754
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int
+min1 (signed char op1, signed char op2)
+{
+  return (op1 < 25) ? (int)op1 : 24;
+}
+int
+min2 (signed char op1, signed char op2)
+{
+  return (op1 <= 24) ? (int)op1 : 25;
+}
+int
+min3 (unsigned char op1, unsigned char op2)
+{
+  return (op1 < 25) ? (unsigned int)op1 : 24;
+}
+int
+min4 (unsigned char op1, unsigned char op2)
+{
+  return (op1 <= 24) ? (unsigned int)op1 : 25;
+}
+int
+max1 (signed char op1, signed char op2)
+{
+  return (op1 > 24) ? (int)op1 : 25;
+}
+int
+max2 (signed char op1, signed char op2)
+{
+  return (op1 >= 25) ? (int)op1 : 24;
+}
+int
+max3 (unsigned char op1, unsigned char op2)
+{
+  return (op1 > 24) ? (unsigned int)op1 : 25;
+}
+int
+max4 (unsigned char op1, unsigned char op2)
+{
+  return (op1 >= 25) ? (unsigned int)op1 : 24;
+}
+
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 4 "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/fold-cond-3.c b/gcc/testsuite/gcc.dg/fold-cond-3.c
new file mode 100644 (file)
index 0000000..fe0ba65
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-original" } */
+
+unsigned long f1 (int x)
+{
+  return x > 0 ? (unsigned long) x : 0;
+}
+
+unsigned long f2 (int x, int y)
+{
+  return x > y ? (unsigned long) x : (unsigned long) y;
+}
+
+unsigned long f3 (int x)
+{
+  return x < 0 ? (unsigned long) x : 0;
+}
+
+unsigned long f4 (int x, int y)
+{
+  return x < y ? (unsigned long) x : (unsigned long) y;
+}
+
+unsigned long f5 (unsigned int x, unsigned int y)
+{
+  return x > y ? (unsigned long) x : (unsigned long) y;
+}
+
+unsigned long f6 (unsigned int x, unsigned int y)
+{
+  return x < y ? (unsigned long) x : (unsigned long) y;
+}
+
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 3 "original"} } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "original"} } */
diff --git a/gcc/testsuite/gcc.dg/fold-cond_expr-1.c b/gcc/testsuite/gcc.dg/fold-cond_expr-1.c
deleted file mode 100644 (file)
index 68ec754..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
-
-int
-min1 (signed char op1, signed char op2)
-{
-  return (op1 < 25) ? (int)op1 : 24;
-}
-int
-min2 (signed char op1, signed char op2)
-{
-  return (op1 <= 24) ? (int)op1 : 25;
-}
-int
-min3 (unsigned char op1, unsigned char op2)
-{
-  return (op1 < 25) ? (unsigned int)op1 : 24;
-}
-int
-min4 (unsigned char op1, unsigned char op2)
-{
-  return (op1 <= 24) ? (unsigned int)op1 : 25;
-}
-int
-max1 (signed char op1, signed char op2)
-{
-  return (op1 > 24) ? (int)op1 : 25;
-}
-int
-max2 (signed char op1, signed char op2)
-{
-  return (op1 >= 25) ? (int)op1 : 24;
-}
-int
-max3 (unsigned char op1, unsigned char op2)
-{
-  return (op1 > 24) ? (unsigned int)op1 : 25;
-}
-int
-max4 (unsigned char op1, unsigned char op2)
-{
-  return (op1 >= 25) ? (unsigned int)op1 : 24;
-}
-
-/* { dg-final { scan-tree-dump-times "MIN_EXPR" 4 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "MAX_EXPR" 4 "optimized" } } */
-