[arm] Pattern match insns for a + ~b + Carry
authorRichard Earnshaw <rearnsha@arm.com>
Thu, 31 Oct 2019 16:04:53 +0000 (16:04 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Thu, 31 Oct 2019 16:04:53 +0000 (16:04 +0000)
commitd84b9ad53fed75590c3ebc6e38bd49db3b201128
treece3b64c8ef2a81cef3e94d237f672cb1df5004d4
parent946b4a68b3766ddbdb2290855c5167bd30c933a0
[arm] Pattern match insns for a + ~b + Carry

On ARM, the SBC instruction is defined as

  Ra - Rb - ~C

where C is the carry flag.  But -Rb = ~Rb + 1, so this is equivalent to

  Ra + ~Rb + 1 - ~C

which then simplifies to

  Ra + ~Rb + C

which is essentially an add-with-carry with one operand inverted.  We
can define RTL patterns to match this.  In thumb2 we can only match
when the operands are both registers, but in Arm state we can also use
RSC to match when Rn is either a constant or a shifted operand.

This overall simplifies some cases of 64-bit arithmetic, for example,

int64_t f (int64_t a, int64_t b) { return a + ~b; }

will now compile to

  MVN  R2, R2
  ADDS R0, R0, R2
  SBC  R1, R1, R3

* config/arm/arm.md (add_not_cin): New insn.
(add_not_shift_cin): Likewise.

From-SVN: r277676
gcc/ChangeLog
gcc/config/arm/arm.md