https://gcc.gnu.org/g:2a502f9e4c5c6a8e908ef1b0b5c03fb2e4bd4390

commit r15-7796-g2a502f9e4c5c6a8e908ef1b0b5c03fb2e4bd4390
Author: Richard Earnshaw <rearn...@arm.com>
Date:   Mon Mar 3 15:30:58 2025 +0000

    arm: remove some redundant zero_extend ops on thumb1
    
    The code in gcc.target/unsigned-extend-1.c really should not need an
    unsigned extension operations when the optimizers are used.  For Arm
    and thumb2 that is indeed the case, but for thumb1 code it gets more
    complicated as there are too many instructions for combine to look at.
    For thumb1 we end up with two redundant zero_extend patterns which are
    not removed: the first after the subtract instruction and the second of
    the final boolean result.
    
    We can partially fix this (for the second case above) by adding a new
    split pattern for LEU and GEU patterns which work because the two
    instructions for the [LG]EU pattern plus the redundant extension
    instruction are combined into a single insn, which we can then split
    using the 3->2 method back into the two insns of the [LG]EU sequence.
    
    Because we're missing the optimization for all thumb1 cases (not just
    those architectures with UXTB), I've adjust the testcase to detect all
    the idioms that we might use for zero-extending a value, namely:
    
           UXTB
           AND ...#255 (in thumb1 this would require a register to hold 255)
           LSL ... #24; LSR ... #24
    
    but I've also marked this test as XFAIL for thumb1 because we can't yet
    eliminate the first of the two extend instructions.
    
    gcc/
            * config/arm/thumb1.md (split patterns for GEU and LEU): New.
    
    gcc/testsuite:
            * gcc.target/arm/unsigned-extend-1.c: Expand check for any
            insn suggesting a zero-extend.  XFAIL for thumb1 code.

Diff:
---
 gcc/config/arm/thumb1.md                         | 28 ++++++++++++++++++++++++
 gcc/testsuite/gcc.target/arm/unsigned-extend-1.c |  4 ++--
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
index 548c36979f12..f9e89e991d9b 100644
--- a/gcc/config/arm/thumb1.md
+++ b/gcc/config/arm/thumb1.md
@@ -1810,6 +1810,34 @@
    (set_attr "type" "multiple")]
 )
 
+;; Re-split an LEU/GEU sequence if combine tries to oversimplify a 3-plus
+;; insn sequence.  Beware of the early-clobber of operand0
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand")
+       (leu:SI (match_operand:SI 1 "s_register_operand")
+              (match_operand:SI 2 "s_register_operand")))]
+ "TARGET_THUMB1
+  && !reg_overlap_mentioned_p (operands[0], operands[1])
+  && !reg_overlap_mentioned_p (operands[0], operands[2])"
+ [(set (match_dup 0) (const_int 0))
+  (set (match_dup 0) (plus:SI (plus:SI (match_dup 0) (match_dup 0))
+                             (geu:SI (match_dup 2) (match_dup 1))))]
+ {}
+)
+
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand")
+       (geu:SI (match_operand:SI 1 "s_register_operand")
+              (match_operand:SI 2 "thumb1_cmp_operand")))]
+ "TARGET_THUMB1
+  && !reg_overlap_mentioned_p (operands[0], operands[1])
+  && !reg_overlap_mentioned_p (operands[0], operands[2])"
+ [(set (match_dup 0) (const_int 0))
+  (set (match_dup 0) (plus:SI (plus:SI (match_dup 0) (match_dup 0))
+                             (geu:SI (match_dup 1) (match_dup 2))))]
+ {}
+)
+
 
 (define_insn "*thumb_jump"
   [(set (pc)
diff --git a/gcc/testsuite/gcc.target/arm/unsigned-extend-1.c 
b/gcc/testsuite/gcc.target/arm/unsigned-extend-1.c
index 3b4ab048fb09..fa3d34400bfa 100644
--- a/gcc/testsuite/gcc.target/arm/unsigned-extend-1.c
+++ b/gcc/testsuite/gcc.target/arm/unsigned-extend-1.c
@@ -5,5 +5,5 @@ unsigned char foo (unsigned char c)
 {
   return (c >= '0') && (c <= '9');
 }
-
-/* { dg-final { scan-assembler-not "uxtb" } } */
+/* We shouldn't need any zero-extension idioms here.  */
+/* { dg-final { scan-assembler-not "\t(uxtb|and|lsr|lsl)" { xfail arm_thumb1 } 
} } */

Reply via email to