1, /* streams */
};
+/* Instruction costs on PPC476 processors. */
+static const
+struct processor_costs ppc476_cost = {
+ COSTS_N_INSNS (4), /* mulsi */
+ COSTS_N_INSNS (4), /* mulsi_const */
+ COSTS_N_INSNS (4), /* mulsi_const9 */
+ COSTS_N_INSNS (4), /* muldi */
+ COSTS_N_INSNS (11), /* divsi */
+ COSTS_N_INSNS (11), /* divdi */
+ COSTS_N_INSNS (6), /* fp */
+ COSTS_N_INSNS (6), /* dmul */
+ COSTS_N_INSNS (19), /* sdiv */
+ COSTS_N_INSNS (33), /* ddiv */
+ 32, /* l1 cache line size */
+ 32, /* l1 cache */
+ 512, /* l2 cache */
+ 1, /* streams */
+};
+
/* Instruction costs on PPC601 processors. */
static const
struct processor_costs ppc601_cost = {
1, /* prefetch streams /*/
};
+/* Instruction costs on PPCE500MC64 processors. */
+static const
+struct processor_costs ppce500mc64_cost = {
+ COSTS_N_INSNS (4), /* mulsi */
+ COSTS_N_INSNS (4), /* mulsi_const */
+ COSTS_N_INSNS (4), /* mulsi_const9 */
+ COSTS_N_INSNS (4), /* muldi */
+ COSTS_N_INSNS (14), /* divsi */
+ COSTS_N_INSNS (14), /* divdi */
+ COSTS_N_INSNS (4), /* fp */
+ COSTS_N_INSNS (10), /* dmul */
+ COSTS_N_INSNS (36), /* sdiv */
+ COSTS_N_INSNS (66), /* ddiv */
+ 64, /* cache line size */
+ 32, /* l1 cache */
+ 128, /* l2 cache */
+ 1, /* prefetch streams /*/
+};
+
/* Instruction costs on POWER4 and POWER5 processors. */
static const
struct processor_costs power4_cost = {
12, /* prefetch streams */
};
+/* Instruction costs on POWER A2 processors. */
+static const
+struct processor_costs ppca2_cost = {
+ COSTS_N_INSNS (16), /* mulsi */
+ COSTS_N_INSNS (16), /* mulsi_const */
+ COSTS_N_INSNS (16), /* mulsi_const9 */
+ COSTS_N_INSNS (16), /* muldi */
+ COSTS_N_INSNS (22), /* divsi */
+ COSTS_N_INSNS (28), /* divdi */
+ COSTS_N_INSNS (3), /* fp */
+ COSTS_N_INSNS (3), /* dmul */
+ COSTS_N_INSNS (59), /* sdiv */
+ COSTS_N_INSNS (72), /* ddiv */
+ 64,
+ 16, /* l1 cache */
+ 2048, /* l2 cache */
+ 16, /* prefetch streams */
+};
+
+\f
+/* Table that classifies rs6000 builtin functions (pure, const, etc.). */
+#undef RS6000_BUILTIN
+#undef RS6000_BUILTIN_EQUATE
+#define RS6000_BUILTIN(NAME, TYPE) TYPE,
+#define RS6000_BUILTIN_EQUATE(NAME, VALUE)
+
+static const enum rs6000_btc builtin_classify[(int)RS6000_BUILTIN_COUNT] =
+{
+#include "rs6000-builtin.def"
+};
+
+#undef RS6000_BUILTIN
+#undef RS6000_BUILTIN_EQUATE
+
\f
static bool rs6000_function_ok_for_sibcall (tree, tree);
static const char *rs6000_invalid_within_doloop (const_rtx);
tree);
static rtx rs6000_emit_set_long_const (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
static bool rs6000_return_in_memory (const_tree, const_tree);
+static rtx rs6000_function_value (const_tree, const_tree, bool);
static void rs6000_file_start (void);
#if TARGET_ELF
static int rs6000_elf_reloc_rw_mask (void);
static void def_builtin (int, const char *, tree, int);
static bool rs6000_vector_alignment_reachable (const_tree, bool);
static void rs6000_init_builtins (void);
+static tree rs6000_builtin_decl (unsigned, bool);
+
static rtx rs6000_expand_unop_builtin (enum insn_code, tree, rtx);
static rtx rs6000_expand_binop_builtin (enum insn_code, tree, rtx);
static rtx rs6000_expand_ternop_builtin (enum insn_code, tree, rtx);
static rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
static rtx rs6000_debug_legitimize_address (rtx, rtx, enum machine_mode);
static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
-static rtx rs6000_delegitimize_address (rtx);
static void rs6000_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
static rtx rs6000_tls_get_addr (void);
static rtx rs6000_got_sym (void);
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS rs6000_init_builtins
+#undef TARGET_BUILTIN_DECL
+#define TARGET_BUILTIN_DECL rs6000_builtin_decl
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN rs6000_expand_builtin
#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
#define TARGET_USE_BLOCKS_FOR_CONSTANT_P rs6000_use_blocks_for_constant_p
-#undef TARGET_DELEGITIMIZE_ADDRESS
-#define TARGET_DELEGITIMIZE_ADDRESS rs6000_delegitimize_address
-
#undef TARGET_BUILTIN_RECIPROCAL
#define TARGET_BUILTIN_RECIPROCAL rs6000_builtin_reciprocal
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT rs6000_trampoline_init
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE rs6000_function_value
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
/* Return number of consecutive hard regs needed starting at reg REGNO
POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
{"464fp", PROCESSOR_PPC440,
POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
+ {"476", PROCESSOR_PPC476,
+ POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_PPC_GFXOPT | MASK_MFCRF
+ | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB},
+ {"476fp", PROCESSOR_PPC476,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB
+ | MASK_FPRND | MASK_CMPB | MASK_MULHW | MASK_DLMZB},
{"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK},
{"601", PROCESSOR_PPC601,
MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING},
/* 8548 has a dummy entry for now. */
{"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
| MASK_ISEL},
+ {"a2", PROCESSOR_PPCA2,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_POPCNTB
+ | MASK_CMPB | MASK_NO_UPDATE },
{"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
{"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
| MASK_ISEL},
+ {"e500mc64", PROCESSOR_PPCE500MC64, POWERPC_BASE_MASK | MASK_POWERPC64
+ | MASK_PPC_GFXOPT | MASK_ISEL},
{"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"970", PROCESSOR_POWER4,
POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
| MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
| MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
| MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP
- | MASK_POPCNTD | MASK_VSX | MASK_ISEL)
+ | MASK_POPCNTD | MASK_VSX | MASK_ISEL | MASK_NO_UPDATE)
};
+ /* Numerous experiment shows that IRA based loop pressure
+ calculation works better for RTL loop invariant motion on targets
+ with enough (>= 32) registers. It is an expensive optimization.
+ So it is on only for peak performance. */
+ if (optimize >= 3)
+ flag_ira_loop_pressure = 1;
+
/* Set the pointer size. */
if (TARGET_64BIT)
{
}
if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
- || rs6000_cpu == PROCESSOR_PPCE500MC)
+ || rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64)
{
if (TARGET_ALTIVEC)
error ("AltiVec not supported in this target");
}
}
- /* Add some warnings for VSX. Enable -maltivec unless the user explicitly
- used -mno-altivec */
+ /* Add some warnings for VSX. */
if (TARGET_VSX)
{
const char *msg = NULL;
msg = N_("-mvsx used with little endian code");
else if (TARGET_AVOID_XFORM > 0)
msg = N_("-mvsx needs indexed addressing");
+ else if (!TARGET_ALTIVEC && (target_flags_explicit & MASK_ALTIVEC))
+ {
+ if (target_flags_explicit & MASK_VSX)
+ msg = N_("-mvsx and -mno-altivec are incompatible");
+ else
+ msg = N_("-mno-altivec disables vsx");
+ }
if (msg)
{
warning (0, msg);
target_flags &= ~ MASK_VSX;
}
- else if (TARGET_VSX && !TARGET_ALTIVEC
- && (target_flags_explicit & MASK_ALTIVEC) == 0)
+ else if (TARGET_VSX && !TARGET_ALTIVEC)
target_flags |= MASK_ALTIVEC;
}
SUB3TARGET_OVERRIDE_OPTIONS;
#endif
- if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC)
+ if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC
+ || rs6000_cpu == PROCESSOR_PPCE500MC64)
{
/* The e500 and e500mc do not have string instructions, and we set
MASK_STRING above when optimizing for size. */
&& rs6000_cpu != PROCESSOR_POWER5
&& rs6000_cpu != PROCESSOR_POWER6
&& rs6000_cpu != PROCESSOR_POWER7
+ && rs6000_cpu != PROCESSOR_PPCA2
&& rs6000_cpu != PROCESSOR_CELL);
rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
|| rs6000_cpu == PROCESSOR_POWER5
rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4
|| rs6000_cpu == PROCESSOR_POWER5
|| rs6000_cpu == PROCESSOR_POWER6
- || rs6000_cpu == PROCESSOR_POWER7);
+ || rs6000_cpu == PROCESSOR_POWER7
+ || rs6000_cpu == PROCESSOR_PPCE500MC
+ || rs6000_cpu == PROCESSOR_PPCE500MC64);
/* Allow debug switches to override the above settings. */
if (TARGET_ALWAYS_HINT > 0)
rs6000_cost = &ppc440_cost;
break;
+ case PROCESSOR_PPC476:
+ rs6000_cost = &ppc476_cost;
+ break;
+
case PROCESSOR_PPC601:
rs6000_cost = &ppc601_cost;
break;
rs6000_cost = &ppce500mc_cost;
break;
+ case PROCESSOR_PPCE500MC64:
+ rs6000_cost = &ppce500mc64_cost;
+ break;
+
case PROCESSOR_POWER4:
case PROCESSOR_POWER5:
rs6000_cost = &power4_cost;
rs6000_cost = &power7_cost;
break;
+ case PROCESSOR_PPCA2:
+ rs6000_cost = &ppca2_cost;
+ break;
+
default:
gcc_unreachable ();
}
if (low == 0)
return num_insns_constant_wide (high) + 1;
+ else if (high == 0)
+ return num_insns_constant_wide (low) + 1;
else
return (num_insns_constant_wide (high)
+ num_insns_constant_wide (low) + 1);
return ret;
}
-/* If ORIG_X is a constant pool reference, return its known value,
- otherwise ORIG_X. */
-
-static rtx
-rs6000_delegitimize_address (rtx x)
-{
- rtx orig_x = delegitimize_mem_from_attrs (x);
-
- x = orig_x;
-
- if (!MEM_P (x))
- return orig_x;
-
- x = XEXP (x, 0);
-
- if (legitimate_constant_pool_address_p (x)
- && GET_CODE (XEXP (x, 1)) == CONST
- && GET_CODE (XEXP (XEXP (x, 1), 0)) == MINUS
- && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == SYMBOL_REF
- && constant_pool_expr_p (XEXP (XEXP (XEXP (x, 1), 0), 0))
- && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == SYMBOL_REF
- && toc_relative_expr_p (XEXP (XEXP (XEXP (x, 1), 0), 1)))
- return get_pool_constant (XEXP (XEXP (XEXP (x, 1), 0), 0));
-
- return orig_x;
-}
-
/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
We need to emit DTP-relative relocations. */
&& legitimate_indexed_address_p (x, reg_ok_strict))
return 1;
if (GET_CODE (x) == PRE_MODIFY
- && VECTOR_MEM_VSX_P (mode)
- && TARGET_UPDATE
- && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)
- && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
- return 1;
- if (GET_CODE (x) == PRE_MODIFY
&& mode != TImode
&& mode != TFmode
&& mode != TDmode
|| TARGET_POWERPC64
|| ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
&& (TARGET_POWERPC64 || mode != DImode)
- && !VECTOR_MEM_ALTIVEC_P (mode)
+ && !VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)
&& !SPE_VECTOR_MODE (mode)
/* Restrict addressing for DI because of our SUBREG hackery. */
&& !(TARGET_E500_DOUBLE
gen_rtx_IOR (DImode, copy_rtx (dest),
GEN_INT (ud1)));
}
+ else if (ud3 == 0 && ud4 == 0)
+ {
+ gcc_assert (ud2 & 0x8000);
+ emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000)
+ - 0x80000000));
+ if (ud1 != 0)
+ emit_move_insn (copy_rtx (dest),
+ gen_rtx_IOR (DImode, copy_rtx (dest),
+ GEN_INT (ud1)));
+ emit_move_insn (copy_rtx (dest),
+ gen_rtx_ZERO_EXTEND (DImode,
+ gen_lowpart (SImode,
+ copy_rtx (dest))));
+ }
else if ((ud4 == 0xffff && (ud3 & 0x8000))
|| (ud4 == 0 && ! (ud3 & 0x8000)))
{
{
if ((mask & target_flags) || TARGET_PAIRED_FLOAT)
{
+ tree t;
if (rs6000_builtin_decls[code])
fatal_error ("internal error: builtin function to %s already processed.",
name);
- rs6000_builtin_decls[code] =
+ rs6000_builtin_decls[code] = t =
add_builtin_function (name, type, code, BUILT_IN_MD,
NULL, NULL_TREE);
+
+ gcc_assert (code >= 0 && code < (int)RS6000_BUILTIN_COUNT);
+ switch (builtin_classify[code])
+ {
+ default:
+ gcc_unreachable ();
+
+ /* assume builtin can do anything. */
+ case RS6000_BTC_MISC:
+ break;
+
+ /* const function, function only depends on the inputs. */
+ case RS6000_BTC_CONST:
+ TREE_READONLY (t) = 1;
+ TREE_NOTHROW (t) = 1;
+ break;
+
+ /* pure function, function can read global memory. */
+ case RS6000_BTC_PURE:
+ DECL_PURE_P (t) = 1;
+ TREE_NOTHROW (t) = 1;
+ break;
+
+ /* Function is a math function. If rounding mode is on, then treat
+ the function as not reading global memory, but it can have
+ arbitrary side effects. If it is off, then assume the function is
+ a const function. This mimics the ATTR_MATHFN_FPROUNDING
+ attribute in builtin-attribute.def that is used for the math
+ functions. */
+ case RS6000_BTC_FP_PURE:
+ TREE_NOTHROW (t) = 1;
+ if (flag_rounding_math)
+ {
+ DECL_PURE_P (t) = 1;
+ DECL_IS_NOVOPS (t) = 1;
+ }
+ else
+ TREE_READONLY (t) = 1;
+ break;
+ }
}
}
{ MASK_VSX, CODE_FOR_nothing, "__builtin_vec_mul", VSX_BUILTIN_VEC_MUL },
{ MASK_VSX, CODE_FOR_nothing, "__builtin_vec_div", VSX_BUILTIN_VEC_DIV },
- { 0, CODE_FOR_divv2sf3, "__builtin_paired_divv2sf3", PAIRED_BUILTIN_DIVV2SF3 },
- { 0, CODE_FOR_addv2sf3, "__builtin_paired_addv2sf3", PAIRED_BUILTIN_ADDV2SF3 },
- { 0, CODE_FOR_subv2sf3, "__builtin_paired_subv2sf3", PAIRED_BUILTIN_SUBV2SF3 },
- { 0, CODE_FOR_mulv2sf3, "__builtin_paired_mulv2sf3", PAIRED_BUILTIN_MULV2SF3 },
+ { 0, CODE_FOR_paired_divv2sf3, "__builtin_paired_divv2sf3", PAIRED_BUILTIN_DIVV2SF3 },
+ { 0, CODE_FOR_paired_addv2sf3, "__builtin_paired_addv2sf3", PAIRED_BUILTIN_ADDV2SF3 },
+ { 0, CODE_FOR_paired_subv2sf3, "__builtin_paired_subv2sf3", PAIRED_BUILTIN_SUBV2SF3 },
+ { 0, CODE_FOR_paired_mulv2sf3, "__builtin_paired_mulv2sf3", PAIRED_BUILTIN_MULV2SF3 },
{ 0, CODE_FOR_paired_muls0, "__builtin_paired_muls0", PAIRED_BUILTIN_MULS0 },
{ 0, CODE_FOR_paired_muls1, "__builtin_paired_muls1", PAIRED_BUILTIN_MULS1 },
{ 0, CODE_FOR_paired_merge00, "__builtin_paired_merge00", PAIRED_BUILTIN_MERGE00 },
{ 0, CODE_FOR_paired_merge11, "__builtin_paired_merge11", PAIRED_BUILTIN_MERGE11 },
/* Place holder, leave as first spe builtin. */
- { 0, CODE_FOR_spe_evaddw, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW },
- { 0, CODE_FOR_spe_evand, "__builtin_spe_evand", SPE_BUILTIN_EVAND },
+ { 0, CODE_FOR_addv2si3, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW },
+ { 0, CODE_FOR_andv2si3, "__builtin_spe_evand", SPE_BUILTIN_EVAND },
{ 0, CODE_FOR_spe_evandc, "__builtin_spe_evandc", SPE_BUILTIN_EVANDC },
- { 0, CODE_FOR_spe_evdivws, "__builtin_spe_evdivws", SPE_BUILTIN_EVDIVWS },
+ { 0, CODE_FOR_divv2si3, "__builtin_spe_evdivws", SPE_BUILTIN_EVDIVWS },
{ 0, CODE_FOR_spe_evdivwu, "__builtin_spe_evdivwu", SPE_BUILTIN_EVDIVWU },
{ 0, CODE_FOR_spe_eveqv, "__builtin_spe_eveqv", SPE_BUILTIN_EVEQV },
{ 0, CODE_FOR_spe_evfsadd, "__builtin_spe_evfsadd", SPE_BUILTIN_EVFSADD },
{ 0, CODE_FOR_spe_evslw, "__builtin_spe_evslw", SPE_BUILTIN_EVSLW },
{ 0, CODE_FOR_spe_evsrws, "__builtin_spe_evsrws", SPE_BUILTIN_EVSRWS },
{ 0, CODE_FOR_spe_evsrwu, "__builtin_spe_evsrwu", SPE_BUILTIN_EVSRWU },
- { 0, CODE_FOR_spe_evsubfw, "__builtin_spe_evsubfw", SPE_BUILTIN_EVSUBFW },
+ { 0, CODE_FOR_subv2si3, "__builtin_spe_evsubfw", SPE_BUILTIN_EVSUBFW },
/* SPE binary operations expecting a 5-bit unsigned literal. */
{ 0, CODE_FOR_spe_evaddiw, "__builtin_spe_evaddiw", SPE_BUILTIN_EVADDIW },
/* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
end with SPE_BUILTIN_EVSUBFUSIAAW. */
- { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
+ { 0, CODE_FOR_absv2si2, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
{ 0, CODE_FOR_spe_evaddsmiaaw, "__builtin_spe_evaddsmiaaw", SPE_BUILTIN_EVADDSMIAAW },
{ 0, CODE_FOR_spe_evaddssiaaw, "__builtin_spe_evaddssiaaw", SPE_BUILTIN_EVADDSSIAAW },
{ 0, CODE_FOR_spe_evaddumiaaw, "__builtin_spe_evaddumiaaw", SPE_BUILTIN_EVADDUMIAAW },
/* Place-holder. Leave as last unary SPE builtin. */
{ 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW },
- { 0, CODE_FOR_absv2sf2, "__builtin_paired_absv2sf2", PAIRED_BUILTIN_ABSV2SF2 },
+ { 0, CODE_FOR_paired_absv2sf2, "__builtin_paired_absv2sf2", PAIRED_BUILTIN_ABSV2SF2 },
{ 0, CODE_FOR_nabsv2sf2, "__builtin_paired_nabsv2sf2", PAIRED_BUILTIN_NABSV2SF2 },
- { 0, CODE_FOR_negv2sf2, "__builtin_paired_negv2sf2", PAIRED_BUILTIN_NEGV2SF2 },
+ { 0, CODE_FOR_paired_negv2sf2, "__builtin_paired_negv2sf2", PAIRED_BUILTIN_NEGV2SF2 },
{ 0, CODE_FOR_sqrtv2sf2, "__builtin_paired_sqrtv2sf2", PAIRED_BUILTIN_SQRTV2SF2 },
{ 0, CODE_FOR_resv2sf2, "__builtin_paired_resv2sf2", PAIRED_BUILTIN_RESV2SF2 }
};
rs6000_init_builtins (void)
{
tree tdecl;
-
+
V2SI_type_node = build_vector_type (intSI_type_node, 2);
V2SF_type_node = build_vector_type (float_type_node, 2);
V2DI_type_node = build_vector_type (intDI_type_node, 2);
#endif
}
+/* Returns the rs6000 builtin decl for CODE. */
+
+static tree
+rs6000_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
+{
+ if (code >= RS6000_BUILTIN_COUNT)
+ return error_mark_node;
+
+ return rs6000_builtin_decls[code];
+}
+
/* Search through a set of builtins and enable the mask bits.
DESC is an array of builtins.
SIZE is the total number of builtins.
/* Emit the RTL for an sCOND pattern. */
void
+rs6000_emit_sISEL (enum machine_mode mode, rtx operands[])
+{
+ rtx condition_rtx;
+ enum machine_mode op_mode;
+ enum rtx_code cond_code;
+ rtx result = operands[0];
+
+ condition_rtx = rs6000_generate_compare (operands[1], mode);
+ cond_code = GET_CODE (condition_rtx);
+
+ op_mode = GET_MODE (XEXP (operands[1], 0));
+ if (op_mode == VOIDmode)
+ op_mode = GET_MODE (XEXP (operands[1], 1));
+
+ if (TARGET_POWERPC64 && GET_MODE (result) == DImode)
+ {
+ PUT_MODE (condition_rtx, DImode);
+ if (cond_code == GEU || cond_code == GTU || cond_code == LEU
+ || cond_code == LTU)
+ emit_insn (gen_isel_unsigned_di (result, condition_rtx,
+ force_reg (DImode, const1_rtx),
+ force_reg (DImode, const0_rtx),
+ XEXP (condition_rtx, 0)));
+ else
+ emit_insn (gen_isel_signed_di (result, condition_rtx,
+ force_reg (DImode, const1_rtx),
+ force_reg (DImode, const0_rtx),
+ XEXP (condition_rtx, 0)));
+ }
+ else
+ {
+ PUT_MODE (condition_rtx, SImode);
+ if (cond_code == GEU || cond_code == GTU || cond_code == LEU
+ || cond_code == LTU)
+ emit_insn (gen_isel_unsigned_si (result, condition_rtx,
+ force_reg (SImode, const1_rtx),
+ force_reg (SImode, const0_rtx),
+ XEXP (condition_rtx, 0)));
+ else
+ emit_insn (gen_isel_signed_si (result, condition_rtx,
+ force_reg (SImode, const1_rtx),
+ force_reg (SImode, const0_rtx),
+ XEXP (condition_rtx, 0)));
+ }
+}
+
+void
rs6000_emit_sCOND (enum machine_mode mode, rtx operands[])
{
rtx condition_rtx;
enum rtx_code cond_code;
rtx result = operands[0];
+ if (TARGET_ISEL && (mode == SImode || mode == DImode))
+ {
+ rs6000_emit_sISEL (mode, operands);
+ return;
+ }
+
condition_rtx = rs6000_generate_compare (operands[1], mode);
cond_code = GET_CODE (condition_rtx);
rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
{
rtx condition_rtx, cr;
- enum machine_mode mode = GET_MODE (XEXP (op, 0));
+ enum machine_mode mode = GET_MODE (dest);
if (mode != SImode && (!TARGET_POWERPC64 || mode != DImode))
return 0;
/* We still have to do the compare, because isel doesn't do a
compare, it just looks at the CRx bits set by a previous compare
instruction. */
- condition_rtx = rs6000_generate_compare (op, SImode);
+ condition_rtx = rs6000_generate_compare (op, mode);
cr = XEXP (condition_rtx, 0);
if (mode == SImode)
use language_string.
C is 0. Fortran is 1. Pascal is 2. Ada is 3. C++ is 9.
Java is 13. Objective-C is 14. Objective-C++ isn't assigned
- a number, so for now use 9. */
- if (! strcmp (language_string, "GNU C"))
+ a number, so for now use 9. LTO isn't assigned a number either,
+ so for now use 0. */
+ if (! strcmp (language_string, "GNU C")
+ || ! strcmp (language_string, "GNU GIMPLE"))
i = 0;
else if (! strcmp (language_string, "GNU F77")
|| ! strcmp (language_string, "GNU Fortran"))
instructions to issue in this cycle. */
static int
-rs6000_variable_issue (FILE *stream ATTRIBUTE_UNUSED,
- int verbose ATTRIBUTE_UNUSED,
- rtx insn, int more)
+rs6000_variable_issue_1 (rtx insn, int more)
{
last_scheduled_insn = insn;
if (GET_CODE (PATTERN (insn)) == USE
return cached_can_issue_more;
}
+static int
+rs6000_variable_issue (FILE *stream, int verbose, rtx insn, int more)
+{
+ int r = rs6000_variable_issue_1 (insn, more);
+ if (verbose)
+ fprintf (stream, "// rs6000_variable_issue (more = %d) = %d\n", more, r);
+ return r;
+}
+
/* Adjust the cost of a scheduling dependency. Return the new cost of
a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
static int
rs6000_issue_rate (void)
{
- /* Use issue rate of 1 for first scheduling pass to decrease degradation. */
- if (!reload_completed)
+ /* Unless scheduling for register pressure, use issue rate of 1 for
+ first scheduling pass to decrease degradation. */
+ if (!reload_completed && !flag_sched_pressure)
return 1;
switch (rs6000_cpu_attr) {
case CPU_PPCE300C2:
case CPU_PPCE300C3:
case CPU_PPCE500MC:
+ case CPU_PPCE500MC64:
return 2;
case CPU_RIOS2:
+ case CPU_PPC476:
case CPU_PPC604:
case CPU_PPC604E:
case CPU_PPC620:
{
if (XEXP (x, 1) == const0_rtx)
{
- *total = COSTS_N_INSNS (2);
+ if (TARGET_ISEL && !TARGET_MFCRF)
+ *total = COSTS_N_INSNS (8);
+ else
+ *total = COSTS_N_INSNS (2);
return true;
}
else if (mode == Pmode)
case UNORDERED:
if (outer_code == SET && (XEXP (x, 1) == const0_rtx))
{
- *total = COSTS_N_INSNS (2);
+ if (TARGET_ISEL && !TARGET_MFCRF)
+ *total = COSTS_N_INSNS (8);
+ else
+ *total = COSTS_N_INSNS (2);
return true;
}
/* CC COMPARE. */
return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
}
-/* Define how to find the value returned by a function.
- VALTYPE is the data type of the value (as a tree).
- If the precise function being called is known, FUNC is its FUNCTION_DECL;
- otherwise, FUNC is 0.
+/* Target hook for TARGET_FUNCTION_VALUE.
On the SPE, both FPs and vectors are returned in r3.
fp1, unless -msoft-float. */
rtx
-rs6000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
+rs6000_function_value (const_tree valtype,
+ const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+ bool outgoing ATTRIBUTE_UNUSED)
{
enum machine_mode mode;
unsigned int regno;