]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
avr-protos.h (output_reload_inhi): Change prototype.
authorGeorg-Johann Lay <avr@gjlay.de>
Mon, 26 Sep 2011 08:14:25 +0000 (08:14 +0000)
committerGeorg-Johann Lay <gjl@gcc.gnu.org>
Mon, 26 Sep 2011 08:14:25 +0000 (08:14 +0000)
* config/avr/avr-protos.h (output_reload_inhi): Change prototype.
* config/avr/avr.md (adjust_len): Add "reload_in16" alternative.
(*reload_inhi): Use it.  Adapt call to output_reload_inhi to new
prototype.
(*movhi): Split constraint alternative "r,rL" into "r,r" and "r,L".
* config/avr/avr.c: Rename output_reload_insisf_1 to
output_reload_in_const.
(avr_popcount_each_byte): Handle SFmode, too.
(output_reload_in_const): Change so it can handle HI loads, too.
Use avr_popcount_each_byte to work out if scratch register must be
created on the fly.
(output_reload_inhi): Rewrite using output_reload_in_const and...
(output_movhi): ...use it to print constants' loads.
(adjust_insn_length): New case ADJUST_LEN_RELOAD_IN16. Cleanup code.

From-SVN: r179181

gcc/ChangeLog
gcc/config/avr/avr-protos.h
gcc/config/avr/avr.c
gcc/config/avr/avr.md

index 848cb32573db7e383f410fb40ca34044744a29f8..71ab33bbd6246c2dd2b5665d920110302ea5aee1 100644 (file)
@@ -1,3 +1,20 @@
+2011-09-26  Georg-Johann Lay  <avr@gjlay.de>
+
+       * config/avr/avr-protos.h (output_reload_inhi): Change prototype.
+       * config/avr/avr.md (adjust_len): Add "reload_in16" alternative.
+       (*reload_inhi): Use it.  Adapt call to output_reload_inhi to new
+       prototype.
+       (*movhi): Split constraint alternative "r,rL" into "r,r" and "r,L".
+       * config/avr/avr.c: Rename output_reload_insisf_1 to
+       output_reload_in_const.
+       (avr_popcount_each_byte): Handle SFmode, too.
+       (output_reload_in_const): Change so it can handle HI loads, too.
+       Use avr_popcount_each_byte to work out if scratch register must be
+       created on the fly.
+       (output_reload_inhi): Rewrite using output_reload_in_const and...
+       (output_movhi): ...use it to print constants' loads.
+       (adjust_insn_length): New case ADJUST_LEN_RELOAD_IN16. Cleanup code.
+
 2011-09-25  David S. Miller  <davem@davemloft.net>
 
        * config/sparc/constraints.md (C, P, Z): New constraints for
index 2fa8ce1c654d20111f2ddb593f65d02ffcc489fc..fe02dc97e4e0e16683c7cddaa7b62f22c869841f 100644 (file)
@@ -87,7 +87,7 @@ extern bool avr_popcount_each_byte (rtx, int, int);
 
 extern int extra_constraint_Q (rtx x);
 extern int adjust_insn_length (rtx insn, int len);
-extern const char *output_reload_inhi (rtx insn, rtx *operands, int *len);
+extern const char* output_reload_inhi (rtx*, rtx, int*);
 extern const char *output_reload_insisf (rtx insn, rtx *operands, rtx clobber, int *len);
 extern void notice_update_cc (rtx body, rtx insn);
 extern void print_operand (FILE *file, rtx x, int code);
index fbc9b972a1de6b48e44b587836f618d1fa6c74e9..8f4ae97ae8bc7cc860d7d0b3164fb4318acc0897 100644 (file)
@@ -319,19 +319,24 @@ avr_popcount (unsigned int val)
 }
 
 
-/* Constraint helper function.  XVAL is an CONST_INT.  Return true if the least
-   significant N_BYTES bytes of XVAL all have a popcount in POP_MASK and false,
-   otherwise.  POP_MASK represents a subset of integers which contains an
-   integer N iff bit N of POP_MASK is set.  */
+/* Constraint helper function.  XVAL is a CONST_INT or a CONST_DOUBLE.
+   Return true if the least significant N_BYTES bytes of XVAL all have a
+   popcount in POP_MASK and false, otherwise.  POP_MASK represents a subset
+   of integers which contains an integer N iff bit N of POP_MASK is set.  */
    
 bool
 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
 {
   int i;
 
+  enum machine_mode mode = GET_MODE (xval);
+
+  if (VOIDmode == mode)
+    mode = SImode;
+
   for (i = 0; i < n_bytes; i++)
     {
-      rtx xval8 = simplify_gen_subreg (QImode, xval, SImode, i);
+      rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
 
       if (0 == (pop_mask & (1 << avr_popcount (val8))))
@@ -2077,84 +2082,9 @@ output_movhi (rtx insn, rtx operands[], int *l)
            }
        }
       else if (CONSTANT_P (src))
