From 4553eccd23d74ba9ad2f862c5e66278a21abfe49 Mon Sep 17 00:00:00 2001 From: Takayuki 'January June' Suwa Date: Fri, 29 Aug 2025 19:19:32 +0900 Subject: xtensa: Optimize branch whether (reg:SI) is within/out the range handled by CLAMPS instruction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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<= -(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. --- gcc/config/xtensa/predicates.md | 3 +++ gcc/config/xtensa/xtensa.md | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) (limited to 'gcc') diff --git a/gcc/config/xtensa/predicates.md b/gcc/config/xtensa/predicates.md index 9aeaba6..20160a4 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 1339b03..52ffb16 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]) -- cgit v1.1