aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2024-09-10 17:51:58 +0200
committerGeorg-Johann Lay <avr@gjlay.de>2024-09-13 11:36:27 +0200
commit1ec16778312a902592822cbda626241da68ea643 (patch)
tree1cf401798939d959a6aa4fde058c0920e148e805
parentbe59aaf13cea06a6dd01736d2c31d1c3bc2a60ee (diff)
downloadgcc-1ec16778312a902592822cbda626241da68ea643.zip
gcc-1ec16778312a902592822cbda626241da68ea643.tar.gz
gcc-1ec16778312a902592822cbda626241da68ea643.tar.bz2
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.
-rw-r--r--gcc/config/avr/avr.cc25
1 files changed, 25 insertions, 0 deletions
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index f743261..25220c3 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. */