-       {
-         if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
-           {
-             *l = 2;
-             return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
-                     AS2 (ldi,%B0,hi8(%1)));
-           }
-         
-         if (GET_CODE (src) == CONST_INT)
-           {
-             if (src == const0_rtx) /* mov r,L */
-               {
-                 *l = 2;
-                 return (AS1 (clr,%A0) CR_TAB
-                         AS1 (clr,%B0));
-               }
-             else if (src == const1_rtx)
-               {
-                 *l = 3;
-                 return (AS1 (clr,%A0) CR_TAB
-                         AS1 (clr,%B0) CR_TAB
-                         AS1 (inc,%A0));
-               }
-             else if (src == constm1_rtx)
-               {
-                 /* Immediate constants -1 to any register */
-                 *l = 3;
-                 return (AS1 (clr,%0)  CR_TAB
-                         AS1 (dec,%A0) CR_TAB
-                         AS2 (mov,%B0,%A0));
-               }
-             else
-               {
-                 int bit_nr = exact_log2 (INTVAL (src));
-
-                 if (bit_nr >= 0)
-                   {
-                     *l = 4;
-                     if (!real_l)
-                       output_asm_insn ((AS1 (clr,%A0) CR_TAB
-                                         AS1 (clr,%B0) CR_TAB
-                                         "set"), operands);
-                     if (!real_l)
-                       avr_output_bld (operands, bit_nr);
-
-                     return "";
-                   }
-               }
-
-             if ((INTVAL (src) & 0xff) == 0)
-               {
-                 *l = 5;
-                 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
-                         AS1 (clr,%A0)             CR_TAB
-                         AS2 (ldi,r31,hi8(%1))     CR_TAB
-                         AS2 (mov,%B0,r31)         CR_TAB
-                         AS2 (mov,r31,__tmp_reg__));
-               }
-             else if ((INTVAL (src) & 0xff00) == 0)
-               {
-                 *l = 5;
-                 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
-                         AS2 (ldi,r31,lo8(%1))     CR_TAB
-                         AS2 (mov,%A0,r31)         CR_TAB
-                         AS1 (clr,%B0)             CR_TAB
-                         AS2 (mov,r31,__tmp_reg__));
-               }
-           }
-         
-         /* Last resort, equal to loading from memory.  */
-         *l = 6;
-         return (AS2 (mov,__tmp_reg__,r31) CR_TAB
-                 AS2 (ldi,r31,lo8(%1))     CR_TAB
-                 AS2 (mov,%A0,r31)         CR_TAB
-                 AS2 (ldi,r31,hi8(%1))     CR_TAB
-                 AS2 (mov,%B0,r31)         CR_TAB
-                 AS2 (mov,r31,__tmp_reg__));
-       }
+        {
+          return output_reload_inhi (operands, NULL, real_l);
+        }
       else if (GET_CODE (src) == MEM)
        return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
     }
