re PR other/50925 ([avr] ICE at spill_failure, at reload1.c:2118)
authorRichard Henderson <rth@redhat.com>
Thu, 12 Jan 2012 18:29:54 +0000 (10:29 -0800)
committerDenis Chertykov <denisc@gcc.gnu.org>
Thu, 12 Jan 2012 18:29:54 +0000 (22:29 +0400)
PR target/50925
* config/avr/avr-protos.h (avr_hard_regno_nregs): Declare.
* config/avr/avr.c (avr_can_eliminate): Simplify.
(avr_initial_elimination_offset): Likewise.
(avr_prologue_setup_frame): Use hard_frame_pointer_rtx.
(expand_epilogue): Likewise.
(avr_legitimize_address): Gut.
(avr_legitimize_reload_address): Use hard_frame_pointer_rtx.
(avr_hard_regno_nregs): New.
(avr_hard_regno_ok): Allow only Pmode for arg and frame_pointers.
(avr_regno_mode_code_ok_for_base_b): Handle arg and frame pointers.
* config/avr/avr.h (FIXED_REGISTERS): Adjust arg pointer,
add soft frame pointer.
(CALL_USED_REGISTERS): Likewise.
(REG_CLASS_CONTENTS): Likewise.
(REGISTER_NAMES): Likewise.
(HARD_REGNO_NREGS): Use avr_hard_regno_nregs.
(HARD_FRAME_POINTER_REGNUM): New.
(FRAME_POINTER_REGNUM): Use soft frame pointer.
(ELIMINABLE_REGS): Eliminate from the soft frame pointer,
remove the HARD_FRAME_POINTER self-elimination.

Co-Authored-By: Denis Chertykov <chertykov@gmail.com>
From-SVN: r183136

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

index eaf050c..837387d 100644 (file)
@@ -1,3 +1,28 @@
+2012-01-09  Richard Henderson  <rth@redhat.com>
+           Denis Chertykov  <chertykov@gmail.com>
+
+       PR target/50925
+       * config/avr/avr-protos.h (avr_hard_regno_nregs): Declare.
+       * config/avr/avr.c (avr_can_eliminate): Simplify.
+       (avr_initial_elimination_offset): Likewise.
+       (avr_prologue_setup_frame): Use hard_frame_pointer_rtx.
+       (expand_epilogue): Likewise.
+       (avr_legitimize_address): Gut.
+       (avr_legitimize_reload_address): Use hard_frame_pointer_rtx.
+       (avr_hard_regno_nregs): New.
+       (avr_hard_regno_ok): Allow only Pmode for arg and frame_pointers.
+       (avr_regno_mode_code_ok_for_base_b): Handle arg and frame pointers.
+       * config/avr/avr.h (FIXED_REGISTERS): Adjust arg pointer,
+       add soft frame pointer.
+       (CALL_USED_REGISTERS): Likewise.
+       (REG_CLASS_CONTENTS): Likewise.
+       (REGISTER_NAMES): Likewise.
+       (HARD_REGNO_NREGS): Use avr_hard_regno_nregs.
+       (HARD_FRAME_POINTER_REGNUM): New.
+       (FRAME_POINTER_REGNUM): Use soft frame pointer.
+       (ELIMINABLE_REGS): Eliminate from the soft frame pointer,
+       remove the HARD_FRAME_POINTER self-elimination.
+
 2012-01-12  Georg-Johann Lay  <avr@gjlay.de>
 
        PR target/51756
index 09f8271..8f6cb87 100644 (file)
@@ -109,6 +109,7 @@ extern int avr_jump_mode (rtx x, rtx insn);
 extern int test_hard_reg_class (enum reg_class rclass, rtx x);
 extern int jump_over_one_insn_p (rtx insn, rtx dest);
 
+extern int avr_hard_regno_nregs (int regno, enum machine_mode mode);
 extern int avr_hard_regno_mode_ok (int regno, enum machine_mode mode);
 extern void final_prescan_insn (rtx insn, rtx *operand, int num_operands);
 extern int avr_simplify_comparison_p (enum machine_mode mode,
index 846c796..5d4dbd3 100644 (file)
@@ -686,31 +686,28 @@ avr_regs_to_save (HARD_REG_SET *set)
 /* Return true if register FROM can be eliminated via register TO.  */
 
 static bool
-avr_can_eliminate (const int from, const int to)
+avr_can_eliminate (int from ATTRIBUTE_UNUSED, int to)
 {
-  return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
-          || (frame_pointer_needed && to == FRAME_POINTER_REGNUM)
-          || ((from == FRAME_POINTER_REGNUM 
-               || from == FRAME_POINTER_REGNUM + 1)
-              && !frame_pointer_needed));
+  return to == HARD_FRAME_POINTER_REGNUM;
 }
 
 /* Compute offset between arg_pointer and frame_pointer.  */
 
 int
