https://gcc.gnu.org/g:1ec16778312a902592822cbda626241da68ea643

commit r15-3622-g1ec16778312a902592822cbda626241da68ea643
Author: Georg-Johann Lay <a...@gjlay.de>
Date:   Tue Sep 10 17:51:58 2024 +0200

    AVR: Tweak 32-bit EQ and NE comparisons.
    
    The order in which multi-byte EQ and NE comparisons are performing
    the byte comparisons does not matter, and there are situations where
    using SBIW on the high word can save an instruction.
    
    gcc/
            * config/avr/avr.cc (avr_out_compare): Tweak 32-bit EQ and NE
            comparisons that can use SBIW for the hi16 part.

Diff:
---
 gcc/config/avr/avr.cc | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index f743261c6adf..25220c3bc0c7 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -5990,6 +5990,31 @@ avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
        }
     }
 
+  /* Comparisons == and != may change the order in which the sub-bytes are
+     being compared.  Start with the high 16 bits so we can use SBIW.  */
+
+  if (n_bytes == 4
+      && compare_eq_p (insn)
+      && AVR_HAVE_ADIW
+      && REGNO (xreg) >= REG_22)
+    {
+      if (xval == const0_rtx)
+       return avr_asm_len ("sbiw %C0,0"           CR_TAB
+                           "cpc %B0,__zero_reg__" CR_TAB
+                           "cpc %A0,__zero_reg__", xop, plen, 3);
+
+      rtx xhi16 = simplify_gen_subreg (HImode, xval, mode, 2);
+      if (IN_RANGE (UINTVAL (xhi16) & GET_MODE_MASK (HImode), 0, 63)
+         && reg_unused_after (insn, xreg))
+       {
+         xop[1] = xhi16;
+         avr_asm_len ("sbiw %C0,%1", xop, plen, 1);
+         xop[1] = xval;
+         return avr_asm_len ("sbci %B0,hi8(%1)" CR_TAB
+                             "sbci %A0,lo8(%1)", xop, plen, 2);
+       }
+    }
+
   for (int i = 0; i < n_bytes; i++)
     {
       /* We compare byte-wise.  */

Reply via email to