@@ -5125,6 +5055,10 @@ adjust_insn_length (rtx insn, int len)
       
       switch (adjust_len)
         {
+        case ADJUST_LEN_RELOAD_IN16:
+          output_reload_inhi (op, op[2], &len);
+          break;
+          
         case ADJUST_LEN_RELOAD_IN32:
           output_reload_insisf (insn, op, op[2], &len);
           break;
@@ -5185,31 +5119,7 @@ adjust_insn_length (rtx insn, int len)
       op[1] = SET_SRC (set);
       op[0] = SET_DEST (set);
 
-      if (GET_CODE (patt) == PARALLEL
-         && general_operand (op[1], VOIDmode)
-         && general_operand (op[0], VOIDmode))
-       {
-         if (XVECLEN (patt, 0) == 2)
-           op[2] = XVECEXP (patt, 0, 1);
-
-         switch (GET_MODE (op[0]))
-           {
-           case QImode:
-             len = 2;
-             break;
-           case HImode:
-             output_reload_inhi (insn, op, &len);
-             break;
-           case SImode:
-           case SFmode:
-             /* Handled by ADJUST_LEN_RELOAD_INSISF above.  */
-             gcc_unreachable();
-             break;
-           default:
-             break;
-           }
-       }
-      else if (GET_CODE (op[1]) == ASHIFT
+      if (GET_CODE (op[1]) == ASHIFT
          || GET_CODE (op[1]) == ASHIFTRT
          || GET_CODE (op[1]) == LSHIFTRT)
        {
@@ -7153,45 +7063,6 @@ avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
   return !(regno & 1);
 }
 
-const char *
-output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
-{
-  int tmp;
-  if (!len)
-    len = &tmp;
-      
-  if (GET_CODE (operands[1]) == CONST_INT)
-    {
-      int val = INTVAL (operands[1]);
-      if ((val & 0xff) == 0)
-       {
-         *len = 3;
-         return (AS2 (mov,%A0,__zero_reg__) CR_TAB
-                 AS2 (ldi,%2,hi8(%1))       CR_TAB
-                 AS2 (mov,%B0,%2));
-       }
-      else if ((val & 0xff00) == 0)
-       {
-         *len = 3;
-         return (AS2 (ldi,%2,lo8(%1)) CR_TAB
-                 AS2 (mov,%A0,%2)     CR_TAB
-                 AS2 (mov,%B0,__zero_reg__));
-       }
-      else if ((val & 0xff) == ((val & 0xff00) >> 8))
-       {
-         *len = 3;
-         return (AS2 (ldi,%2,lo8(%1)) CR_TAB
-                 AS2 (mov,%A0,%2)     CR_TAB
-                 AS2 (mov,%B0,%2));
-       }
-    }
-  *len = 4;
-  return (AS2 (ldi,%2,lo8(%1)) CR_TAB
-         AS2 (mov,%A0,%2)     CR_TAB
-         AS2 (ldi,%2,hi8(%1)) CR_TAB
-         AS2 (mov,%B0,%2));
-}
-
 
 /* A helper for `output_reload_insisf'.  */
 /* Set 32-bit register OP[0] to compile-time constant OP[1].
@@ -7203,7 +7074,7 @@ output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
    If CLEAR_P is false, nothing is known about OP[0].  */
 
 static void
-output_reload_insisf_1 (rtx *op, rtx clobber_reg, int *len, bool clear_p)
+output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
 {
   rtx src = op[1];
   rtx dest = op[0];
@@ -7223,7 +7094,8 @@ output_reload_insisf_1 (rtx *op, rtx clobber_reg, int *len, bool clear_p)
   /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
      but has some subregs that are in LD_REGS.  Use the MSB (REG:QI 17).  */
   
-  if (14 == REGNO (dest))
+  if (14 == REGNO (dest)
+      && 4 == GET_MODE_SIZE (mode))
     {
       clobber_reg = gen_rtx_REG (QImode, 17);
     }
@@ -7233,25 +7105,16 @@ output_reload_insisf_1 (rtx *op, rtx clobber_reg, int *len, bool clear_p)
      a byte that is neither 0, -1 or a power of 2.  */
   
   if (NULL_RTX == clobber_reg
-      && !test_hard_reg_class (LD_REGS, dest))
+      && !test_hard_reg_class (LD_REGS, dest)
+      && !avr_popcount_each_byte (src, GET_MODE_SIZE (mode),
+                                  (1 << 0) | (1 << 1) | (1 << 8)))
     {
-      for (n = 0; n < GET_MODE_SIZE (mode); n++)
-        {
-          xval = simplify_gen_subreg (QImode, src, mode, n);
-
-          if (!(const0_rtx == xval
-                || constm1_rtx == xval
-                || single_one_operand (xval, QImode)))
-            {
-              /* We have no clobber reg but need one.  Cook one up.
-                 That's cheaper than loading from constant pool.  */
-              
-              cooked_clobber_p = true;
-              clobber_reg = gen_rtx_REG (QImode, REG_Z + 1);
-              avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
-              break;
-            }
-        }
+      /* We have no clobber register but need one.  Cook one up.
+         That's cheaper than loading from constant pool.  */
+      
+      cooked_clobber_p = true;
+      clobber_reg = gen_rtx_REG (QImode, REG_Z + 1);
+      avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
     }
 
   /* Now start filling DEST from LSB to MSB.  */
@@ -7396,6 +7259,63 @@ output_reload_insisf_1 (rtx *op, rtx clobber_reg, int *len, bool clear_p)
 }
 
 
+/* Reload the constant OP[1] into the HI register OP[0].
+   CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
+   into a NO_LD_REGS register.  If CLOBBER_REG is NULL_RTX we either don't
+   need a clobber reg or have to cook one up.
+
+   PLEN == NULL: Output instructions.
+   PLEN != NULL: Output nothing.  Set *PLEN to number of words occupied
+                 by the insns printed.
+
+   Return "".  */
+
+const char*
+output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
+{
+  if (CONST_INT_P (op[1]))
+    {
+      output_reload_in_const (op, clobber_reg, plen, false);
+    }
+  else if (test_hard_reg_class (LD_REGS, op[0]))
+    {
+      avr_asm_len ("ldi %A0,lo8(%1)" CR_TAB
+                   "ldi %B0,hi8(%1)", op, plen, -2);
+    }
+  else
+    {
+      rtx xop[3];
+
+      xop[0] = op[0];
+      xop[1] = op[1];
+      xop[2] = clobber_reg;
+      
+      if (plen)
+        *plen = 0;
+      
+      if (clobber_reg == NULL_RTX)
+        {
+          /* No scratch register provided: cook une up.  */
+          
+          xop[2] = gen_rtx_REG (QImode, REG_Z + 1);
+          avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
+        }
+      
+      avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
+                   "mov %A0,%2"     CR_TAB
+                   "ldi %2,hi8(%1)" CR_TAB
+                   "mov %B0,%2", xop, plen, 4);
+
+      if (clobber_reg == NULL_RTX)
+        {
+          avr_asm_len ("mov %2,__tmp_reg__", xop, plen, 1);
+        }
+    }
+
+  return "";
+}
+
+
 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
    CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
    into a NO_LD_REGS register.  If CLOBBER_REG is NULL_RTX we either don't