-avr_initial_elimination_offset (int from, int to)
+avr_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
 {
-  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
-    return 0;
-  else
+  int offset = 0;
+
+  if (from == ARG_POINTER_REGNUM)
     {
-      int offset = frame_pointer_needed ? 2 : 0;
-      int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
-      
+      offset += AVR_HAVE_EIJMP_EICALL ? 3 : 2;
+      offset += frame_pointer_needed ? 2 : 0;
       offset += avr_regs_to_save (NULL);
-      return (get_frame_size () + avr_outgoing_args_size()
-              + avr_pc_size + 1 + offset);
+      offset += get_frame_size ();
+      offset += 1; /* post-dec stack space */
     }
+
+  return offset;
 }
 
 /* Actual start of frame is virtual_stack_vars_rtx this is offset from 
@@ -902,12 +899,12 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
          notes to the front.  Thus we build them in the reverse order of
          how we want dwarf2out to process them.  */
 
-      /* The function does always set frame_pointer_rtx, but whether that
+      /* The function does always set hard_frame_pointer_rtx, but whether that
          is going to be permanent in the function is frame_pointer_needed.  */
 
       add_reg_note (insn, REG_CFA_ADJUST_CFA,
                     gen_rtx_SET (VOIDmode, (frame_pointer_needed
-                                            ? frame_pointer_rtx
+                                            ? hard_frame_pointer_rtx
                                             : stack_pointer_rtx),
                                  plus_constant (stack_pointer_rtx,
                                                 -(size + live_seq))));
@@ -952,7 +949,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
       if (frame_pointer_needed
           && size == 0)
         {
-          insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+          insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
           RTX_FRAME_RELATED_P (insn) = 1;
         }
       
@@ -987,7 +984,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
                       || !current_function_is_leaf);
           
           fp = my_fp = (frame_pointer_needed
-                        ? frame_pointer_rtx
+                        ? hard_frame_pointer_rtx
                         : gen_rtx_REG (Pmode, REG_X));
           
           if (AVR_HAVE_8BIT_SP)
@@ -995,7 +992,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
               /* The high byte (r29) does not change:
                  Prefer SUBI (1 cycle) over ABIW (2 cycles, same size).  */
 
-              my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
+              my_fp = all_regs_rtx[HARD_FRAME_POINTER_REGNUM];
             }
 
           /************  Method 1: Adjust frame pointer  ************/
@@ -1260,13 +1257,13 @@ expand_epilogue (bool sibcall_p)
       
       if (!frame_pointer_needed)
         {
-          emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+          emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
         }
 
       if (size)
         {
-          emit_move_insn (frame_pointer_rtx,
-                          plus_constant (frame_pointer_rtx, size));
+          emit_move_insn (hard_frame_pointer_rtx,
+                          plus_constant (hard_frame_pointer_rtx, size));
         }
         
       emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
@@ -1285,7 +1282,7 @@ expand_epilogue (bool sibcall_p)
                   || !current_function_is_leaf);
       
       fp = my_fp = (frame_pointer_needed
-                    ? frame_pointer_rtx
+                    ? hard_frame_pointer_rtx
                     : gen_rtx_REG (Pmode, REG_X));
 
       if (AVR_HAVE_8BIT_SP)
@@ -1293,7 +1290,7 @@ expand_epilogue (bool sibcall_p)
           /* The high byte (r29) does not change:
              Prefer SUBI (1 cycle) over SBIW (2 cycles).  */
                   
-          my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
+          my_fp = all_regs_rtx[HARD_FRAME_POINTER_REGNUM];
         }
               
       /********** Method 1: Adjust fp register  **********/
@@ -1534,37 +1531,8 @@ avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
    memory address for an operand of mode MODE  */
 
 static rtx
-avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
+avr_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
 {
-  bool big_offset_p = false;
-  
-  x = oldx;
-  
-  if (GET_CODE (oldx) == PLUS
-      && REG_P (XEXP (oldx, 0)))
-    {
-      if (REG_P (XEXP (oldx, 1)))
-        x = force_reg (GET_MODE (oldx), oldx);
-      else if (CONST_INT_P (XEXP (oldx, 1)))
-        {
-         int offs = INTVAL (XEXP (oldx, 1));
-          if (frame_pointer_rtx != XEXP (oldx, 0)
-              && offs > MAX_LD_OFFSET (mode))
-            {
-              big_offset_p = true;
-              x = force_reg (GET_MODE (oldx), oldx);
-            }
-        }
-    }
-  
-  if (avr_log.legitimize_address)
-    {
-      avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
-
-      if (x != oldx)
-        avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
-    }
-
   return x;
 }
 
