This patch resolves PR target/43892 (suboptimal add with carry) by
adding four new define_insn_and_split to the rs6000 backend, that all
recognize pairs of instructions where the first instruction sets the
carry flag and the second one consumes it. It also adds a commutative
variant of add<mode>3_carry_in_0 (aka "addze") to catch cases, not
caught by recog's insn canonicalization, where CA_REG appears first.
For the add32carry function in the original PR:
unsigned int add32carry(unsigned int sum, unsigned int x)
{
unsigned int z = sum + x;
if (sum + x < x)
z++;
return z;
}
previously "-O2 -m32" would generate:
add32carry:
add 3,3,4
subfc 4,4,3
subfe 9,9,9
subf 3,9,3
blr
with this patch we now generate:
add32carry:
addc 3,3,4
addze 3,3
blr
And for the related examples in the new test case,
unsigned long add_leu(unsigned long a, unsigned long b, unsigned long c) {
return a + (b <= c);
}
unsigned long add_geu(unsigned long a, unsigned long b, unsigned long c) {
return a + (b >= c);
}
On powerpc64 with -O2 we'd previously generate:
add_leu:
subfc 4,4,5
subfe 9,9,9
addi 9,9,1
add 3,9,3
blr
add_geu:
subfc 5,5,4
subfe 9,9,9
addi 9,9,1
add 3,9,3
blr
but with this patch we now generate:
add_leu:
subfc 4,4,5
addze 3,3
blr
add_geu:
subfc 5,5,4
addze 3,3
blr
This patch has been tested on powerpc64-unknown-linux-gnu (many thanks
to gcc203.fsffrance.org on the GCC compile farm) with a make bootstrap
and make -k check with now new failures.
Ok for mainline?
2021-12-02 Roger Sayle <[email protected]>
gcc/ChangeLog
PR target/43892
* config/rs6000/rs6000.md (*add<mode>3_carry_in_0_2): New
define_insn to recognize commutative form of add<mode>3_carry_in_0.
(*add<mode>3_geu, *add<mode>3_leu, *subf<mode>3_carry_in_xx_subf,
*add<mode>3_carry_in_addc): New define_insn_and_split patterns.
gcc/testsuite/ChangeLog
PR target/43892
* gcc.target/powerpc/addcmp.c: New test case.
* gcc.target/powerpc/pr43892.c: New test case.
Many thanks in advance.
Roger
--