Commit 36f0b74
Jeff Law
[RISC-V][PR target/123838] Improve code generated for shifts with counts 31-N or 63-N
A shift count expressed at 31 - n ends up generating code like this:
li a5,31
subw a5,a5,a1
sllw a0,a0,a5
ret
Note how we had to load 31 into a constant for the subtraction. But instead of
using 31 - n we can use a bit-not as it'll do precisely what we need in the
bits that the shift instruction actually uses. This results in:
not a1, a1
sllw a0, a0, a1
ret
The core idea we're exploiting here is the processor implements
SHIFT_COUNT_TRUNCATED semantics. so a SI shift only cares about the low 5 bits
and DI the low 6 bits of the shift count. And if we think about what bit
pattern -1 would be in those cases we get 31 and 63. We then exploit the
identity
-x = ~x + 1 // identity
-1 - x = ~x // a tiny bit of algebra
So in these limited cases we can place the the -1 - x with ~x.
I didn't implement this in simplify-rtx. It wasn't actually going to help
because while the RISC-V chip implements SHIFT_COUNT_TRUNCATED semantics, it
doesn't define SHIFT_COUNT_TRUNCATED for "reasons".
So there's two patterns. One for an X mode destination, naturally the shift
count is 31/63 - n for SI/DI respectively. It's a bit odd that the subtraction
is always SImode, but that's probably narrowing happening somewhere.
The second pattern covers the "w" forms for rv64.
This trick probably works for the zbs instructions as well. That's going to be
a whole lot more patterns and I haven't seen this idiom show up anywhere in
practice, so it doesn't seem like a good cost/benefit analysis.
This spun overnight on riscv32-elf and riscv64-elf and on the Pioneer without
regressions. I'll wait for pre-commit CI to do its thing before pushing.
PR target/123838
gcc/
* config/riscv/riscv.md: Use splitters to simplify shifts where
the shift count is 31-N or 63-N.
gcc/testsuite
* gcc.target/riscv/pr123838.c: New test.
Co-authored-by: Austin Law <austinklaw@gmail.com>1 parent 7c3e6df commit 36f0b74
2 files changed
Lines changed: 57 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4995 | 4995 | | |
4996 | 4996 | | |
4997 | 4997 | | |
| 4998 | + | |
| 4999 | + | |
| 5000 | + | |
| 5001 | + | |
| 5002 | + | |
| 5003 | + | |
| 5004 | + | |
| 5005 | + | |
| 5006 | + | |
| 5007 | + | |
| 5008 | + | |
| 5009 | + | |
| 5010 | + | |
| 5011 | + | |
| 5012 | + | |
| 5013 | + | |
| 5014 | + | |
| 5015 | + | |
| 5016 | + | |
| 5017 | + | |
| 5018 | + | |
| 5019 | + | |
| 5020 | + | |
| 5021 | + | |
| 5022 | + | |
| 5023 | + | |
| 5024 | + | |
| 5025 | + | |
| 5026 | + | |
| 5027 | + | |
| 5028 | + | |
| 5029 | + | |
| 5030 | + | |
| 5031 | + | |
| 5032 | + | |
| 5033 | + | |
| 5034 | + | |
| 5035 | + | |
| 5036 | + | |
| 5037 | + | |
| 5038 | + | |
| 5039 | + | |
4998 | 5040 | | |
4999 | 5041 | | |
5000 | 5042 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
0 commit comments