I goof'd when doing analysis of missed bext cases. For the shift into
the sign bit, then shift into the low bit case (thankfully the least
common), I got it in my brain that the field is at the left shift count.
It's actually at word_size - 1 - left shift count.
One the subtraction is included, it's no longer profitable to turn those
cases into bext. Best case scenario would be sub+bext, but we can just
as easily use sll+srl which fuses in some designs into a single op.
So this patch removes those two patterns, adjusts the existing testcase
and adds the new execution test.
Given it's a partial reversion and has passed in my tester, I'm going to
go ahead and push it to the trunk rather than waiting for upstream CI.
Jeff
commit 38fa6c0455ec14f2f42310a817b90765ad894aa4
Author: Jeff Law <j...@ventanamicro.com>
Date: Mon May 19 16:55:15 2025 -0600
[committed][RISC-V][PR target/120333] Remove bogus bext pattern
I goof'd when doing analysis of missed bext cases. For the shift into the
sign
bit, then shift into the low bit case (thankfully the least common), I got
it
in my brain that the field is at the left shift count. It's actually at
word_size - 1 - left shift count.
One the subtraction is included, it's no longer profitable to turn those
cases
into bext. Best case scenario would be sub+bext, but we can just as easily
use
sll+srl which fuses in some designs into a single op.
So this patch removes those two patterns, adjusts the existing testcase and
adds the new execution test.
Given it's a partial reversion and has passed in my tester, I'm going to go
ahead and push it to the trunk rather than waiting for upstream CI.
PR target/120333
gcc/
* config/riscv/bitmanip.md: Remove bext formed from left+right
shift patterns.
gcc/testsuite/
* gcc.target/riscv/pr114512.c: Update expected output.
* gcc.target/riscv/pr120333.c: New test.
diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index c226c39f580..7e6f3df5133 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -1337,32 +1337,6 @@ (define_insn "*bextdi_position_ze_masked"
"bext\t%0,%1,%2"
[(set_attr "type" "bitmanip")])
-
-;; Single bit extraction by first shifting it into the sign bit, then
-;; shifting it down to the low bit.
-(define_insn "*bext<mode>_position_masked"
- [(set (match_operand:X 0 "register_operand" "=r")
- (lshiftrt:X (ashift:X (match_operand:X 1 "register_operand" "r")
- (match_operand:QI 2 "register_operand" "r"))
- (match_operand:X 3 "bitpos_mask_operand" "n")))]
- "TARGET_ZBS"
- "bext\t%0,%1,%2"
- [(set_attr "type" "bitmanip")])
-
-;; Single bit extraction by shifting into the low bit, but with the
-;; position formed with a subreg of a mask.
-(define_insn "*bext<mode>_position_masked_subreg"
- [(set (match_operand:X 0 "register_operand" "=r")
- (lshiftrt:X
- (ashift:X (match_operand:X 1 "register_operand" "r")
- (subreg:QI
- (and:X (match_operand:X 2 "register_operand" "r")
- (match_operand:X 3 "bitpos_mask_operand" "n")) 0))
- (match_operand:X 4 "bitpos_mask_operand" "n")))]
- "TARGET_ZBS"
- "bext\t%0,%1,%2"
- [(set_attr "type" "bitmanip")])
-
;; This has shown up in testing. In particular we end up with an
;; immediate input. We can load that into a register and target
;; one of the above bext patterns.
diff --git a/gcc/testsuite/gcc.target/riscv/pr114512.c
b/gcc/testsuite/gcc.target/riscv/pr114512.c
index 205071c0883..70146f5c023 100644
--- a/gcc/testsuite/gcc.target/riscv/pr114512.c
+++ b/gcc/testsuite/gcc.target/riscv/pr114512.c
@@ -47,22 +47,6 @@ _Bool my_isxdigit_2a(unsigned char ch) {
return 1;
}
-_Bool my_isxdigit_3(unsigned char ch) {
- utype mask1 = 0x7E00FFC0;
- if (!((mask1 << (MASK - (ch & MASK))) >> MASK))
- return 0;
-
- return 1;
-}
-
-_Bool my_isxdigit_3a(unsigned char ch) {
- utype mask2 = 0x7E00FFC0;
- if (!((mask2 << (MASK - ((ch >> 4) & MASK))) >> MASK))
- return 0;
-
- return 1;
-}
-
_Bool my_isxdigit_1_parm(unsigned char ch, utype mask1) {
if (!((mask1 >> (ch & MASK)) & 1))
return 0;
@@ -91,19 +75,5 @@ _Bool my_isxdigit_2a_parm(unsigned char ch, utype mask2) {
return 1;
}
-_Bool my_isxdigit_3_parm(unsigned char ch, utype mask1) {
- if (!((mask1 << (MASK - (ch & MASK))) >> MASK))
- return 0;
-
- return 1;
-}
-
-_Bool my_isxdigit_3a_parm(unsigned char ch, utype mask2) {
- if (!((mask2 << (MASK - ((ch >> 4) & MASK))) >> MASK))
- return 0;
-
- return 1;
-}
-
/* Each test should generate a single bext. */
-/* { dg-final { scan-assembler-times "bext\t" 12 } } */
+/* { dg-final { scan-assembler-times "bext\t" 8 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/pr120333.c
b/gcc/testsuite/gcc.target/riscv/pr120333.c
new file mode 100644
index 00000000000..17b376f3add
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr120333.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { rv64 } } } */
+/* { dg-additional-options "-march=rv64gcb -std=gnu23" } */
+
+__attribute__ ((noipa)) _Bool
+foo (unsigned char ch, unsigned long mask) {
+ return (mask << (0x3f - (ch & 0x3f))) >> 0x3f;
+}
+
+int main()
+{
+ if (!foo (0x3f, 0x8000000000000000ul))
+ __builtin_abort ();
+ return 0;
+}
+