The only pattern for which the len may be zero is cmpstrsni. The other
pattern using rx_cmpstrn is cmpstrsi for which len is a constant -1,
so we'll be moving the setpsw instructions from rx_cmpstrn to
cmpstrnsi as follows:

 1. Adjust the predicate on the length operand from "register_operand"
    to "nonmemory_operand". This will allow constants to appear here,
    instead of having them already transferred into a register.

 2. Check to see if the len value is constant, and then check if it is
    actually zero. In that case, short-circuit the rest of the pattern
    and set the result register to 0.

 3. Emit 'setpsw c' and 'setpsw z' instructions when the len is not a
    constant, in case it turns out to be zero at runtime.

 4. Remove the two 'setpsw' instructions from rx_cmpstrn.

Signed-off-by: Keith Packard <kei...@keithp.com>
---
 gcc/config/rx/rx.md | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
index edb2c96603f..b3f36379fe2 100644
--- a/gcc/config/rx/rx.md
+++ b/gcc/config/rx/rx.md
@@ -2541,10 +2541,20 @@ (define_expand "cmpstrnsi"
        (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand")     ;; 
String1
                             (match_operand:BLK 2 "memory_operand")]    ;; 
String2
                            UNSPEC_CMPSTRN))
-   (use (match_operand:SI                       3 "register_operand"))  ;; Max 
Length
+   (use (match_operand:SI                       3 "nonmemory_operand")) ;; Max 
Length
    (match_operand:SI                            4 "immediate_operand")] ;; 
Known Align
   "rx_allow_string_insns"
   {
+    bool const_len = CONST_INT_P(operands[3]);
+    if (const_len)
+    {
+      if (INTVAL(operands[3]) == 0)
+      {
+        emit_move_insn (operands[0], GEN_INT(0));
+        DONE;
+      }
+    }
+
     rtx str1 = gen_rtx_REG (SImode, 1);
     rtx str2 = gen_rtx_REG (SImode, 2);
     rtx len  = gen_rtx_REG (SImode, 3);
@@ -2553,6 +2563,11 @@ (define_expand "cmpstrnsi"
     emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
     emit_move_insn (len, operands[3]);
 
+    /* Set flags in case len is zero */
+    if (!const_len) {
+      emit_insn (gen_setpsw (GEN_INT('C')));
+      emit_insn (gen_setpsw (GEN_INT('Z')));
+    }
     emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
     DONE;
   }
@@ -2590,9 +2605,7 @@ (define_insn "rx_cmpstrn"
    (clobber (reg:SI 3))
    (clobber (reg:CC CC_REG))]
   "rx_allow_string_insns"
-  "setpsw  z           ; Set flags in case len is zero
-   setpsw  c
-   scmpu               ; Perform the string comparison
+  "scmpu               ; Perform the string comparison
    mov     #-1, %0      ; Set up -1 result (which cannot be created
                         ; by the SC insn)
    bnc    ?+           ; If Carry is not set skip over
-- 
2.49.0

Reply via email to