match: fold a remainder compared with its dividend

A remainder of non-negative operands equals its dividend exactly when the
dividend is smaller than the divisor.  Comparing the two therefore does
not need the division at all.  This sits next to the (X / Y) == 0 rule,
which has the same shape and the same non-negativity requirement.

  int f (unsigned x, unsigned y) { return x % y == x; }

aarch64 -O2:

  before                          after
    udiv  w2, w0, w1                cmp   w0, w1
    msub  w2, w2, w1, w0            cset  w0, cc
    cmp   w2, w0
    cset  w0, eq

A zero divisor can raise a non-call exception.  Keep the division or
remainder when the divisor might be zero and non-call exceptions are
enabled.  Also keep an explicit zero divisor for diagnostics.

Bootstrapped and tested on aarch64-none-linux-gnu.

gcc/ChangeLog:

	* match.pd ((X / Y) ==/!= 0): Preserve a possible zero-divisor
	exception.
	((X % Y) ==/!= X): New simplification.  Preserve a possible
	zero-divisor exception.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/modcmp-1.c: New test.
	* gcc.dg/tree-ssa/modcmp-noncall-1.c: Likewise.

Signed-off-by: Kyrylo Tkachov <ktkachov@nvidia.com>
3 files changed