@@ -1634,7 +1602,7 @@ avr_legitimize_reload_address (rtx *px, enum machine_mode mode,
             }
         }
       else if (! (frame_pointer_needed
-                  && XEXP (x, 0) == frame_pointer_rtx))
+                  && XEXP (x, 0) == hard_frame_pointer_rtx))
         {
           push_reload (x, NULL_RTX, px, NULL,
                        POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
@@ -8366,6 +8334,19 @@ extra_constraint_Q (rtx x)
   return ok;
 }
 
+/* Returns the number of registers required to hold a value of MODE.  */
+
+int
+avr_hard_regno_nregs (int regno, enum machine_mode mode)
+{
+  /* The fake registers are designed to hold exactly a pointer.  */
+  if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
+    return 1;
+
+  return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+}
+
+
 /* Convert condition code CONDITION to the valid AVR condition code.  */
 
 RTX_CODE
@@ -8789,6 +8770,10 @@ jump_over_one_insn_p (rtx insn, rtx dest)
 int
 avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
 {
+  /* The fake registers are designed to hold exactly a pointer.  */
+  if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
+    return mode == Pmode;
+
   /* NOTE: 8-bit values must not be disallowed for R28 or R29.
         Disallowing QI et al. in these regs might lead to code like
             (set (subreg:QI (reg:HI 28) n) ...)
@@ -8812,7 +8797,6 @@ avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
     return 0;
 
   /* All modes larger than 8 bits should start in an even register.  */
-  
   return !(regno & 1);
 }
 
@@ -8872,7 +8856,8 @@ avr_regno_mode_code_ok_for_base_p (int regno,
       && (regno == REG_X
           || regno == REG_Y
           || regno == REG_Z
-          || regno == ARG_POINTER_REGNUM))
+          || regno == ARG_POINTER_REGNUM
+         || regno == FRAME_POINTER_REGNUM))
     {
       ok = true;
     }
@@ -8883,7 +8868,8 @@ avr_regno_mode_code_ok_for_base_p (int regno,
       if (regno == REG_X
           || regno == REG_Y
           || regno == REG_Z
-          || regno == ARG_POINTER_REGNUM)
+          || regno == ARG_POINTER_REGNUM
+         || regno == FRAME_POINTER_REGNUM)
         {
           ok = true;
         }
index 33017ba..a231b7f 100644 (file)
@@ -231,45 +231,47 @@ enum
 
 #define FIRST_PSEUDO_REGISTER 36
 
-#define FIXED_REGISTERS {\
-  1,1,/* r0 r1 */\
-  0,0,/* r2 r3 */\
-  0,0,/* r4 r5 */\
-  0,0,/* r6 r7 */\
-  0,0,/* r8 r9 */\
-  0,0,/* r10 r11 */\
-  0,0,/* r12 r13 */\
-  0,0,/* r14 r15 */\
-  0,0,/* r16 r17 */\
-  0,0,/* r18 r19 */\
-  0,0,/* r20 r21 */\
-  0,0,/* r22 r23 */\
-  0,0,/* r24 r25 */\
-  0,0,/* r26 r27 */\
-  0,0,/* r28 r29 */\
-  0,0,/* r30 r31 */\
-  1,1,/*  STACK */\
-  1,1 /* arg pointer */  }
+#define FIXED_REGISTERS {                      \
+  1,1,/* r0 r1 */                              \
+  0,0,/* r2 r3 */                              \
+  0,0,/* r4 r5 */                              \
+  0,0,/* r6 r7 */                              \
+  0,0,/* r8 r9 */                              \
+  0,0,/* r10 r11 */                            \
+  0,0,/* r12 r13 */                            \
+  0,0,/* r14 r15 */                            \
+  0,0,/* r16 r17 */                            \
+  0,0,/* r18 r19 */                            \
+  0,0,/* r20 r21 */                            \
+  0,0,/* r22 r23 */                            \
+  0,0,/* r24 r25 */                            \
+  0,0,/* r26 r27 */                            \
+  0,0,/* r28 r29 */                            \
+  0,0,/* r30 r31 */                            \
+  1,1,/*  STACK */                             \
+  1,  /* arg pointer */                                \
+  1   /* frame pointer */ }
 
 #define CALL_USED_REGISTERS {                  \
   1,1,/* r0 r1 */                              \
