mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
[V3][RISC-V][PR rtl-optimization/96692] Improve xor+xor+ior sequence when possible
Consider this code:
int f(int a, int b, int c)
{
return (a ^ b) ^ (a | c);
}
For RISC-V we generate something like this:
xor a1,a0,a1
or a0,a0,a2
xor a0,a1,a0
But this would be better:
andn a0,a2,a0
xor a0,a0,a1
It looks like Roger tackled this earlier with splitters for x86. I'd have
leaned more towards simplify-rtx, but there may be secondary concerns at play.
So I'll attack in the RISC-V target files in a similar manner.
The patch, but not the testcase, have been in my tester for a while, so it's
been bootstrapped and regression tested on the Pioneer and BPI-F3 board and
regression tested on riscv32-elf and riscv64-elf. Obviously I'll wait for
pre-commit CI before moving forward.
PR rtl-optimization/96692
gcc/
* config/riscv/bitmanip.md (xor+xor+ior splitters): New splitters
that ultimately generate andn+xor when possible.
gcc/testsuite
* gcc.target/riscv/pr96692.c: New test.
This commit is contained in:
@@ -1441,3 +1441,26 @@
|
||||
operands[3] = gen_lowpart (DImode, operands[3]);
|
||||
operands[6] = gen_lowpart (SImode, operands[5]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:X 0 "register_operand")
|
||||
(xor:X (xor:X (ior:X (match_operand:X 1 "register_operand")
|
||||
(match_operand:X 2 "register_operand"))
|
||||
(match_dup 1))
|
||||
(match_operand:X 3 "register_operand")))
|
||||
(clobber (match_operand:X 4 "register_operand"))]
|
||||
"TARGET_ZBB || TARGET_ZBKB"
|
||||
[(set (match_dup 4) (and:X (not:X (match_dup 1)) (match_dup 2)))
|
||||
(set (match_dup 0) (xor:X (match_dup 4) (match_dup 3)))])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:X 0 "register_operand")
|
||||
(xor:X (xor:X (ior:X (match_operand:X 1 "register_operand")
|
||||
(match_operand:X 2 "register_operand"))
|
||||
(match_dup 2))
|
||||
(match_operand:X 3 "register_operand")))
|
||||
(clobber (match_operand:X 4 "register_operand"))]
|
||||
"TARGET_ZBB || TARGET_ZBKB"
|
||||
[(set (match_dup 4) (and:X (not:X (match_dup 2)) (match_dup 1)))
|
||||
(set (match_dup 0) (xor:X (match_dup 4) (match_dup 3)))])
|
||||
|
||||
|
||||
12
gcc/testsuite/gcc.target/riscv/pr96692.c
Normal file
12
gcc/testsuite/gcc.target/riscv/pr96692.c
Normal file
@@ -0,0 +1,12 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-additional-options "-march=rv64gcb_zicond -mabi=lp64d" { target rv64 } } */
|
||||
/* { dg-additional-options "-march=rv32gcb_zicond -mabi=ilp32" { target rv32 } } */
|
||||
/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
|
||||
|
||||
int f(int a, int b, int c)
|
||||
{
|
||||
return (a ^ b) ^ (a | c);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times "xor\t" 1 } } */
|
||||
/* { dg-final { scan-assembler-times "andn\t" 1 } } */
|
||||
Reference in New Issue
Block a user