OSDN Git Service

2010-04-09 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / config / rs6000 / rs6000.c
index 61140a2..2817706 100644 (file)
@@ -115,16 +115,14 @@ typedef struct rs6000_stack {
    This is added to the cfun structure.  */
 typedef struct GTY(()) machine_function
 {
+  /* Flags if __builtin_return_address (n) with n >= 1 was used.  */
+  int ra_needs_full_frame;
   /* Some local-dynamic symbol.  */
   const char *some_ld_name;
   /* Whether the instruction chain has been scanned already.  */
   int insn_chain_scanned_p;
-  /* Flags if __builtin_return_address (n) with n >= 1 was used.  */
-  int ra_needs_full_frame;
   /* Flags if __builtin_return_address (0) was used.  */
   int ra_need_lr;
-  /* Cache lr_save_p after expansion of builtin_eh_return.  */
-  int lr_save_state;
   /* Offset from virtual_stack_vars_rtx to the start of the ABI_V4
      varargs save area.  */
   HOST_WIDE_INT varargs_save_offset;
@@ -883,6 +881,7 @@ static bool spe_func_has_64bit_regs_p (void);
 static void emit_frame_save (rtx, rtx, enum machine_mode, unsigned int,
                             int, HOST_WIDE_INT);
 static rtx gen_frame_mem_offset (enum machine_mode, rtx, int);
+static void rs6000_emit_allocate_stack (HOST_WIDE_INT, int, int);
 static unsigned rs6000_hash_constant (rtx);
 static unsigned toc_hash_function (const void *);
 static int toc_hash_eq (const void *, const void *);
@@ -898,7 +897,6 @@ static bool no_global_regs_above (int, bool);
 static void rs6000_assemble_visibility (tree, int);
 #endif
 static int rs6000_ra_ever_killed (void);
-static bool rs6000_attribute_takes_identifier_p (const_tree);
 static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
 static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
 static bool rs6000_ms_bitfield_layout_p (const_tree);
@@ -1119,9 +1117,9 @@ rtx (*rs6000_legitimize_reload_address_ptr) (rtx, enum machine_mode, int, int,
                                             int, int *)
   = rs6000_legitimize_reload_address;
 
-static bool rs6000_mode_dependent_address (const_rtx);
-static bool rs6000_debug_mode_dependent_address (const_rtx);
-bool (*rs6000_mode_dependent_address_ptr) (const_rtx)
+static bool rs6000_mode_dependent_address (rtx);
+static bool rs6000_debug_mode_dependent_address (rtx);
+bool (*rs6000_mode_dependent_address_ptr) (rtx)
   = rs6000_mode_dependent_address;
 
 static enum reg_class rs6000_secondary_reload_class (enum reg_class,
@@ -1281,8 +1279,6 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #define TARGET_ATTRIBUTE_TABLE rs6000_attribute_table
 #undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
 #define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES rs6000_set_default_type_attributes
-#undef TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P
-#define TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P rs6000_attribute_takes_identifier_p
 
 #undef TARGET_ASM_ALIGNED_DI_OP
 #define TARGET_ASM_ALIGNED_DI_OP DOUBLE_INT_ASM_OP
@@ -4187,7 +4183,7 @@ paired_emit_vector_compare (enum rtx_code rcode,
                             rtx cc_op0, rtx cc_op1)
 {
   rtx tmp = gen_reg_rtx (V2SFmode);
-  rtx tmp1, max, min;
+  rtx tmp1, max, min, equal_zero;
 
   gcc_assert (TARGET_PAIRED_FLOAT);
   gcc_assert (GET_MODE (op0) == GET_MODE (op1));
@@ -4214,8 +4210,8 @@ paired_emit_vector_compare (enum rtx_code rcode,
       tmp1 = gen_reg_rtx (V2SFmode);
       max = gen_reg_rtx (V2SFmode);
       min = gen_reg_rtx (V2SFmode);
-      gen_reg_rtx (V2SFmode);
-      
+      equal_zero = gen_reg_rtx (V2SFmode);
+
       emit_insn (gen_subv2sf3 (tmp, cc_op0, cc_op1));
       emit_insn (gen_selv2sf4
                  (max, tmp, cc_op0, cc_op1, CONST0_RTX (SFmode)));
@@ -5416,14 +5412,14 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
              else
                {
                  rtx tmp3, mem;
-                 rtx last;
+                 rtx first, last;
 
                  tmp1 = gen_reg_rtx (Pmode);
                  tmp2 = gen_reg_rtx (Pmode);
                  tmp3 = gen_reg_rtx (Pmode);
                  mem = gen_const_mem (Pmode, tmp1);
 
-                 emit_insn (gen_load_toc_v4_PIC_1b (gsym));
+                 first = emit_insn (gen_load_toc_v4_PIC_1b (gsym));
                  emit_move_insn (tmp1,
                                  gen_rtx_REG (Pmode, LR_REGNO));
                  emit_move_insn (tmp2, mem);
@@ -5897,7 +5893,7 @@ rs6000_debug_legitimate_address_p (enum machine_mode mode, rtx x,
    sub-words of a TFmode operand, which is what we had before.  */
 
 static bool
-rs6000_mode_dependent_address (const_rtx addr)
+rs6000_mode_dependent_address (rtx addr)
 {
   switch (GET_CODE (addr))
     {
@@ -5937,7 +5933,7 @@ rs6000_mode_dependent_address (const_rtx addr)
 
 /* Debug version of rs6000_mode_dependent_address.  */
 static bool
-rs6000_debug_mode_dependent_address (const_rtx addr)
+rs6000_debug_mode_dependent_address (rtx addr)
 {
   bool ret = rs6000_mode_dependent_address (addr);
 
@@ -10152,7 +10148,7 @@ altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
   tree arg0, arg1, arg2;
-  enum machine_mode mode0, mode1;
+  enum machine_mode mode0, mode1, mode2;
   rtx pat, op0, op1, op2;
   const struct builtin_description *d;
   size_t i;
@@ -10172,6 +10168,7 @@ altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
        op2 = expand_normal (arg2);
        mode0 = insn_data[d->icode].operand[0].mode;
        mode1 = insn_data[d->icode].operand[1].mode;
+       mode2 = insn_data[d->icode].operand[2].mode;
 
        /* Invalid arguments, bail out before generating bad rtl.  */
        if (arg0 == error_mark_node
@@ -17730,9 +17727,6 @@ rs6000_ra_ever_killed (void)
   if (cfun->is_thunk)
     return 0;
 
-  if (cfun->machine->lr_save_state)
-    return cfun->machine->lr_save_state - 1;
-
   /* regs_ever_live has LR marked as used if any sibcalls are present,
      but this should not force saving and restoring in the
      pro/epilogue.  Likewise, reg_set_between_p thinks a sibcall
@@ -17902,12 +17896,6 @@ rs6000_emit_eh_reg_restore (rtx source, rtx scratch)
     }
   else
     emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), operands[0]);
-
-  /* Freeze lr_save_p.  We've just emitted rtl that depends on the
-     state of lr_save_p so any change from here on would be a bug.  In
-     particular, stop rs6000_ra_ever_killed from considering the SET
-     of lr we may have added just above.  */ 
-  cfun->machine->lr_save_state = info->lr_save_p + 1;
 }
 
 static GTY(()) alias_set_type set = -1;
@@ -18034,11 +18022,13 @@ rs6000_emit_stack_tie (void)
 }
 
 /* Emit the correct code for allocating stack space, as insns.
-   If COPY_REG, make sure a copy of the old frame is left there.
+   If COPY_R12, make sure a copy of the old frame is left in r12.
+   If COPY_R11, make sure a copy of the old frame is left in r11,
+   in preference to r12 if COPY_R12.
    The generated code may use hard register 0 as a temporary.  */
 
 static void
-rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg)
+rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12, int copy_r11)
 {
   rtx insn;
   rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
@@ -18081,8 +18071,11 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg)
        warning (0, "stack limit expression is not supported");
     }
 
-  if (copy_reg)
-    emit_move_insn (copy_reg, stack_reg);
+  if (copy_r12 || copy_r11)
+    emit_move_insn (copy_r11
+                    ? gen_rtx_REG (Pmode, 11)
+                    : gen_rtx_REG (Pmode, 12),
+                    stack_reg);
 
   if (size > 32767)
     {
@@ -18768,33 +18761,20 @@ rs6000_emit_prologue (void)
                       ? (!saving_GPRs_inline
                          && info->spe_64bit_regs_used == 0)
                       : (!saving_FPRs_inline || !saving_GPRs_inline));
-      rtx copy_reg = need_r11 ? gen_rtx_REG (Pmode, 11) : NULL;
-
       if (info->total_size < 32767)
        sp_offset = info->total_size;
-      else if (need_r11)
-       frame_reg_rtx = copy_reg;
-      else if (info->cr_save_p
-              || info->lr_save_p
-              || info->first_fp_reg_save < 64
-              || info->first_gp_reg_save < 32
-              || info->altivec_size != 0
-              || info->vrsave_mask != 0
-              || crtl->calls_eh_return)
-       {
-         copy_reg = frame_ptr_rtx;
-         frame_reg_rtx = copy_reg;
-       }
       else
-       {
-         /* The prologue won't be saving any regs so there is no need
-            to set up a frame register to access any frame save area.
-            We also won't be using sp_offset anywhere below, but set
-            the correct value anyway to protect against future
-            changes to this function.  */
-         sp_offset = info->total_size;
-       }
-      rs6000_emit_allocate_stack (info->total_size, copy_reg);
+       frame_reg_rtx = (need_r11
+                        ? gen_rtx_REG (Pmode, 11)
+                        : frame_ptr_rtx);
+      rs6000_emit_allocate_stack (info->total_size,
+                                 (frame_reg_rtx != sp_reg_rtx
+                                  && (info->cr_save_p
+                                      || info->lr_save_p
+                                      || info->first_fp_reg_save < 64
+                                      || info->first_gp_reg_save < 32
+                                      )),
+                                 need_r11);
       if (frame_reg_rtx != sp_reg_rtx)
        rs6000_emit_stack_tie ();
     }
@@ -19229,19 +19209,16 @@ rs6000_emit_prologue (void)
   if (!WORLD_SAVE_P (info) && info->push_p
       && !(DEFAULT_ABI == ABI_V4 || crtl->calls_eh_return))
     {
-      rtx copy_reg = NULL;
-
       if (info->total_size < 32767)
-       sp_offset = info->total_size;
-      else if (info->altivec_size != 0
-              || info->vrsave_mask != 0)
-       {
-         copy_reg = frame_ptr_rtx;
-         frame_reg_rtx = copy_reg;
-       }
+      sp_offset = info->total_size;
       else
-       sp_offset = info->total_size;
-      rs6000_emit_allocate_stack (info->total_size, copy_reg);
+       frame_reg_rtx = frame_ptr_rtx;
+      rs6000_emit_allocate_stack (info->total_size,
+                                 (frame_reg_rtx != sp_reg_rtx
+                                  && ((info->altivec_size != 0)
+                                      || (info->vrsave_mask != 0)
+                                      )),
+                                 FALSE);
       if (frame_reg_rtx != sp_reg_rtx)
        rs6000_emit_stack_tie ();
     }
@@ -23344,15 +23321,6 @@ rs6000_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
 }
 
 \f
-/* Returns TRUE iff the target attribute indicated by ATTR_ID takes a plain
-   identifier as an argument, so the front end shouldn't look it up.  */
-
-static bool
-rs6000_attribute_takes_identifier_p (const_tree attr_id)
-{
-  return is_attribute_p ("altivec", attr_id);
-}
-
 /* Handle the "altivec" attribute.  The attribute may have
    arguments as follows: