[Bug rtl-optimization/124955] Improve code generation for leela's random number generation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124955 Jeffrey A. Law changed: What|Removed |Added Resolution|--- |FIXED Status|NEW |RESOLVED --- Comment #6 from Jeffrey A. Law --- Fixed on the trunk.
[Bug rtl-optimization/124955] Improve code generation for leela's random number generation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124955
--- Comment #5 from GCC Commits ---
The master branch has been updated by Jeff Law :
https://gcc.gnu.org/g:046bc3484c90a25fb09c851d6afac13b790bb20c
commit r17-412-g046bc3484c90a25fb09c851d6afac13b790bb20c
Author: Jeff Law
Date: Fri May 8 11:40:29 2026 -0600
[V2][RISC-V][PR target/124955] Utilize slliw for some left shifted signed
bitfield extractions
Some functional change as was already posted, this time with a testcase.
Given
it's been in my tester and through the pre-commit CI system, I'm going
forward
now.
--
So as the PR notes, this is an attempt to squeeze out some instructions
from a
hot part of leela, the random number generator in particular.
typedef unsigned int uint32;
uint32 random(uint32 s1) {
const uint32 mask = 0x;
s1 = (((s1 & 0xFFFEU) << 12) & mask);
return s1;
}
Generates this RISC-V code:
sllia5,a0,44# 25[c=4 l=4] ashldi3
sraia0,a5,44# 26[c=4 l=4] ashrdi3
andia0,a0,-2# 21[c=4 l=4] *anddi3/1
sllia0,a0,12# 22[c=4 l=4] ashldi3
But this is an equivalent sequence:
andia0, a0, -2
slliw a0, a0, 12
The key is realizing that the the first two statements are just a sign
extended
bitfield of length 20. That ultimately gets shifted left 12 bits. 20+12 =
32,
so we can at least conceptually use slliw (shift left sign extending result
from SI to DI). The andi just turns off the low bit.
Given a sign extracted bitfield starting at bit 0, of size N that is then
left
shifted by M where N+M == 32 is a natural slliw instruction. However, when
I
tried to recognize that and generate the slliw form I saw code quality
regressions that didn't look particularly reasonable to try and fix. So
we
want to be more selective about recognizing that idiom. So we recognize it
when we subsequently mask off some bits and the mask can be encoded via
andi.
This likely could be extended to other logical operations that don't
ultimately
affect the SI sign bit.
PR target/124955
gcc/
* config/riscv/riscv.md (masked shifted bitfield extraction): New
splitter to utilize slliw to eliminate the need for sign extnesion.
gcc/testsuite/
* gcc.target/riscv/pr124955.c: New test
[Bug rtl-optimization/124955] Improve code generation for leela's random number generation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124955 Jeffrey A. Law changed: What|Removed |Added Blocks|120763 | Assignee|unassigned at gcc dot gnu.org |law at gcc dot gnu.org --- Comment #4 from Jeffrey A. Law --- I'm testing a patch. It's a run-of-the-mill 3->2 combination. Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120763 [Bug 120763] [meta-bug] Tracker for bugs to visit during weekly RISC-V meeting
[Bug rtl-optimization/124955] Improve code generation for leela's random number generation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124955 --- Comment #3 from Drea Pinski --- (In reply to Jeffrey A. Law from comment #2) > I think avoiding the sign_extract form would be better. Right and expand_compound_operation should/will expand it to be the shifts; I was doing the math wrong for the expansion so I left that off.
[Bug rtl-optimization/124955] Improve code generation for leela's random number generation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124955 --- Comment #2 from Jeffrey A. Law --- I think avoiding the sign_extract form would be better. As a spitter I would target generating something like this for the new RTL: (set (match_dup 0) (and (match_dup 1) (const_int -2)) (set (match_dup 0) (sign_extend:DI(ashift (match_dup 0) (const_int 12)) Or something along those lines. There's some obvious type changes in there, but that's the basic idea. The key is realizing the field from the sign_extract N bits long, starting at 0 and fed into a shift by M bits, where N + M == 32. That's a natural match for slliw. Then we just need to handle the logical and, which we can do first or second in the generated RTL. In the case where the mask doesn't fit andi we can generate th two shift form. One shifts LSB bits off, the second moves the remaining bits into position. Again we'd be using slliw, so we'll get the proper sign extension.
[Bug rtl-optimization/124955] Improve code generation for leela's random number generation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124955 Drea Pinski changed: What|Removed |Added Ever confirmed|0 |1 Last reconfirmed||2026-04-21 Status|UNCONFIRMED |NEW --- Comment #1 from Drea Pinski --- GCC (and LLVM) for aarch64 produces: ``` lsl w0, w0, 12 and w0, w0, -8192 ``` Trying 10, 6 -> 11: 10: r142:DI=0xe000 6: r138:DI=sign_extend(r136:DI#0<<0xc) REG_DEAD r136:DI 11: r141:DI=r138:DI&r142:DI REG_DEAD r142:DI REG_DEAD r138:DI REG_EQUAL r138:DI&0xe000 Failed to match this instruction: (set (reg:DI 141) (and:DI (ashift:DI (sign_extract:DI (reg/v:DI 136 [ s1 ]) (const_int 20 [0x14]) (const_int 0 [0])) (const_int 12 [0xc])) (const_int -8192 [0xe000]))) Can't we push the and past the shift and then into the sign_extract. So that becomes (ashift:DI (sign_extract:DI (reg/v:DI 136 [ s1 ]) (const_int 18 [0x14]) (const_int 2 [0])) (const_int 2 [0])) Hopefully I did my math correctly.
