[v2] RISC-V: Missed bit manipulation on RISC-V [PR123884]
Checks
| Context |
Check |
Description |
| rivoscibot/toolchain-ci-rivos-apply-patch |
success
|
Patch applied
|
| rivoscibot/toolchain-ci-rivos-lint |
warning
|
Lint failed
|
| rivoscibot/toolchain-ci-rivos-build--linux-rv64gcv-lp64d-multilib |
success
|
Build passed
|
| rivoscibot/toolchain-ci-rivos-test |
fail
|
Testing failed
|
Commit Message
We currently have an issue in my previous RTL when dest is a 64-bit value.
The upper 32 bits are lost during the sext instruction.
https://godbolt.org/z/q31obx3b6
Example:
dest = 0xFFFFFFFF00000001
a = 29
In the initial implementation, we get:
0xFFFFFFFF00000001 | 0x0000000020000000
which results in:
0xFFFFFFFF20000001
However, with the bset + sext sequence, the behavior is incorrect:
after best : 0xFFFFFFFF20000001
after sext : 0x0000000020000001
So the sign extension is performed incorrectly, causing the upper 32 bits
to be dropped and leading to an incorrect final result. I would like to change
the pattern so that it becomes something like bset + sext + or, since it is
required for this case. The issue is that both long and int cases currently
share the same RTL in combine pass when our pattern match, so at the moment
I don’t have a clear way to distinguish between them. As a result, GCC would also
generate bset + sext + or for the int case, which should be just bset + sext.
2026-05-06 Milan Tripkovic <Milan.Tripkovic@rt-rk.com>
gcc/ChangeLog:
* config/riscv/bitmanip.md (bset_sextw_or): new pattern for bset
gcc/testsuite/ChangeLog:
* gcc.target/riscv/pr123884-c.c: New test for new pattern
CONFIDENTIALITY: The contents of this e-mail are confidential and intended only for the above addressee(s). If you are not the intended recipient, or the person responsible for delivering it to the intended recipient, copying or delivering it to anyone else or using it in any unauthorized manner is prohibited and may be unlawful. If you receive this e-mail by mistake, please notify the sender and the systems administrator at straymail@rt-rk.com immediately.
---
gcc/config/riscv/bitmanip.md | 26 +++++++++++++++++++++
gcc/testsuite/gcc.target/riscv/pr123884-c.c | 12 ++++++++++
2 files changed, 38 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/riscv/pr123884-c.c
@@ -740,6 +740,32 @@
{ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); }
[(set_attr "type" "bitmanip")])
+;;Pattern for bset with sign_extend
+(define_insn_and_split "bset_sextw_or"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ior:DI
+ (sign_extend:DI
+ (ashift:SI
+ (const_int 1)
+ (subreg:QI
+ (match_operand:DI 1 "register_operand" "r") 0)))
+ (match_operand:DI 2 "register_operand" "r")))]
+ "TARGET_64BIT && TARGET_ZBS"
+ "#"
+ "&& !reload_completed"
+ [
+ (set (match_dup 3)
+ (ashift:DI (const_int 1)
+ (subreg:QI (match_dup 1) 0)))
+ (set (match_dup 3)
+ (sign_extend:DI (subreg:SI (match_dup 3) 0)))
+ (set (match_dup 0)
+ (ior:DI (match_dup 2) (match_dup 3)))
+ ]
+ {
+ operands[3] = gen_reg_rtx (DImode);
+ }
+)
;; Similarly two patterns for AND generating bclr to
;; manipulate a bit in a register
(define_insn_and_split ""
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbs -mabi=lp64d -O2" } */
+
+int foo2(int dst, int a)
+{
+ dst |= (1 << a);
+ return dst;
+}
+
+/* { dg-final { scan-assembler-times "bset" 1 } } */
+/* { dg-final { scan-assembler-times "sext.w" 1 } } */
+/* { dg-final { scan-assembler-times "or" 1 } } */
\ No newline at end of file