This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]