[PATCH] aarch64: prefer using csinv, csneg in zero extend contexts
authorAlex Coplan <alex.coplan@arm.com>
Mon, 11 May 2020 14:18:46 +0000 (15:18 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Mon, 11 May 2020 14:18:46 +0000 (15:18 +0100)
commitd572ad49217c09ca09e382774fdc6c407db4fc20
tree2ac5c7daf04199adf84fd3a406a8ead415ec738e
parentfa853214b8f62d9df04e9bd956d6a8f0e28fd5a7
[PATCH] aarch64: prefer using csinv, csneg in zero extend contexts

Given the C code:

unsigned long long inv(unsigned a, unsigned b, unsigned c)
{
  return a ? b : ~c;
}

Prior to this patch, AArch64 GCC at -O2 generates:

inv:
        cmp     w0, 0
        mvn     w2, w2
        csel    w0, w1, w2, ne
        ret

and after applying the patch, we get:

inv:
        cmp     w0, 0
        csinv   w0, w1, w2, ne
        ret

The new pattern also catches the optimization for the symmetric case where the
body of foo reads a ? ~b : c.

Similarly, with the following code:

unsigned long long neg(unsigned a, unsigned b, unsigned c)
{
  return a ? b : -c;
}

GCC at -O2 previously gave:

neg:
        cmp     w0, 0
        neg     w2, w2
        csel    w0, w1, w2, ne

but now gives:

neg:
        cmp     w0, 0
        csneg   w0, w1, w2, ne
        ret

with the corresponding code for the symmetric case as above.

2020-05-11  Alex Coplan  <alex.coplan@arm.com>

gcc/
* config/aarch64/aarch64.c (aarch64_if_then_else_costs): Add case
to correctly calculate cost for new pattern (*csinv3_uxtw_insn3).
* config/aarch64/aarch64.md (*csinv3_utxw_insn1): New.
(*csinv3_uxtw_insn2): New.
(*csinv3_uxtw_insn3): New.
* config/aarch64/iterators.md (neg_not_cs): New.

gcc/testsuite/
* gcc.target/aarch64/csinv-neg.c: New test.
gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/iterators.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/csinv-neg.c [new file with mode: 0644]