https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82062
--- Comment #13 from rguenther at suse dot de <rguenther at suse dot de> --- On Wed, 25 Oct 2017, ebotcazou at gcc dot gnu.org wrote: > 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. Ok if it passes bootstrap / regtest (with the testcase added of course).