https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784
--- Comment #10 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Qi Feng from comment #9)
> And there's another problem. Take `x > y && x != 0 --> x > y' for
> example, I would also like to do
>
> x < y && y != 0 --> x < y
> x != 0 && x > y --> x > y
> y != 0 && x < y --> x < y
>
> If the constant always comes in as the second operand is incorrect, these
> would have to be doubled.
>
> I tried to add :c to truth_andif, but got the `operation is not commutative'
> error. I also tried to make truth_andif commutative by modifying
> genmatch.c, but again, I don't know it well, afraid that I would break
> something.
>
> The patterns I wrote looks like:
>
> /* x > y && x != 0 --> x > y
> Only for unsigned x and y. */
> (simplify
> (truth_andif:c (gt@2 @0 @1) (ne @0 integer_zerop))
> (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@0))
> && INTEGRAL_TYPE_P (TREE_TYPE(@1)) && TYPE_UNSIGNED
> (TREE_TYPE(@1)))
> @2))
>
> I have to wrote 4 of this with minor modification for a single
> transformation. If there's better way to do it, please do leave a comment.
I think first of all you do _not_ want to use truth_andif since that
will only prevail iff x or y have side-effects. To match on GIMPLE
you want bit_and instead/as well since all truth_ stuff doesn't prevail there.
And obviously truth_andif is _not_ commutative. You can use :C if you
want to force it though. Both truth_and and bit_and are commutative.
So sth like
(for and (truth_and bit_and)
(for ltgtop (lt le)
(simplify
(and:c (ltgtop:c@2 @0 @1) (ne @0 integer_zerop))
(if (...)
@2)))
should cover all of
x < y && y != 0 --> x < y
x != 0 && x > y --> x > y
y != 0 && x < y --> x < y
x < y && y != 0 --> x < y
note that from
(and (lt:c@2 @0 @1) (ne @0 integer_zerop))
we generate
(and (lt@2 @0 @1) (ne @0 integer_zerop))
(and (gt@2 @1 @0) (ne @0 integer_zerop))
so :c will ensure the semantically same operation will be present with
swapped operands. As opposed to :C which would do lt@2 @1 @0.