diff mbox

[AVR] : Fix loading ZERO_REG with 0 in ISR prologue

Message ID 4F01D627.9040901@gjlay.de
State New
Headers show

Commit Message

Georg-Johann Lay Jan. 2, 2012, 4:07 p.m. UTC
This is fix for ISR prologue that "cleared" zero reg with

  mov __zero_reg__,__zero_reg__

The right way is

  clr __zero_reg__

of course. As CLR does change cc0 notice_update_cc needs to be adapted.

Passes testsuite. Moreover, lightly tested on ISR source (there is no ISR test
case in test suite).

Ok for trunk?

Johann

	* config/avr/avr.md (cc): Add alternative "ldi".
	(movqi_insn): Use it in cc attribute.
	* config/avr/avr.c (notice_update_cc): Handle CC_LDI.
	(output_reload_in_const): Use CLR to move 0 to ZERO_REG.
	(output_reload_insisf): Use ZERO_REG to pre-clear register.

Comments

Denis Chertykov Jan. 2, 2012, 6:45 p.m. UTC | #1
2012/1/2 Georg-Johann Lay <avr@gjlay.de>:
> This is fix for ISR prologue that "cleared" zero reg with
>
>  mov __zero_reg__,__zero_reg__
>
> The right way is
>
>  clr __zero_reg__
>
> of course. As CLR does change cc0 notice_update_cc needs to be adapted.
>
> Passes testsuite. Moreover, lightly tested on ISR source (there is no ISR test
> case in test suite).
>
> Ok for trunk?
>
> Johann
>
>        * config/avr/avr.md (cc): Add alternative "ldi".
>        (movqi_insn): Use it in cc attribute.
>        * config/avr/avr.c (notice_update_cc): Handle CC_LDI.
>        (output_reload_in_const): Use CLR to move 0 to ZERO_REG.
>        (output_reload_insisf): Use ZERO_REG to pre-clear register.
>

Please commit.

Denis.
diff mbox

Patch

Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md	(revision 182796)
+++ config/avr/avr.md	(working copy)
@@ -95,7 +95,7 @@  (define_c_enum "unspecv"
   
 ;; Condition code settings.
 (define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,
-                   out_plus, out_plus_noclobber"
+                   out_plus, out_plus_noclobber,ldi"
   (const_string "none"))
 
 (define_attr "type" "branch,branch1,arith,xcall"
@@ -584,7 +584,7 @@  (define_insn "movqi_insn"
   }
   [(set_attr "length" "1,1,5,5,1,1,4")
    (set_attr "adjust_len" "mov8")
-   (set_attr "cc" "none,none,clobber,clobber,none,none,clobber")])
+   (set_attr "cc" "ldi,none,clobber,clobber,none,none,clobber")])
 
 ;; This is used in peephole2 to optimize loading immediate constants
 ;; if a scratch register from LD_REGS happens to be available.
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 182796)
+++ config/avr/avr.c	(working copy)
@@ -1994,6 +1994,7 @@  notice_update_cc (rtx body ATTRIBUTE_UNU
 
     case CC_OUT_PLUS:
     case CC_OUT_PLUS_NOCLOBBER:
+    case CC_LDI:
       {
         rtx *op = recog_data.operand;
         int len_dummy, icc;
@@ -2001,16 +2002,36 @@  notice_update_cc (rtx body ATTRIBUTE_UNU
         /* Extract insn's operands.  */
         extract_constrain_insn_cached (insn);
 
-        if (CC_OUT_PLUS == cc)
-          avr_out_plus (op, &len_dummy, &icc);
-        else
-          avr_out_plus_noclobber (op, &len_dummy, &icc);
-        
-        cc = (enum attr_cc) icc;
-        
+        switch (cc)
+          {
+          default:
+            gcc_unreachable();
+            
+          case CC_OUT_PLUS:
+            avr_out_plus (op, &len_dummy, &icc);
+            cc = (enum attr_cc) icc;
+            break;
+            
+          case CC_OUT_PLUS_NOCLOBBER:
+            avr_out_plus_noclobber (op, &len_dummy, &icc);
+            cc = (enum attr_cc) icc;
+            break;
+
+          case CC_LDI:
+
+            cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
+                  && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
+              /* Loading zero-reg with 0 uses CLI and thus clobbers cc0.  */
+              ? CC_CLOBBER
+              /* Any other "r,rL" combination does not alter cc0.  */
+              : CC_NONE;
+            
+            break;
+          } /* inner switch */
+
         break;
       }
-    }
+    } /* outer swicth */
 
   switch (cc)
     {
@@ -8945,9 +8966,9 @@  avr_regno_mode_code_ok_for_base_p (int r
 
    The effect on cc0 is as follows:
 
-   Load 0 to any register          : NONE
-   Load ld register with any value : NONE
-   Anything else:                  : CLOBBER  */
+   Load 0 to any register except ZERO_REG : NONE
+   Load ld register with any value        : NONE
+   Anything else:                         : CLOBBER  */
 
 static void
 output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
@@ -9062,7 +9083,9 @@  output_reload_in_const (rtx *op, rtx clo
       if (ival[n] == 0)
         {
           if (!clear_p)
-            avr_asm_len (ldreg_p ? "ldi %0,0" : "mov %0,__zero_reg__",
+            avr_asm_len (ldreg_p ? "ldi %0,0"
+                         : ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
+                         : "mov %0,__zero_reg__",
                          &xdest[n], len, 1);
           continue;
         }
@@ -9224,8 +9247,8 @@  output_reload_insisf (rtx *op, rtx clobb
         {
           /* Default needs 4 CLR instructions: clear register beforehand.  */
           
-          avr_asm_len ("clr %A0" CR_TAB
-                       "clr %B0" CR_TAB
+          avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
+                       "mov %B0,__zero_reg__" CR_TAB
                        "movw %C0,%A0", &op[0], len, 3);
           
           output_reload_in_const (op, clobber_reg, len, true);