https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104280
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Priority|P3 |P1 Last reconfirmed| |2022-01-29 CC| |jakub at gcc dot gnu.org Status|UNCONFIRMED |NEW Ever confirmed|0 |1 --- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> --- To me this looks like a bug in gimple-fold.cc. The r12-6924-gc2b610e7c6c89fd4 simplifies _5 = 1 / c.0_4; into _5 = c.0_4 == 1; As it is unsigned division, that is perfectly fine. But then gimple-fold.cc's /* Try to canonicalize for boolean-typed X the comparisons X == 0, X == 1, X != 0, and X != 1. */ if (gimple_assign_rhs_code (stmt) == EQ_EXPR || gimple_assign_rhs_code (stmt) == NE_EXPR) { tree lhs = gimple_assign_lhs (stmt); tree op1 = gimple_assign_rhs1 (stmt); tree op2 = gimple_assign_rhs2 (stmt); tree type = TREE_TYPE (op1); /* Check whether the comparison operands are of the same boolean type as the result type is. Check that second operand is an integer-constant with value one or zero. */ if (TREE_CODE (op2) == INTEGER_CST && (integer_zerop (op2) || integer_onep (op2)) && useless_type_conversion_p (TREE_TYPE (lhs), type)) { enum tree_code cmp_code = gimple_assign_rhs_code (stmt); bool is_logical_not = false; /* X == 0 and X != 1 is a logical-not.of X X == 1 and X != 0 is X */ if ((cmp_code == EQ_EXPR && integer_zerop (op2)) || (cmp_code == NE_EXPR && integer_onep (op2))) is_logical_not = true; if (is_logical_not == false) gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (op1), op1); /* Only for one-bit precision typed X the transformation !X -> ~X is valied. */ else if (TYPE_PRECISION (type) == 1) gimple_assign_set_rhs_with_ops (gsi, BIT_NOT_EXPR, op1); /* Otherwise we use !X -> X ^ 1. */ else gimple_assign_set_rhs_with_ops (gsi, BIT_XOR_EXPR, op1, build_int_cst (type, 1)); changed = true; break; } } kicks in and incorrectly "simplifies" it further into _5 = c.0_4; The comment talks about boolean type but nothing really checks that it is a boolean or precision 1 type, perhaps it expects that EQ_EXPR/NE_EXPR result must be boolean-ish, but that is not true. So, I think this optimization needs to be guarded on gimple_truth_valued_p (op1, valueize) but unfortunately while the function is not static inside of gimple-match.cc, it isn't declared in any header.