-    0,0,/* r2 r3 */                            \
-    0,0,/* r4 r5 */                            \
-    0,0,/* r6 r7 */                            \
-    0,0,/* r8 r9 */                            \
-    0,0,/* r10 r11 */                          \
-    0,0,/* r12 r13 */                          \
-    0,0,/* r14 r15 */                          \
-    0,0,/* r16 r17 */                          \
-    1,1,/* r18 r19 */                          \
-    1,1,/* r20 r21 */                          \
-    1,1,/* r22 r23 */                          \
-    1,1,/* r24 r25 */                          \
-    1,1,/* r26 r27 */                          \
-    0,0,/* r28 r29 */                          \
-    1,1,/* r30 r31 */                          \
-    1,1,/*  STACK */                           \
-    1,1 /* arg pointer */  }
+  0,0,/* r2 r3 */                              \
+  0,0,/* r4 r5 */                              \
+  0,0,/* r6 r7 */                              \
+  0,0,/* r8 r9 */                              \
+  0,0,/* r10 r11 */                            \
+  0,0,/* r12 r13 */                            \
+  0,0,/* r14 r15 */                            \
+  0,0,/* r16 r17 */                            \
+  1,1,/* r18 r19 */                            \
+  1,1,/* r20 r21 */                            \
+  1,1,/* r22 r23 */                            \
+  1,1,/* r24 r25 */                            \
+  1,1,/* r26 r27 */                            \
+  0,0,/* r28 r29 */                            \
+  1,1,/* r30 r31 */                            \
+  1,1,/*  STACK */                             \
+  1,  /* arg pointer */                                \
+  1   /* frame pointer */ }
 
 #define REG_ALLOC_ORDER {                      \
     24,25,                                     \
@@ -287,7 +289,7 @@ enum
 #define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc ()
 
 
-#define HARD_REGNO_NREGS(REGNO, MODE) ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+#define HARD_REGNO_NREGS(REGNO, MODE) avr_hard_regno_nregs(REGNO, MODE)
 
 #define HARD_REGNO_MODE_OK(REGNO, MODE) avr_hard_regno_mode_ok(REGNO, MODE)
 
@@ -337,17 +339,17 @@ enum reg_class {
   {3 << REG_Z,0x00000000},      /* POINTER_Z_REGS, r30 - r31 */                \
   {0x00000000,0x00000003},     /* STACK_REG, STACK */                  \
   {(3 << REG_Y) | (3 << REG_Z),                                                \
-     0x00000000},              /* BASE_POINTER_REGS, r28 - r31 */      \
+     0x0000000c},              /* BASE_POINTER_REGS, r28 - r31,ap,fp */ \
   {(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z),                         \
-     0x00000000},              /* POINTER_REGS, r26 - r31 */           \
+     0x0000000c},              /* POINTER_REGS, r26 - r31 */           \
   {(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z) | (3 << REG_W),          \
      0x00000000},              /* ADDW_REGS, r24 - r31 */              \
   {0x00ff0000,0x00000000},     /* SIMPLE_LD_REGS r16 - r23 */          \
   {(3 << REG_X)|(3 << REG_Y)|(3 << REG_Z)|(3 << REG_W)|(0xff << 16),   \
-     0x00000000},      /* LD_REGS, r16 - r31 */                        \
+     0x0000000c},      /* LD_REGS, r16 - r31 */                        \
   {0x0000ffff,0x00000000},     /* NO_LD_REGS  r0 - r15 */              \
-  {0xffffffff,0x00000000},     /* GENERAL_REGS, r0 - r31 */            \
-  {0xffffffff,0x00000003}      /* ALL_REGS */                          \
+  {0xffffffff,0x0000000c},     /* GENERAL_REGS, r0 - r31 */            \
+  {0xffffffff,0x0000000f}      /* ALL_REGS */                          \
 }
 
 #define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
@@ -378,18 +380,20 @@ enum reg_class {
 
 #define STACK_POINTER_REGNUM 32
 
-#define FRAME_POINTER_REGNUM REG_Y
+#define HARD_FRAME_POINTER_REGNUM REG_Y
 
 #define ARG_POINTER_REGNUM 34
+#define FRAME_POINTER_REGNUM 35
 
 #define STATIC_CHAIN_REGNUM 2
 
 #define ELIMINABLE_REGS {                                      \
-      {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},              \
-       {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}            \
-       ,{FRAME_POINTER_REGNUM+1,STACK_POINTER_REGNUM+1}}
+     { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM },             \
+     { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM },                \
+     { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM },           \
+     { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }}
 
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)   \
   OFFSET = avr_initial_elimination_offset (FROM, TO)
 
 #define RETURN_ADDR_RTX(count, tem) avr_return_addr_rtx (count, tem)
@@ -493,7 +497,7 @@ typedef struct avr_args {
     "r8","r9","r10","r11","r12","r13","r14","r15",     \
     "r16","r17","r18","r19","r20","r21","r22","r23",   \
     "r24","r25","r26","r27","r28","r29","r30","r31",   \
-    "__SP_L__","__SP_H__","argL","argH"}
+    "__SP_L__","__SP_H__","ap","fp"}
 
 #define FINAL_PRESCAN_INSN(insn, operand, nop) final_prescan_insn (insn, operand,nop)