https://gcc.gnu.org/g:cfbc8c48ae78c69401e8bc70d80eacbea8b47ec5

commit r17-5638-gcfbc8c48ae78c69401e8bc70d80eacbea8b47ec5
Author: Jiawei <[email protected]>
Date:   Tue Oct 27 07:30:09 2026 -0600

    [PATCH 1/3] RISC-V: Combine Zba shift-add with word division and remainder
    
    Extend the word-division split to unsigned division and both remainder
    operations using any_div.  These instructions consume only the low word
    of each input and sign-extend their results, so an XLEN-wide shNadd can
    replace the word shift-add sequence before the division or remainder.
    
    gcc/ChangeLog:
    
            * config/riscv/bitmanip.md: Use any_div.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/zba-shNadd-05.c: Add unsigned div.
            * gcc.target/riscv/zba-shNadd-12.c: New test.

Diff:
---
 gcc/config/riscv/bitmanip.md                   | 13 ++++++------
 gcc/testsuite/gcc.target/riscv/zba-shNadd-05.c | 28 ++++++++++++++++++++++++--
 gcc/testsuite/gcc.target/riscv/zba-shNadd-12.c | 27 +++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index b18d4c8e5c6f..fe2b9fbae02a 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -41,20 +41,21 @@
 
 ; When using strength-reduction, we will reduce a multiplication to a
 ; sequence of shifts and adds.  If this is performed with 32-bit types
-; and followed by a division, the lack of w-form sh[123]add will make
-; combination impossible and lead to a slli + addw being generated.
-; Split the sequence with the knowledge that a w-form div will perform
-; implicit sign-extensions.
+; and followed by a division or remainder, the lack of w-form sh[123]add
+; will make combination impossible and lead to a slli + addw being
+; generated.  Split the sequence with the knowledge that word division
+; and remainder only use the low word of their inputs and sign-extend
+; their results, including for unsigned operations.
 (define_split
   [(set (match_operand:DI 0 "register_operand")
-       (sign_extend:DI (div:SI (plus:SI (ashift:SI (subreg:SI 
(match_operand:DI 1 "register_operand") 0)
+       (sign_extend:DI (any_div:SI (plus:SI (ashift:SI (subreg:SI 
(match_operand:DI 1 "register_operand") 0)
                                                    (match_operand:QI 2 
"imm123_operand"))
                                         (subreg:SI (match_operand:DI 3 
"register_operand") 0))
                                (match_operand:SI 4 "register_operand"))))
    (clobber (match_operand:DI 5 "register_operand"))]
   "TARGET_64BIT && TARGET_ZBA"
    [(set (match_dup 5) (plus:DI (ashift:DI (match_dup 1) (match_dup 2)) 
(match_dup 3)))
-    (set (match_dup 0) (sign_extend:DI (div:SI (subreg:SI (match_dup 5) 0) 
(match_dup 4))))])
+    (set (match_dup 0) (sign_extend:DI (any_div:SI (subreg:SI (match_dup 5) 0) 
(match_dup 4))))])
 
 ; Zba does not provide W-forms of sh[123]add(.uw)?, which leads to an
 ; interesting irregularity: we can generate a signed 32-bit result
diff --git a/gcc/testsuite/gcc.target/riscv/zba-shNadd-05.c 
b/gcc/testsuite/gcc.target/riscv/zba-shNadd-05.c
index 271c3a8c0ac0..8bb6706496cc 100644
--- a/gcc/testsuite/gcc.target/riscv/zba-shNadd-05.c
+++ b/gcc/testsuite/gcc.target/riscv/zba-shNadd-05.c
@@ -2,10 +2,34 @@
 /* { dg-options "-march=rv64gc_zba -mabi=lp64" } */
 /* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Oz" "-Og" } } */
 
-long long f(int a, int b)
+long long
+f (int a, int b)
 {
   return (a * 3) / b;
 }
 
-/* { dg-final { scan-assembler-times "sh1add\t" 1 } } */
+unsigned int
+f1 (unsigned int a, unsigned int b)
+{
+  return (a * 3) / b;
+}
+
+int
+f2 (int a, int b)
+{
+  return (a * 5) % b;
+}
+
+unsigned int
+f3 (unsigned int a, unsigned int b)
+{
+  return (a * 9) % b;
+}
+
+/* { dg-final { scan-assembler-times "sh1add\t" 2 } } */
+/* { dg-final { scan-assembler-times "sh2add\t" 1 } } */
+/* { dg-final { scan-assembler-times "sh3add\t" 1 } } */
 /* { dg-final { scan-assembler-times "divw\t" 1 } } */
+/* { dg-final { scan-assembler-times "divuw\t" 1 } } */
+/* { dg-final { scan-assembler-times "remw\t" 1 } } */
+/* { dg-final { scan-assembler-times "remuw\t" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zba-shNadd-12.c 
b/gcc/testsuite/gcc.target/riscv/zba-shNadd-12.c
new file mode 100644
index 000000000000..8b5566c66931
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zba-shNadd-12.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zba -mabi=lp64 -O2" } */
+
+unsigned int
+f1 (unsigned int a, unsigned int b, unsigned int c)
+{
+  return (a * 2 + b) / c;
+}
+
+int
+f2 (int a, int b, int c)
+{
+  return (a * 4 + b) % c;
+}
+
+unsigned int
+f3 (unsigned int a, unsigned int b, unsigned int c)
+{
+  return (a * 8 + b) % c;
+}
+
+/* { dg-final { scan-assembler-times "sh1add\t" 1 } } */
+/* { dg-final { scan-assembler-times "sh2add\t" 1 } } */
+/* { dg-final { scan-assembler-times "sh3add\t" 1 } } */
+/* { dg-final { scan-assembler-times "divuw\t" 1 } } */
+/* { dg-final { scan-assembler-times "remw\t" 1 } } */
+/* { dg-final { scan-assembler-times "remuw\t" 1 } } */

Reply via email to