[gcc/devel/jlaw/pr123904] Use shift pair to optimize this case
Jeff Law
law@gcc.gnu.org
Wed Mar 11 00:09:48 GMT 2026
https://gcc.gnu.org/g:9b642bb5353528a552bc44440769f64aba965590
commit 9b642bb5353528a552bc44440769f64aba965590
Author: Jeff Law <jeffrey.law@oss.qualcomm.com>
Date: Tue Mar 10 16:01:44 2026 -0600
Use shift pair to optimize this case
Diff:
---
gcc/config/riscv/riscv.md | 27 +++++++++++++++++++++++++++
gcc/testsuite/gcc.target/riscv/pr123904.c | 8 ++++++++
2 files changed, 35 insertions(+)
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 3fe0ad0ccdf4..7ffbdbbb8700 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -4960,6 +4960,33 @@
{ operands[3] = GEN_INT (BITS_PER_WORD
- exact_log2 (INTVAL (operands[3]) + 1)); })
+;; This is similar using a shift triplet to implement a logical AND when
+;; the mask is a consecutive_bits_operand.
+;;
+;; The difference is we have a left shift in the input RTL and we verify
+;; that clears the appropriate low bits. So we can get away with just
+;; two shifts.
+(define_split
+ [(set (match_operand:X 0 "register_operand")
+ (and:X (ashift:X (match_operand:X 1 "register_operand")
+ (match_operand 2 "const_int_operand"))
+ (match_operand 3 "consecutive_bits_operand")))
+ (clobber (match_operand:X 4 "register_operand"))]
+ "ctz_hwi (INTVAL (operands[3]) & GET_MODE_MASK (word_mode)) == INTVAL (operands[2])"
+ [(set (match_dup 4) (ashift:X (match_dup 1) (match_dup 5)))
+ (set (match_dup 0) (lshiftrt:X (match_dup 4) (match_dup 6)))]
+"{
+ /* We want to left shift by the number of leading zeros in the mask,
+ plus the number of bits shifted left by the pattern. */
+ HOST_WIDE_INT lshift
+ = clz_hwi (UINTVAL (operands[3])) % BITS_PER_WORD + INTVAL (operands[2]);
+ operands[5] = gen_int_mode (lshift, QImode);
+
+ /* And then we right shift things back into position. */
+ HOST_WIDE_INT rshift = lshift - INTVAL (operands[2]);
+ operands[6] = gen_int_mode (rshift, QImode);
+}")
+
;; Standard extensions and pattern for optimization
(include "bitmanip.md")
(include "crypto.md")
diff --git a/gcc/testsuite/gcc.target/riscv/pr123904.c b/gcc/testsuite/gcc.target/riscv/pr123904.c
new file mode 100644
index 000000000000..7181c8de46f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr123904.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+unsigned foo19(unsigned a, unsigned b) { b = (b << 2) >> 2; return a + (b << 1); }
+
+/* { dg-final { scan-assembler-times "slli" 1 } } */
+/* { dg-final { scan-assembler-times "srli" 1 } } */
+/* { dg-final { scan-assembler-times "add" 1 } } */
More information about the Gcc-cvs
mailing list