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.

Reply via email to