@@ -7432,8 +7352,8 @@ output_reload_insisf (rtx insn ATTRIBUTE_UNUSED,
          Instead, we call the print function twice to get the lengths of
          both methods and use the shortest one.  */
          
-      output_reload_insisf_1 (op, clobber_reg, &len_clr, true);
-      output_reload_insisf_1 (op, clobber_reg, &len_noclr, false);
+      output_reload_in_const (op, clobber_reg, &len_clr, true);
+      output_reload_in_const (op, clobber_reg, &len_noclr, false);
       
       if (len_noclr - len_clr == 4)
         {
@@ -7443,7 +7363,7 @@ output_reload_insisf (rtx insn ATTRIBUTE_UNUSED,
                        "clr %B0" CR_TAB
                        "movw %C0,%A0", &op[0], len, 3);
           
-          output_reload_insisf_1 (op, clobber_reg, len, true);
+          output_reload_in_const (op, clobber_reg, len, true);
           
           if (len)
             *len += 3;
@@ -7454,7 +7374,7 @@ output_reload_insisf (rtx insn ATTRIBUTE_UNUSED,
 
   /* Default: destination not pre-cleared.  */
 
-  output_reload_insisf_1 (op, clobber_reg, len, false);
+  output_reload_in_const (op, clobber_reg, len, false);
   return "";
 }
 
index 06e00392dbc8836a57aee4436b6fb8ecfdcca498..294023076182150afdd5999b472d157cb074f3d3 100644 (file)
 ;; Otherwise do special processing depending on the attribute.
 
 (define_attr "adjust_len"
-  "yes,no,reload_in32,out_bitop,out_plus,tsthi,tstsi,compare"
+  "yes,no,reload_in16,reload_in32,out_bitop,out_plus,tsthi,tstsi,compare"
   (const_string "yes"))
 
 ;; Define mode iterators
         (match_operand:HI 1 "immediate_operand" "i"))
    (clobber (match_operand:QI 2 "register_operand" "=&d"))]
   "reload_completed"
-  "* return output_reload_inhi (insn, operands, NULL);"
+  {
+    return output_reload_inhi (operands, operands[2], NULL);
+  }
   [(set_attr "length" "4")
+   (set_attr "adjust_len" "reload_in16")
    (set_attr "cc" "none")])
 
 (define_insn "*movhi"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,d,*r,q,r")
-        (match_operand:HI 1 "general_operand"       "rL,m,rL,i,i,r,q"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,d,*r,q,r")
+        (match_operand:HI 1 "general_operand"       "r,L,m,rL,i,i,r,q"))]
   "(register_operand (operands[0],HImode)
     || register_operand (operands[1],HImode) || const0_rtx == operands[1])"
   "* return output_movhi (insn, operands, NULL);"
-  [(set_attr "length" "2,6,7,2,6,5,2")
-   (set_attr "cc" "none,clobber,clobber,none,clobber,none,none")])
+  [(set_attr "length" "2,2,6,7,2,6,5,2")
+   (set_attr "cc" "none,clobber,clobber,clobber,none,clobber,none,none")])
 
 (define_peephole2 ; movw
   [(set (match_operand:QI 0 "even_register_operand" "")