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;
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 *);
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);
static rtx rs6000_make_savres_rtx (rs6000_stack_t *, rtx, int,
enum machine_mode, bool, bool, bool);
static bool rs6000_reg_live_or_pic_offset_p (int);
-static tree rs6000_builtin_vectorized_function (tree, tree, tree);
+static tree rs6000_builtin_vectorized_function (unsigned int, tree, tree);
static int rs6000_savres_strategy (rs6000_stack_t *, bool, int, int);
static void rs6000_restore_saved_cr (rtx, int);
static void rs6000_output_function_prologue (FILE *, HOST_WIDE_INT);
static tree rs6000_builtin_mask_for_load (void);
static tree rs6000_builtin_mul_widen_even (tree);
static tree rs6000_builtin_mul_widen_odd (tree);
-static tree rs6000_builtin_conversion (unsigned int, tree, tree);
+static tree rs6000_builtin_conversion (unsigned int, tree);
static tree rs6000_builtin_vec_perm (tree, tree *);
static bool rs6000_builtin_support_vector_misalignment (enum
machine_mode,
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,
#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
/* Implement targetm.vectorize.builtin_conversion.
Returns a decl of a function that implements conversion of an integer vector
- into a floating-point vector, or vice-versa. DEST_TYPE is the
- destination type and SRC_TYPE the source type of the conversion.
+ into a floating-point vector, or vice-versa. TYPE is the type of the integer
+ side of the conversion.
Return NULL_TREE if it is not available. */
static tree
-rs6000_builtin_conversion (unsigned int tcode, tree dest_type, tree src_type)
+rs6000_builtin_conversion (unsigned int tcode, tree type)
{
enum tree_code code = (enum tree_code) tcode;
switch (code)
{
case FIX_TRUNC_EXPR:
- switch (TYPE_MODE (dest_type))
+ switch (TYPE_MODE (type))
{
case V2DImode:
if (!VECTOR_UNIT_VSX_P (V2DFmode))
return NULL_TREE;
- return TYPE_UNSIGNED (dest_type)
+ return TYPE_UNSIGNED (type)
? rs6000_builtin_decls[VSX_BUILTIN_XVCVDPUXDS_UNS]
: rs6000_builtin_decls[VSX_BUILTIN_XVCVDPSXDS];
if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
return NULL_TREE;
- return TYPE_UNSIGNED (dest_type)
+ return TYPE_UNSIGNED (type)
? rs6000_builtin_decls[VECTOR_BUILTIN_FIXUNS_V4SF_V4SI]
: rs6000_builtin_decls[VECTOR_BUILTIN_FIX_V4SF_V4SI];
}
case FLOAT_EXPR:
- switch (TYPE_MODE (src_type))
+ switch (TYPE_MODE (type))
{
case V2DImode:
if (!VECTOR_UNIT_VSX_P (V2DFmode))
return NULL_TREE;
- return TYPE_UNSIGNED (src_type)
+ return TYPE_UNSIGNED (type)
? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDDP]
: rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDDP];
if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
return NULL_TREE;
- return TYPE_UNSIGNED (src_type)
+ return TYPE_UNSIGNED (type)
? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF]
: rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF];
if it is not available. */
static tree
-rs6000_builtin_vectorized_function (tree fndecl, tree type_out,
+rs6000_builtin_vectorized_function (unsigned int fn, tree type_out,
tree type_in)
{
enum machine_mode in_mode, out_mode;
int in_n, out_n;
- enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
if (TREE_CODE (type_out) != VECTOR_TYPE
|| TREE_CODE (type_in) != VECTOR_TYPE
- || !TARGET_VECTORIZE_BUILTINS
- || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
+ || !TARGET_VECTORIZE_BUILTINS)
return NULL_TREE;
out_mode = TYPE_MODE (TREE_TYPE (type_out));
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));
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)));
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);
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))
{
/* 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);
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;
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
{
rtx basereg = XEXP (XEXP (dst, 0), 0);
rtx offsetreg = XEXP (XEXP (dst, 0), 1);
- gcc_assert (GET_CODE (XEXP (dst, 0)) == PLUS
- && REG_P (basereg)
- && REG_P (offsetreg)
- && REGNO (basereg) != REGNO (offsetreg));
- if (REGNO (basereg) == 0)
- {
- rtx tmp = offsetreg;
- offsetreg = basereg;
- basereg = tmp;
- }
emit_insn (gen_add3_insn (basereg, basereg, offsetreg));
restore_basereg = gen_sub3_insn (basereg, basereg, offsetreg);
dst = replace_equiv_address (dst, basereg);
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
}
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;
}
/* 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);
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)
{
? (!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 ();
}
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 ();
}
}
\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: