This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch,AVR]: Tweak EQ/NE comparisons against +/-1
- From: Georg-Johann Lay <avr at gjlay dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Denis Chertykov <chertykov at gmail dot com>, Eric Weddington <eric dot weddington at atmel dot com>
- Date: Mon, 26 Sep 2011 15:26:51 +0200
- Subject: [Patch,AVR]: Tweak EQ/NE comparisons against +/-1
This is a minor tweak to do eq/ne comparisons one instruction shorter in the
case where the compare target is unused after the comparison:
For 1:
DEC R0
OR R0,R1
OR R0,R2
OR R0,R3
For -1:
AND R0,R3
AND R0,R2
AND R0,R1
COM R0
The text peephole casesi+2 used 0xffff where -1 is the right canonical
representation, e.g. the following source
char c;
unsigned int cmp_p (unsigned int x)
{
if (--x == 65535)
c = 0;
return x;
}
compiles with -S -Os -dP -fno-peephole to
; (insn 7 6 8 (parallel [
; (set (cc0)
; (compare (reg/v:HI 24 r24 [orig:42 x ] [42])
; (const_int -1 [0xffffffff])))
; (clobber (reg:QI 18 r18))
; ]) cmp.c:6 184 {*cmphi}
; (expr_list:REG_UNUSED (reg:QI 18 r18)
; (nil)))
Fixed that, too. Test suite passes fine.
Ok?
Johann
* config/avr/avr.md (peephole casesi+2): Use -1
instead of 65535.
* config/avr/avr.c (avr_out_compare): Print shorter sequence for
EQ/NE comparisons against +/-1 in the case of unused-after,
non-ld-regs target.
Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md (revision 179191)
+++ config/avr/avr.md (working copy)
@@ -4119,7 +4119,7 @@ (define_peephole
(parallel
[(set (cc0)
(compare (match_dup 0)
- (const_int 65535)))
+ (const_int -1)))
(clobber (match_operand:QI 1 "d_register_operand" ""))])
(set (pc)
(if_then_else (ne (cc0) (const_int 0))
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c (revision 179191)
+++ config/avr/avr.c (working copy)
@@ -3048,6 +3048,37 @@ avr_out_compare (rtx insn, rtx *xop, int
if (plen)
*plen = 0;
+ /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
+ against 0 by ORing the bytes. This is one instruction shorter. */
+
+ if (!test_hard_reg_class (LD_REGS, xreg)
+ && compare_eq_p (insn)
+ && reg_unused_after (insn, xreg))
+ {
+ if (xval == const1_rtx)
+ {
+ avr_asm_len ("dec %A0" CR_TAB
+ "or %A0,%B0", xop, plen, 2);
+
+ if (n_bytes == 4)
+ avr_asm_len ("or %A0,%C0" CR_TAB
+ "or %A0,%D0", xop, plen, 2);
+
+ return "";
+ }
+ else if (xval == constm1_rtx)
+ {
+ if (n_bytes == 4)
+ avr_asm_len ("and %A0,%D0" CR_TAB
+ "and %A0,%C0", xop, plen, 2);
+
+ avr_asm_len ("and %A0,%B0" CR_TAB
+ "com %A0", xop, plen, 2);
+
+ return "";
+ }
+ }
+
for (i = 0; i < n_bytes; i++)
{
/* We compare byte-wise. */