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.