https://gcc.gnu.org/g:40209cb15a3f2af8233ee887dc960992f358ad86

commit r14-9389-g40209cb15a3f2af8233ee887dc960992f358ad86
Author: Georg-Johann Lay <a...@gjlay.de>
Date:   Fri Mar 8 13:29:13 2024 +0100

    AVR: Add an insn combine pattern for offset computation.
    
    Computing  uint16_t += 2 * uint8_t  can occur when an offset
    into a 16-bit array is computed.  Without this pattern is costs
    six instructions: A move (1), a zero-extend (1), a shift (2) and
    an addition (2).  With this pattern it costs 4.
    
    gcc/
            * config/avr/avr.md (*addhi3_zero_extend.ashift1): New pattern.
            * config/avr/avr.cc (avr_rtx_costs_1) [PLUS]: Compute its cost.

Diff:
---
 gcc/config/avr/avr.cc | 11 +++++++++++
 gcc/config/avr/avr.md | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index b87ae6a256d..1fa4b557f5d 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -12513,6 +12513,17 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int 
outer_code,
       return true;
 
     case PLUS:
+      // uint16_t += 2 * uint8_t;
+      if (mode == HImode
+         && GET_CODE (XEXP (x, 0)) == ASHIFT
+         && REG_P (XEXP (x, 1))
+         && XEXP (XEXP (x, 0), 1) == const1_rtx
+         && GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND)
+       {
+         *total = COSTS_N_INSNS (4);
+         return true;
+       }
+
       if (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
          && REG_P (XEXP (x, 1)))
        {
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index bc8a59c956c..52b6cff4a8b 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -1630,6 +1630,39 @@
   "subi %A0,%n2\;sbc %B0,%B0"
   [(set_attr "length" "2")])
 
+
+;; Occurs when computing offsets into 16-bit arrays.
+;; Saves up to 2 instructions.
+(define_insn_and_split "*addhi3_zero_extend.ashift1.split"
+  [(set (match_operand:HI 0 "register_operand"                                 
   "=r")
+        (plus:HI (ashift:HI (zero_extend:HI (match_operand:QI 1 
"register_operand" "r"))
+                            (const_int 1))
+                 (match_operand:HI 2 "register_operand"                        
    "0")))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(parallel [(set (match_dup 0)
+                   (plus:HI (ashift:HI (zero_extend:HI (match_dup 1))
+                                       (const_int 1))
+                            (match_dup 2)))
+              (clobber (reg:CC REG_CC))])])
+
+(define_insn "*addhi3_zero_extend.ashift1"
+  [(set (match_operand:HI 0 "register_operand"                                 
   "=r")
+        (plus:HI (ashift:HI (zero_extend:HI (match_operand:QI 1 
"register_operand" "r"))
+                            (const_int 1))
+                 (match_operand:HI 2 "register_operand"                        
    "0")))
+   (clobber (reg:CC REG_CC))]
+  "reload_completed"
+  {
+    return reg_overlap_mentioned_p (operands[1], operands[0])
+      ? "mov __tmp_reg__,%1\;add %A0,__tmp_reg__\;adc %B0,__zero_reg__\;add 
%A0,__tmp_reg__\;adc %B0,__zero_reg__"
+      : "add %A0,%1\;adc %B0,__zero_reg__\;add %A0,%1\;adc %B0,__zero_reg__";
+  }
+  [(set (attr "length")
+        (symbol_ref ("4 + reg_overlap_mentioned_p (operands[1], 
operands[0])")))])
+
+
 (define_insn_and_split "*usum_widenqihi3_split"
   [(set (match_operand:HI 0 "register_operand"                          "=r")
         (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand"  "0"))

Reply via email to