https://gcc.gnu.org/g:4553eccd23d74ba9ad2f862c5e66278a21abfe49

commit r16-3482-g4553eccd23d74ba9ad2f862c5e66278a21abfe49
Author: Takayuki 'January June' Suwa <jjsuwa_sys3...@yahoo.co.jp>
Date:   Fri Aug 29 19:19:32 2025 +0900

    xtensa: Optimize branch whether (reg:SI) is within/out the range handled by 
CLAMPS instruction
    
    The CLAMPS instruction in Xtensa ISA, provided when the TARGET_CLAMPS
    configuration is enabled (and also requires TARGET_MINMAX), returns a
    value clamped the number in the specified register to between -(1<<N) and
    (1<<N)-1 inclusive, where N is an immediate value from 7 to 22.
    
    Therefore, when the above configurations are met, by comparing the clamped
    result with the original value for equality, branching whether the value
    is within the range mentioned above or not is implemented with fewer
    instructions, especially when the upper and lower bounds of the range are
    too large to fit into a single immediate assignment.
    
         /* example (TARGET_MINMAX and TARGET_CLAMPS) */
         extern void foo(void);
         void test0(int a) {
           if (a >= -(1 << 9) && a < (1 << 9))
             foo();
         }
         void test1(int a) {
           if (a < -(1 << 20) || a >= (1 << 20))
             foo();
         }
    
         ;; before
         test0:
            entry   sp, 32
            addmi   a2, a2, 0x200
            movi    a8, 0x3ff
            bltu    a8, a2, .L1
            call8   foo
         .L1:
            retw.n
         test1:
            entry   sp, 32
            movi.n  a9, 1
            movi.n  a8, -1
            slli    a9, a9, 20
            srli    a8, a8, 11
            add.n   a2, a2, a9
            bgeu    a8, a2, .L4
            call8   foo
         .L4:
            retw.n
    
         ;; after
         test0:
            entry   sp, 32
            clamps  a8, a2, 9
            bne     a2, a8, .L1
            call8   foo
         .L1:
            retw.n
         test1:
            entry   sp, 32
            clamps  a8, a2, 20
            beq     a2, a8, .L4
            call8   foo
         .L4:
            retw.n
    
    (note: Currently, in the RTL instruction combination pass, the possible
    const_int values ​​are fundamentally constrained by
    TARGET_LEGITIMATE_CONSTANT_P() if no bare large constant assignments are
    possible (i.e., neither -mconst16 nor -mauto-litpools), so limiting N to
    a range of 7 to only 10 instead of to 22.  A series of forthcoming
    patches will introduce an entirely new "xt_largeconst" pass that will
    solve several issues including this.)
    
    gcc/ChangeLog:
    
            * config/xtensa/predicates.md (alt_ubranch_operator):
            New predicate.
            * config/xtensa/xtensa.md (*eqne_in_range):
            New insn_and_split pattern.

Diff:
---
 gcc/config/xtensa/predicates.md |  3 +++
 gcc/config/xtensa/xtensa.md     | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/gcc/config/xtensa/predicates.md b/gcc/config/xtensa/predicates.md
index 9aeaba6ad723..20160a4c4e5f 100644
--- a/gcc/config/xtensa/predicates.md
+++ b/gcc/config/xtensa/predicates.md
@@ -189,6 +189,9 @@
 (define_predicate "ubranch_operator"
   (match_code "ltu,geu"))
 
+(define_predicate "alt_ubranch_operator"
+  (match_code "gtu,leu"))
+
 (define_predicate "boolean_operator"
   (match_code "eq,ne"))
 
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 1339b03ce1e9..52ffb161c0f5 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -3313,6 +3313,42 @@
                                    (const_int 8)
                                    (const_int 9))))])
 
+(define_insn_and_split "*eqne_in_range"
+  [(set (pc)
+       (if_then_else (match_operator 4 "alt_ubranch_operator"
+                       [(plus:SI (match_operand:SI 0 "register_operand" "r")
+                                 (match_operand:SI 1 "const_int_operand" "i"))
+                        (match_operand:SI 2 "const_int_operand" "i")])
+                     (label_ref (match_operand 3 ""))
+                     (pc)))
+   (clobber (match_scratch:SI 5 "=&a"))]
+  "TARGET_MINMAX && TARGET_CLAMPS
+   && INTVAL (operands[1]) * 2 - INTVAL (operands[2]) == 1
+   && IN_RANGE (exact_log2 (INTVAL (operands[1])), 7, 22)"
+  "#"
+  "&& 1"
+  [(set (match_dup 5)
+       (smin:SI (smax:SI (match_dup 0)
+                         (match_dup 1))
+                (match_dup 2)))
+   (set (pc)
+       (if_then_else (match_op_dup 4
+                       [(match_dup 0)
+                        (match_dup 5)])
+                     (label_ref (match_dup 3))
+                     (pc)))]
+{
+  HOST_WIDE_INT v = INTVAL (operands[1]);
+  operands[1] = GEN_INT (-v);
+  operands[2] = GEN_INT (v - 1);
+  PUT_CODE (operands[4], GET_CODE (operands[4]) == GTU ? NE : EQ);
+  if (GET_CODE (operands[5]) == SCRATCH)
+    operands[5] = gen_reg_rtx (SImode);
+}
+  [(set_attr "type"    "jump")
+   (set_attr "mode"    "none")
+   (set_attr "length"  "6")])
+
 (define_split
   [(clobber (match_operand 0 "register_operand"))]
   "HARD_REGISTER_P (operands[0])

Reply via email to