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. */