This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug middle-end/82062] [8 regression] simple conditional expressions no longer folded


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82062

--- Comment #11 from Eric Botcazou <ebotcazou at gcc dot gnu.org> ---
> Simplified but not equal - you are also stripping a possible truncation.
> I think the original code only ever stripped widening conversions.

Right, but IMO there is no real reason to distinguish the 2 cases now.

> It also had some additional constraints on the stripping looking
> at the other comparison operand (for some weird reason...).

I agree with your wording. :-)  I think it was supposed to deal with more
general cases of comparison X < (T1) Y ? (T2) X : (T2) Y.  My understanding is
that it's obsolete if we forbids non-NOPS conversions in the operands of the
comparison.

> I guess I'm ok with your proposed change if you restrict it to
> widening conversions (and use CONVERT_EXPR_P (arg1)).

Fair enough.  Here's what I'm going to test:

Index: fold-const.c
===================================================================
--- fold-const.c        (revision 254037)
+++ fold-const.c        (working copy)
@@ -3366,7 +3366,8 @@ operand_equal_p (const_tree arg0, const_
 #undef OP_SAME_WITH_NULL
 }

-/* 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 arg
   /* 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 t

          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)


The third hunk makes sure that we always pass the unstripped operand to the
predicate, as in the swapped case just below.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]