Skip to content

Commit d53f7ad

Browse files
Dusan StojkovicJeffreyALaw
authored andcommitted
[PATCH][PR target/121778] RISC-V: Improve rotation detection for RISC-V
This patch splits the canonical sign-bit checking idiom into a 2-insn sequence when Zbb is available. Combine often normalizes (xor (lshr A, (W - 1)) 1) to (ge A, 0). For width W = bitsize (mode), the identity: (a << 1) | (a >= 0) == (a << 1) | ((a >> (W - 1)) ^ 1) == ROL1 (a) ^ 1 lets us split: (ior:X (ashift:X A 1) (ge:X A 0)) into: → rotatert:X A, (W-1) → xor:X A, 1 PR target/121778 gcc/ChangeLog: * config/riscv/riscv.md: Add define_split pattern. gcc/testsuite/ChangeLog: * gcc.target/riscv/pr121778-1.c: New test. * gcc.target/riscv/pr121778-2.c: New test.
1 parent dfbce1f commit d53f7ad

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

gcc/config/riscv/riscv.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4614,6 +4614,26 @@
46144614
FAIL;
46154615
})
46164616

4617+
; Split (A<<1) | (A>=0) into a rotate + xor. Using two’s-complement identities:
4618+
; (A>=0) == ((A >> (W-1)) ^ 1) and (A<<1) | (A>>(W-1)) == ROL1 (A), so the whole
4619+
; expression equals ROL1 (A) ^ 1.
4620+
(define_split
4621+
[(set (match_operand:X 0 "register_operand")
4622+
(ior:X
4623+
(ashift:X (match_operand:X 1 "register_operand")
4624+
(const_int 1))
4625+
(ge:X (match_dup 1) (const_int 0))))]
4626+
"TARGET_ZBB"
4627+
[(set (match_dup 0)
4628+
(rotatert:X (match_dup 1) (match_operand 2 "const_int_operand")))
4629+
(set (match_dup 0)
4630+
(xor:X (match_dup 0) (const_int 1)))]
4631+
{
4632+
HOST_WIDE_INT rotval;
4633+
rotval = GET_MODE_BITSIZE (GET_MODE (operands[1])).to_constant () - 1;
4634+
operands[2] = GEN_INT (rotval);
4635+
})
4636+
46174637
(define_insn "*large_load_address"
46184638
[(set (match_operand:DI 0 "register_operand" "=r")
46194639
(mem:DI (match_operand 1 "pcrel_symbol_operand" "")))]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* { dg-do compile { target { rv32 } } } */
2+
/* { dg-options "-march=rv32gc_zbb -mabi=ilp32 -O2" } */
3+
4+
unsigned int
5+
foo (unsigned int a)
6+
{
7+
return (a << 1) | ((a >> 31) ^ 1);
8+
}
9+
10+
/* { dg-final { scan-assembler {\mrori} } } */
11+
/* { dg-final { scan-assembler {\mxori} } } */
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* { dg-do compile { target { rv64 } } } */
2+
/* { dg-options "-march=rv64gc_zbb -mabi=lp64 -O2" } */
3+
4+
unsigned long
5+
foo (unsigned long a)
6+
{
7+
return (a << 1) | ((a >> 63) ^ 1);
8+
}
9+
10+
/* { dg-final { scan-assembler {\mrori} } } */
11+
/* { dg-final { scan-assembler {\mxori} } } */

0 commit comments

Comments
 (0)