https://gcc.gnu.org/g:8c2010a09a3a63f908fcf999b3248343369185b9

commit 8c2010a09a3a63f908fcf999b3248343369185b9
Author: Jovan Vukic <jovan.vu...@rt-rk.com>
Date:   Wed Oct 9 16:53:38 2024 -0600

    RISC-V: Optimize branches with shifted immediate operands
    
    After the valuable feedback I received, it’s clear to me that the
    oversight was in the tests showing the benefits of the patch. In the
    test file, I added functions f5 and f6, which now generate more
    efficient code with fewer instructions.
    
    Before the patch:
    
    f5:
            li      a4,2097152
            addi    a4,a4,-2048
            li      a5,1167360
            and     a0,a0,a4
            addi    a5,a5,-2048
            beq     a0,a5,.L4
    
    f6:
            li      a5,3407872
            addi    a5,a5,-2048
            and     a0,a0,a5
            li      a5,1114112
            beq     a0,a5,.L7
    
    After the patch:
    
    f5:
            srli    a5,a0,11
            andi    a5,a5,1023
            li      a4,569
            beq     a5,a4,.L5
    
    f6:
            srli    a5,a0,11
            andi    a5,a5,1663
            li      a4,544
            beq     a5,a4,.L9
    
            PR target/115921
    
    gcc/ChangeLog:
    
            * config/riscv/iterators.md (any_eq): New code iterator.
            * config/riscv/riscv.h (COMMON_TRAILING_ZEROS): New macro.
            (SMALL_AFTER_COMMON_TRAILING_SHIFT): Ditto.
            * config/riscv/riscv.md 
(*branch<ANYI:mode>_shiftedarith_<optab>_shifted):
            New pattern.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/branch-1.c: Additional tests.
    
    (cherry picked from commit c8957c8779954c3b0bade1dde0a8987b4db157b4)

Diff:
---
 gcc/config/riscv/iterators.md             |  4 ++++
 gcc/config/riscv/riscv.h                  | 12 ++++++++++++
 gcc/config/riscv/riscv.md                 | 32 +++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/branch-1.c | 18 ++++++++++++++---
 4 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 872c542e9065..081659499a99 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -233,6 +233,8 @@
 (define_code_iterator any_ge [ge geu])
 (define_code_iterator any_lt [lt ltu])
 (define_code_iterator any_le [le leu])
+(define_code_iterator any_eq [eq ne])
+
 ;; Iterators for conditions we can emit a sCC against 0 or a reg directly
 (define_code_iterator scc_0  [eq ne gt gtu])
 
@@ -285,6 +287,8 @@
                         (le "le")
                         (gt "gt")
                         (lt "lt")
+                        (eq "eq")
+                        (ne "ne")
                         (ior "ior")
                         (xor "xor")
                         (and "and")
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 57e3a5e03eb1..a9211be29bb4 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -671,6 +671,18 @@ enum reg_class
 /* True if bit BIT is set in VALUE.  */
 #define BITSET_P(VALUE, BIT) (((VALUE) & (1ULL << (BIT))) != 0)
 
+/* Returns the smaller (common) number of trailing zeros for VAL1 and VAL2.  */
+#define COMMON_TRAILING_ZEROS(VAL1, VAL2)                              \
+  (ctz_hwi (VAL1) < ctz_hwi (VAL2)                                     \
+   ? ctz_hwi (VAL1)                                                    \
+   : ctz_hwi (VAL2))
+
+/* Returns true if both VAL1 and VAL2 are SMALL_OPERANDs after shifting by
+   the common number of trailing zeros.  */
+#define SMALL_AFTER_COMMON_TRAILING_SHIFT(VAL1, VAL2)                  \
+  (SMALL_OPERAND ((VAL1) >> COMMON_TRAILING_ZEROS (VAL1, VAL2))                
\
+   && SMALL_OPERAND ((VAL2) >> COMMON_TRAILING_ZEROS (VAL1, VAL2)))
+
 /* Stack layout; function entry, exit and calling.  */
 
 #define STACK_GROWS_DOWNWARD 1
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 688c07df46c4..78112afbb261 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3129,6 +3129,38 @@
 }
 [(set_attr "type" "branch")])
 
+(define_insn_and_split "*branch<ANYI:mode>_shiftedarith_<optab>_shifted"
+  [(set (pc)
+       (if_then_else (any_eq
+                   (and:ANYI (match_operand:ANYI 1 "register_operand" "r")
+                         (match_operand 2 "shifted_const_arith_operand" "i"))
+                   (match_operand 3 "shifted_const_arith_operand" "i"))
+        (label_ref (match_operand 0 "" ""))
+        (pc)))
+   (clobber (match_scratch:X 4 "=&r"))
+   (clobber (match_scratch:X 5 "=&r"))]
+  "!SMALL_OPERAND (INTVAL (operands[2]))
+    && !SMALL_OPERAND (INTVAL (operands[3]))
+    && SMALL_AFTER_COMMON_TRAILING_SHIFT (INTVAL (operands[2]),
+                                            INTVAL (operands[3]))"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 4) (lshiftrt:X (match_dup 1) (match_dup 7)))
+   (set (match_dup 4) (and:X (match_dup 4) (match_dup 8)))
+   (set (match_dup 5) (match_dup 9))
+   (set (pc) (if_then_else (any_eq (match_dup 4) (match_dup 5))
+                          (label_ref (match_dup 0)) (pc)))]
+{
+  HOST_WIDE_INT mask1 = INTVAL (operands[2]);
+  HOST_WIDE_INT mask2 = INTVAL (operands[3]);
+  int trailing_shift = COMMON_TRAILING_ZEROS (mask1, mask2);
+
+  operands[7] = GEN_INT (trailing_shift);
+  operands[8] = GEN_INT (mask1 >> trailing_shift);
+  operands[9] = GEN_INT (mask2 >> trailing_shift);
+}
+[(set_attr "type" "branch")])
+
 (define_insn_and_split "*branch<ANYI:mode>_shiftedmask_equals_zero"
   [(set (pc)
        (if_then_else (match_operator 1 "equality_operator"
diff --git a/gcc/testsuite/gcc.target/riscv/branch-1.c 
b/gcc/testsuite/gcc.target/riscv/branch-1.c
index b4a3a946379a..7fa878324841 100644
--- a/gcc/testsuite/gcc.target/riscv/branch-1.c
+++ b/gcc/testsuite/gcc.target/riscv/branch-1.c
@@ -28,10 +28,22 @@ void f4(long long a)
     g();
 }
 
+void f5(long long a)
+{
+  if ((a & 0x1ff800) == 0x11c800)
+    g();
+}
+
+void f6(long long a)
+{
+  if ((a & 0x33f800) == 0x110000)
+    g();
+}
+
 /* { dg-final { scan-assembler-times "slli\t" 2 } } */
-/* { dg-final { scan-assembler-times "srli\t" 3 } } */
-/* { dg-final { scan-assembler-times "andi\t" 1 } } */
-/* { dg-final { scan-assembler-times "\tli\t" 1 } } */
+/* { dg-final { scan-assembler-times "srli\t" 5 } } */
+/* { dg-final { scan-assembler-times "andi\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tli\t" 3 } } */
 /* { dg-final { scan-assembler-not "addi\t" } } */
 /* { dg-final { scan-assembler-not "and\t" } } */

Reply via email to