aarch64: Fix subs_compare_2.c regression [PR100874]
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 15 Feb 2022 18:09:35 +0000 (18:09 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Tue, 15 Feb 2022 18:09:35 +0000 (18:09 +0000)
commit8e84b2b37a541b27feea69769fc314d534464ebd
tree9a14883947209d80f42453ac8c91ccfdce5090be
parent65df3aefaa6c0735bd46ffdc7b5018a8b4020ab8
aarch64: Fix subs_compare_2.c regression [PR100874]

subs_compare_2.c tests that we can use a SUBS+CSEL sequence for:

unsigned int
foo (unsigned int a, unsigned int b)
{
  unsigned int x = a - 4;
  if (a < 4)
    return x;
  else
    return 0;
}

As Andrew notes in the PR, this is effectively MIN (x, 4) - 4,
and it is now recognised as such by phiopt.  Previously it was
if-converted in RTL instead.

I tried to look for ways to generalise this to other situations
and to other ?:-style operations, not just max and min.  However,
for general ?: we tend to push an outer “- CST” into the arms of
the ?: -- at least if one of them simplifies -- so I didn't find
any useful abstraction.

This patch therefore adds a pattern specifically for
max/min(a,cst)-cst.  I'm not thrilled at having to do this,
but it seems like the least worst fix in the circumstances.
Also, max(a,cst)-cst for unsigned a is a useful saturating
subtraction idiom and so is arguably worth its own code
for that reason.

gcc/
PR target/100874
* config/aarch64/aarch64-protos.h (aarch64_maxmin_plus_const):
Declare.
* config/aarch64/aarch64.cc (aarch64_maxmin_plus_const): New function.
* config/aarch64/aarch64.md (*aarch64_minmax_plus): New pattern.

gcc/testsuite/
* gcc.target/aarch64/max_plus_1.c: New test.
* gcc.target/aarch64/max_plus_2.c: Likewise.
* gcc.target/aarch64/max_plus_3.c: Likewise.
* gcc.target/aarch64/max_plus_4.c: Likewise.
* gcc.target/aarch64/max_plus_5.c: Likewise.
* gcc.target/aarch64/max_plus_6.c: Likewise.
* gcc.target/aarch64/max_plus_7.c: Likewise.
* gcc.target/aarch64/min_plus_1.c: Likewise.
* gcc.target/aarch64/min_plus_2.c: Likewise.
* gcc.target/aarch64/min_plus_3.c: Likewise.
* gcc.target/aarch64/min_plus_4.c: Likewise.
* gcc.target/aarch64/min_plus_5.c: Likewise.
* gcc.target/aarch64/min_plus_6.c: Likewise.
* gcc.target/aarch64/min_plus_7.c: Likewise.
17 files changed:
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.cc
gcc/config/aarch64/aarch64.md
gcc/testsuite/gcc.target/aarch64/max_plus_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/max_plus_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/max_plus_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/max_plus_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/max_plus_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/max_plus_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/max_plus_7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/min_plus_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/min_plus_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/min_plus_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/min_plus_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/min_plus_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/min_plus_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/min_plus_7.c [new file with mode: 0644]