Am 16.09.24 um 13:04 schrieb Denis Chertykov:
вс, 15 сент. 2024 г. в 19:32, Georg-Johann Lay <a...@gjlay.de>:
Unsigned comparisons may skip comparing the lower bytes when
the according bytes of the constant are all zeros. For example,
uint16 >= 0x1200
is true iff
hi8 (uint16) >= hi8 (0x1200)
and similar for uint16 < 0x1200. Some comparisons against constants
that are an integral power of 256 where already handled in the split
preparation. That code has been outsourced to new avr_maybe_cmp_lsr()
which may change the operands such that the resulting insns become
a comparison of the high bytes against 0 plus a EQ / NE branch.
For example,
uint32 >= 0x10000
can be rewritten as
(uint32 >> 16) != 0.
The according asm output is performed by new avr_out_cmp_lsr().
Ok for trunk?
Please apply.
Denis.
Applied with the following addendum because the same also works
for signed comparisons.
Johann
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 5e5b5779d8a..92013c3845d 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -6152,11 +6152,12 @@ avr_out_compare (rtx_insn *insn, rtx *xop, int
*plen)
bool changed[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- /* Unsigned comparisons may skip the lower bytes when the according bytes
+ /* The >= and < comparisons may skip the lower bytes when the
according bytes
of the constant are all zeros. In that case, the comparison may
start
at a byte other than the LSB. */
- const int start = (cond == GEU || cond == LTU) && INTVAL (xval) != 0
+ const int start = ((cond == GEU || cond == LTU || cond == GE || cond
== LT)
+ && INTVAL (xval) != 0)
? ctz_hwi (INTVAL (xval)) / 8
: 0;
--
gcc/
* config/avr/avr-protos.h (avr_out_cmp_lsr, avr_maybe_cmp_lsr): New.
* config/avr/avr.cc (avr_maybe_cmp_lsr, avr_out_cmp_lsr): New
functions.
(avr_out_compare) [GEU, LTU]: Start output at byte CTZ(xval) / 8.
(avr_adjust_insn_length) [ADJUST_LEN_CMP_LSR]: Handle case.
* config/avr/avr.md (adjust_len) <cmp_lsr>: New attr value.
(*cmp<mode>_lsr): New define_insn_and_split.
(cbranch<mode>4_insn): When splitting, run avr_maybe_cmp_lsr()
which may map the operands to *cmp<mode>_lsr.
gcc/testsuite/
* gcc.target/avr/torture/cmp-lsr-u16.c: New test.
* gcc.target/avr/torture/cmp-lsr-u24.c: New test.
* gcc.target/avr/torture/cmp-lsr-u32.c: New test.
* gcc.target/avr/torture/cmp-lsr-u64.c: New test.