re PR middle-end/81814 (Incorrect behaviour at -O0 (conditional operator))
authorMarek Polacek <polacek@redhat.com>
Thu, 17 Aug 2017 14:33:13 +0000 (14:33 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Thu, 17 Aug 2017 14:33:13 +0000 (14:33 +0000)
PR middle-end/81814
* fold-const.c (operand_equal_for_comparison_p): Remove code that used
to mimic what shorten_compare did.  Change the return type to bool.
(fold_cond_expr_with_comparison): Update call to
operand_equal_for_comparison_p.
(fold_ternary_loc): Likewise.

* gcc.dg/torture/pr81814.c: New test.

From-SVN: r251152

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr81814.c [new file with mode: 0644]

index 2df218b93dafb81c79f6f6b39e93bc15808e3807..f8e24cd6e7a18e074e119a0355971ffe16d5688b 100644 (file)
@@ -1,3 +1,12 @@
+2017-08-17  Marek Polacek  <polacek@redhat.com>
+
+       PR middle-end/81814
+       * fold-const.c (operand_equal_for_comparison_p): Remove code that used
+       to mimic what shorten_compare did.  Change the return type to bool.
+       (fold_cond_expr_with_comparison): Update call to
+       operand_equal_for_comparison_p.
+       (fold_ternary_loc): Likewise.
+
 2017-08-17  Jackson Woodruff  <jackson.woodruff@arm.com>
 
        * aarch64-simd.md (mov<mode>): No longer force zero immediate into
index 0a5b168c3200168c04bc313eca53f56d313bf8f6..fef9b1a707a89b0b420f04e9dfdda6514510c226 100644 (file)
@@ -113,7 +113,6 @@ static tree negate_expr (tree);
 static tree associate_trees (location_t, tree, tree, enum tree_code, tree);
 static enum comparison_code comparison_to_compcode (enum tree_code);
 static enum tree_code compcode_to_comparison (enum comparison_code);
-static int operand_equal_for_comparison_p (tree, tree, tree);
 static int twoval_comparison_p (tree, tree *, tree *, int *);
 static tree eval_subst (location_t, tree, tree, tree, tree, tree);
 static tree optimize_bit_field_compare (location_t, enum tree_code,
@@ -3365,60 +3364,27 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 #undef OP_SAME_WITH_NULL
 }
 \f
-/* Similar to operand_equal_p, but see if ARG0 might have been made by
-   shorten_compare from ARG1 when ARG1 was being compared with OTHER.
+/* Similar to operand_equal_p, but strip nops first.  */
 
-   When in doubt, return 0.  */
-
-static int
-operand_equal_for_comparison_p (tree arg0, tree arg1, tree other)
+static bool
+operand_equal_for_comparison_p (tree arg0, tree arg1)
 {
-  int unsignedp1, unsignedpo;
-  tree primarg0, primarg1, primother;
-  unsigned int correct_width;
-
   if (operand_equal_p (arg0, arg1, 0))
-    return 1;
+    return true;
 
   if (! INTEGRAL_TYPE_P (TREE_TYPE (arg0))
       || ! INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
-    return 0;
+    return false;
 
   /* 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.  */
-  primarg0 = arg0, primarg1 = arg1;
-  STRIP_NOPS (primarg0);
-  STRIP_NOPS (primarg1);
-  if (operand_equal_p (primarg0, primarg1, 0))
-    return 1;
-
-  /* Duplicate what shorten_compare does to ARG1 and see if that gives the
-     actual comparison operand, ARG0.
-
-     First throw away any conversions to wider types
-     already present in the operands.  */
-
-  primarg1 = get_narrower (arg1, &unsignedp1);
-  primother = get_narrower (other, &unsignedpo);
-
-  correct_width = TYPE_PRECISION (TREE_TYPE (arg1));
-  if (unsignedp1 == unsignedpo
-      && TYPE_PRECISION (TREE_TYPE (primarg1)) < correct_width
-      && TYPE_PRECISION (TREE_TYPE (primother)) < correct_width)
-    {
-      tree type = TREE_TYPE (arg0);
-
-      /* Make sure shorter operand is extended the right way
-        to match the longer operand.  */
-      primarg1 = fold_convert (signed_or_unsigned_type_for
-                              (unsignedp1, TREE_TYPE (primarg1)), primarg1);
-
-      if (operand_equal_p (arg0, fold_convert (type, primarg1), 0))
-       return 1;
-    }
+  STRIP_NOPS (arg0);
+  STRIP_NOPS (arg1);
+  if (operand_equal_p (arg0, arg1, 0))
+    return true;
 
-  return 0;
+  return false;
 }
 \f
 /* See if ARG is an expression that is either a comparison or is performing
@@ -5300,7 +5266,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
      expressions will be false, so all four give B.  The min()
      and max() versions would give a NaN instead.  */
   if (!HONOR_SIGNED_ZEROS (element_mode (type))
-      && operand_equal_for_comparison_p (arg01, arg2, arg00)
+      && operand_equal_for_comparison_p (arg01, arg2)
       /* Avoid these transformations if the COND_EXPR may be used
         as an lvalue in the C++ front-end.  PR c++/19199.  */
       && (in_gimple_form
@@ -11357,8 +11323,7 @@ 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, TREE_OPERAND (arg0, 1))
+         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), arg1)
          && !HONOR_SIGNED_ZEROS (element_mode (arg1)))
        {
          tem = fold_cond_expr_with_comparison (loc, type, arg0, op1, op2);
@@ -11367,9 +11332,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
        }
 
       if (COMPARISON_CLASS_P (arg0)
-         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
-                                            op2,
-                                            TREE_OPERAND (arg0, 1))
+         && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), op2)
          && !HONOR_SIGNED_ZEROS (element_mode (op2)))
        {
          location_t loc0 = expr_location_or (arg0, loc);
index 7c4270c9c98f22f735fdd1bf9f6c2407b44c95e5..68962aca05a22f75bc7f38514063453abeecaa7d 100644 (file)
@@ -1,3 +1,8 @@
+2017-08-17  Marek Polacek  <polacek@redhat.com>
+
+       PR middle-end/81814
+       * gcc.dg/torture/pr81814.c: New test.
+
 2017-08-17  Jackson Woodruff  <jackson.woodruff@arm.com>
 
        * gcc.target/aarch64/simd/vect_str_zero.c: New testcase.
diff --git a/gcc/testsuite/gcc.dg/torture/pr81814.c b/gcc/testsuite/gcc.dg/torture/pr81814.c
new file mode 100644 (file)
index 0000000..aaf7c7f
--- /dev/null
@@ -0,0 +1,36 @@
+/* PR middle-end/81814 */
+/* { dg-do run } */
+
+int
+main ()
+{
+  int i = 0x01000000;
+  int a;
+
+  a = ((signed char) i) != 0 ? 0 : (unsigned long long int) i;
+  if (a != 0x01000000)
+    __builtin_abort ();
+  a = ((signed short int) i) != 0 ? 0 : (unsigned long long int) i;
+  if (a != 0x01000000)
+    __builtin_abort ();
+  a = ((unsigned short int) i) != 0 ? 0 : (unsigned long long int) i;
+  if (a != 0x01000000)
+    __builtin_abort ();
+  a = ((unsigned char) i) != 0 ? 0 : (unsigned long long int) i;
+  if (a != 0x01000000)
+    __builtin_abort ();
+  a = ((signed char) i) == 0 ? (unsigned long long int) i : 0;
+  if (a != 0x01000000)
+    __builtin_abort ();
+  a = ((signed short int) i) == 0 ? (unsigned long long int) i : 0;
+  if (a != 0x01000000)
+    __builtin_abort ();
+  a = ((unsigned short int) i) == 0 ? (unsigned long long int) i : 0;
+  if (a != 0x01000000)
+    __builtin_abort ();
+  a = ((unsigned char) i) == 0 ? (unsigned long long int) i : 0;
+  if (a != 0x01000000)
+    __builtin_abort ();
+
+  return 0;
+}