| m_CORE2 | m_GENERIC);
const int x86_use_mov0 = m_K6;
const int x86_use_cltd = ~(m_PENT | m_K6 | m_CORE2 | m_GENERIC);
+/* Use xchgb %rh,%rl instead of rolw/rorw $8,rx. */
+const int x86_use_xchgb = m_PENT4;
const int x86_read_modify_write = ~m_PENT;
const int x86_read_modify = ~(m_PENT | m_PPRO);
const int x86_split_long_moves = m_PPRO;
const int x86_use_ffreep = m_ATHLON_K8_AMDFAM10;
const int x86_use_incdec = ~(m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC);
-/* ??? Allowing interunit moves makes it all too easy for the compiler to put
- integer data in xmm registers. Which results in pretty abysmal code. */
-const int x86_inter_unit_moves = 0 /* ~(m_ATHLON_K8) */;
+const int x86_inter_unit_moves = ~(m_ATHLON_K8_AMDFAM10 | m_GENERIC);
const int x86_ext_80387_constants = m_K6_GEODE | m_ATHLON_K8 | m_PENT4
| m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC;
static void ix86_init_builtins (void);
static rtx ix86_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
static tree ix86_builtin_vectorized_function (enum built_in_function, tree, tree);
+static tree ix86_builtin_conversion (enum tree_code, tree);
static const char *ix86_mangle_fundamental_type (tree);
static tree ix86_stack_protect_fail (void);
static rtx ix86_internal_arg_pointer (void);
static void ix86_dwarf_handle_frame_unspec (const char *, rtx, int);
+static bool ix86_expand_vector_init_one_nonzero (bool, enum machine_mode,
+ rtx, rtx, int);
/* This function is only used on Solaris. */
static void i386_solaris_elf_named_section (const char *, unsigned int, tree)
#define TARGET_INIT_BUILTINS ix86_init_builtins
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN ix86_expand_builtin
+
#undef TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION
#define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION ix86_builtin_vectorized_function
+#undef TARGET_VECTORIZE_BUILTIN_CONVERSION
+#define TARGET_VECTORIZE_BUILTIN_CONVERSION ix86_builtin_conversion
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
func = decl;
else
{
- func = TREE_TYPE (TREE_OPERAND (exp, 0));
+ func = TREE_TYPE (CALL_EXPR_FN (exp));
if (POINTER_TYPE_P (func))
func = TREE_TYPE (func);
}
tree type;
/* We're looking at the CALL_EXPR, we need the type of the function. */
- type = TREE_OPERAND (exp, 0); /* pointer expression */
+ type = CALL_EXPR_FN (exp); /* pointer expression */
type = TREE_TYPE (type); /* pointer type */
type = TREE_TYPE (type); /* function type */
return TRUE;
}
+/* Post-reload splitter for converting an SF or DFmode value in an
+ SSE register into an unsigned SImode. */
+
+void
+ix86_split_convert_uns_si_sse (rtx operands[])
+{
+ enum machine_mode vecmode;
+ rtx value, large, zero_or_two31, input, two31, x;
+
+ large = operands[1];
+ zero_or_two31 = operands[2];
+ input = operands[3];
+ two31 = operands[4];
+ vecmode = GET_MODE (large);
+ value = gen_rtx_REG (vecmode, REGNO (operands[0]));
+
+ /* Load up the value into the low element. We must ensure that the other
+ elements are valid floats -- zero is the easiest such value. */
+ if (MEM_P (input))
+ {
+ if (vecmode == V4SFmode)
+ emit_insn (gen_vec_setv4sf_0 (value, CONST0_RTX (V4SFmode), input));
+ else
+ emit_insn (gen_sse2_loadlpd (value, CONST0_RTX (V2DFmode), input));
+ }
+ else
+ {
+ input = gen_rtx_REG (vecmode, REGNO (input));
+ emit_move_insn (value, CONST0_RTX (vecmode));
+ if (vecmode == V4SFmode)
+ emit_insn (gen_sse_movss (value, value, input));
+ else
+ emit_insn (gen_sse2_movsd (value, value, input));
+ }
+
+ emit_move_insn (large, two31);
+ emit_move_insn (zero_or_two31, MEM_P (two31) ? large : two31);
+
+ x = gen_rtx_fmt_ee (LE, vecmode, large, value);
+ emit_insn (gen_rtx_SET (VOIDmode, large, x));
+
+ x = gen_rtx_AND (vecmode, zero_or_two31, large);
+ emit_insn (gen_rtx_SET (VOIDmode, zero_or_two31, x));
+
+ x = gen_rtx_MINUS (vecmode, value, zero_or_two31);
+ emit_insn (gen_rtx_SET (VOIDmode, value, x));
+
+ large = gen_rtx_REG (V4SImode, REGNO (large));
+ emit_insn (gen_ashlv4si3 (large, large, GEN_INT (31)));
+
+ x = gen_rtx_REG (V4SImode, REGNO (value));
+ if (vecmode == V4SFmode)
+ emit_insn (gen_sse2_cvttps2dq (x, value));
+ else
+ emit_insn (gen_sse2_cvttpd2dq (x, value));
+ value = x;
+
+ emit_insn (gen_xorv4si3 (value, value, large));
+}
+
+/* Convert an unsigned DImode value into a DFmode, using only SSE.
+ Expects the 64-bit DImode to be supplied in a pair of integral
+ registers. Requires SSE2; will use SSE3 if available. For x86_32,
+ -mfpmath=sse, !optimize_size only. */
+
+void
+ix86_expand_convert_uns_didf_sse (rtx target, rtx input)
+{
+ REAL_VALUE_TYPE bias_lo_rvt, bias_hi_rvt;
+ rtx int_xmm, fp_xmm;
+ rtx biases, exponents;
+ rtx x;
+
+ int_xmm = gen_reg_rtx (V4SImode);
+ if (TARGET_INTER_UNIT_MOVES)
+ emit_insn (gen_movdi_to_sse (int_xmm, input));
+ else if (TARGET_SSE_SPLIT_REGS)
+ {
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, int_xmm));
+ emit_move_insn (gen_lowpart (DImode, int_xmm), input);
+ }
+ else
+ {
+ x = gen_reg_rtx (V2DImode);
+ ix86_expand_vector_init_one_nonzero (false, V2DImode, x, input, 0);
+ emit_move_insn (int_xmm, gen_lowpart (V4SImode, x));
+ }
+
+ x = gen_rtx_CONST_VECTOR (V4SImode,
+ gen_rtvec (4, GEN_INT (0x43300000UL),
+ GEN_INT (0x45300000UL),
+ const0_rtx, const0_rtx));
+ exponents = validize_mem (force_const_mem (V4SImode, x));
+
+ /* int_xmm = {0x45300000UL, fp_xmm/hi, 0x43300000, fp_xmm/lo } */
+ emit_insn (gen_sse2_punpckldq (int_xmm, int_xmm, exponents));
+
+ /* Concatenating (juxtaposing) (0x43300000UL ## fp_value_low_xmm)
+ yields a valid DF value equal to (0x1.0p52 + double(fp_value_lo_xmm)).
+ Similarly (0x45300000UL ## fp_value_hi_xmm) yields
+ (0x1.0p84 + double(fp_value_hi_xmm)).
+ Note these exponents differ by 32. */
+
+ fp_xmm = copy_to_mode_reg (V2DFmode, gen_lowpart (V2DFmode, int_xmm));
+
+ /* Subtract off those 0x1.0p52 and 0x1.0p84 biases, to produce values
+ in [0,2**32-1] and [0]+[2**32,2**64-1] respectively. */
+ real_ldexp (&bias_lo_rvt, &dconst1, 52);
+ real_ldexp (&bias_hi_rvt, &dconst1, 84);
+ biases = const_double_from_real_value (bias_lo_rvt, DFmode);
+ x = const_double_from_real_value (bias_hi_rvt, DFmode);
+ biases = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, biases, x));
+ biases = validize_mem (force_const_mem (V2DFmode, biases));
+ emit_insn (gen_subv2df3 (fp_xmm, fp_xmm, biases));
+
+ /* Add the upper and lower DFmode values together. */
+ if (TARGET_SSE3)
+ emit_insn (gen_sse3_haddv2df3 (fp_xmm, fp_xmm, fp_xmm));
+ else
+ {
+ x = copy_to_mode_reg (V2DFmode, fp_xmm);
+ emit_insn (gen_sse2_unpckhpd (fp_xmm, fp_xmm, fp_xmm));
+ emit_insn (gen_addv2df3 (fp_xmm, fp_xmm, x));
+ }
+
+ ix86_expand_vector_extract (false, target, fp_xmm, 0);
+}
+
+/* Convert an unsigned SImode value into a DFmode. Only currently used
+ for SSE, but applicable anywhere. */
+
+void
+ix86_expand_convert_uns_sidf_sse (rtx target, rtx input)
+{
+ REAL_VALUE_TYPE TWO31r;
+ rtx x, fp;
+
+ x = expand_simple_binop (SImode, PLUS, input, GEN_INT (-2147483647 - 1),
+ NULL, 1, OPTAB_DIRECT);
+
+ fp = gen_reg_rtx (DFmode);
+ emit_insn (gen_floatsidf2 (fp, x));
+
+ real_ldexp (&TWO31r, &dconst1, 31);
+ x = const_double_from_real_value (TWO31r, DFmode);
+
+ x = expand_simple_binop (DFmode, PLUS, fp, x, target, 0, OPTAB_DIRECT);
+ if (x != target)
+ emit_move_insn (target, x);
+}
+
+/* Convert a signed DImode value into a DFmode. Only used for SSE in
+ 32-bit mode; otherwise we have a direct convert instruction. */
+
+void
+ix86_expand_convert_sign_didf_sse (rtx target, rtx input)
+{
+ REAL_VALUE_TYPE TWO32r;
+ rtx fp_lo, fp_hi, x;
+
+ fp_lo = gen_reg_rtx (DFmode);
+ fp_hi = gen_reg_rtx (DFmode);
+
+ emit_insn (gen_floatsidf2 (fp_hi, gen_highpart (SImode, input)));
+
+ real_ldexp (&TWO32r, &dconst1, 32);
+ x = const_double_from_real_value (TWO32r, DFmode);
+ fp_hi = expand_simple_binop (DFmode, MULT, fp_hi, x, fp_hi, 0, OPTAB_DIRECT);
+
+ ix86_expand_convert_uns_sidf_sse (fp_lo, gen_lowpart (SImode, input));
+
+ x = expand_simple_binop (DFmode, PLUS, fp_hi, fp_lo, target,
+ 0, OPTAB_DIRECT);
+ if (x != target)
+ emit_move_insn (target, x);
+}
+
+/* Convert an unsigned SImode value into a SFmode, using only SSE.
+ For x86_32, -mfpmath=sse, !optimize_size only. */
+void
+ix86_expand_convert_uns_sisf_sse (rtx target, rtx input)
+{
+ REAL_VALUE_TYPE ONE16r;
+ rtx fp_hi, fp_lo, int_hi, int_lo, x;
+
+ real_ldexp (&ONE16r, &dconst1, 16);
+ x = const_double_from_real_value (ONE16r, SFmode);
+ int_lo = expand_simple_binop (SImode, AND, input, GEN_INT(0xffff),
+ NULL, 0, OPTAB_DIRECT);
+ int_hi = expand_simple_binop (SImode, LSHIFTRT, input, GEN_INT(16),
+ NULL, 0, OPTAB_DIRECT);
+ fp_hi = gen_reg_rtx (SFmode);
+ fp_lo = gen_reg_rtx (SFmode);
+ emit_insn (gen_floatsisf2 (fp_hi, int_hi));
+ emit_insn (gen_floatsisf2 (fp_lo, int_lo));
+ fp_hi = expand_simple_binop (SFmode, MULT, fp_hi, x, fp_hi,
+ 0, OPTAB_DIRECT);
+ fp_hi = expand_simple_binop (SFmode, PLUS, fp_hi, fp_lo, target,
+ 0, OPTAB_DIRECT);
+ if (!rtx_equal_p (target, fp_hi))
+ emit_move_insn (target, fp_hi);
+}
+
+/* A subroutine of ix86_build_signbit_mask_vector. If VECT is true,
+ then replicate the value for all elements of the vector
+ register. */
+
+rtx
+ix86_build_const_vector (enum machine_mode mode, bool vect, rtx value)
+{
+ rtvec v;
+ switch (mode)
+ {
+ case SFmode:
+ if (vect)
+ v = gen_rtvec (4, value, value, value, value);
+ else
+ v = gen_rtvec (4, value, CONST0_RTX (SFmode),
+ CONST0_RTX (SFmode), CONST0_RTX (SFmode));
+ return gen_rtx_CONST_VECTOR (V4SFmode, v);
+
+ case DFmode:
+ if (vect)
+ v = gen_rtvec (2, value, value);
+ else
+ v = gen_rtvec (2, value, CONST0_RTX (DFmode));
+ return gen_rtx_CONST_VECTOR (V2DFmode, v);
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* A subroutine of ix86_expand_fp_absneg_operator and copysign expanders.
Create a mask for the sign bit in MODE for an SSE register. If VECT is
true, then replicate the mask for all elements of the vector register.
enum machine_mode vec_mode;
HOST_WIDE_INT hi, lo;
int shift = 63;
- rtvec v;
+ rtx v;
rtx mask;
/* Find the sign bit, sign extended to 2*HWI. */
mask = immed_double_const (lo, hi, mode == SFmode ? SImode : DImode);
mask = gen_lowpart (mode, mask);
- if (mode == SFmode)
- {
- if (vect)
- v = gen_rtvec (4, mask, mask, mask, mask);
- else
- v = gen_rtvec (4, mask, CONST0_RTX (SFmode),
- CONST0_RTX (SFmode), CONST0_RTX (SFmode));
- vec_mode = V4SFmode;
- }
- else
- {
- if (vect)
- v = gen_rtvec (2, mask, mask);
- else
- v = gen_rtvec (2, mask, CONST0_RTX (DFmode));
- vec_mode = V2DFmode;
- }
-
- return force_reg (vec_mode, gen_rtx_CONST_VECTOR (vec_mode, v));
+ v = ix86_build_const_vector (mode, vect, mask);
+ vec_mode = (mode == SFmode) ? V4SFmode : V2DFmode;
+ return force_reg (vec_mode, v);
}
/* Generate code for floating point ABS or NEG. */
int
ix86_data_alignment (tree type, int align)
{
- int max_align = optimize_size ? BITS_PER_WORD : 256;
+ int max_align = optimize_size ? BITS_PER_WORD : MIN (256, MAX_OFILE_ALIGNMENT);
if (AGGREGATE_TYPE_P (type)
&& TYPE_SIZE (type)
{ MASK_SSE2, CODE_FOR_sse2_cvttps2dq, 0, IX86_BUILTIN_CVTTPS2DQ, 0, 0 },
/* SSE3 */
- { MASK_SSE3, CODE_FOR_sse3_movshdup, 0, IX86_BUILTIN_MOVSHDUP, 0, 0 },
- { MASK_SSE3, CODE_FOR_sse3_movsldup, 0, IX86_BUILTIN_MOVSLDUP, 0, 0 },
+ { MASK_SSE3, CODE_FOR_sse3_movshdup, "__builtin_ia32_movshdup", IX86_BUILTIN_MOVSHDUP, 0, 0 },
+ { MASK_SSE3, CODE_FOR_sse3_movsldup, "__builtin_ia32_movsldup", IX86_BUILTIN_MOVSLDUP, 0, 0 },
/* SSSE3 */
{ MASK_SSSE3, CODE_FOR_absv16qi2, "__builtin_ia32_pabsb128", IX86_BUILTIN_PABSB128, 0, 0 },
def_builtin (MASK_SSE3, "__builtin_ia32_mwait",
void_ftype_unsigned_unsigned,
IX86_BUILTIN_MWAIT);
- def_builtin (MASK_SSE3, "__builtin_ia32_movshdup",
- v4sf_ftype_v4sf,
- IX86_BUILTIN_MOVSHDUP);
- def_builtin (MASK_SSE3, "__builtin_ia32_movsldup",
- v4sf_ftype_v4sf,
- IX86_BUILTIN_MOVSLDUP);
def_builtin (MASK_SSE3, "__builtin_ia32_lddqu",
v16qi_ftype_pcchar, IX86_BUILTIN_LDDQU);
/* Subroutine of ix86_expand_builtin to take care of binop insns. */
static rtx
-ix86_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target)
+ix86_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
{
rtx pat, xops[3];
- tree arg0 = TREE_VALUE (arglist);
- tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ tree arg1 = CALL_EXPR_ARG (exp, 1);
rtx op0 = expand_normal (arg0);
rtx op1 = expand_normal (arg1);
enum machine_mode tmode = insn_data[icode].operand[0].mode;
/* Subroutine of ix86_expand_builtin to take care of stores. */
static rtx
-ix86_expand_store_builtin (enum insn_code icode, tree arglist)
+ix86_expand_store_builtin (enum insn_code icode, tree exp)
{
rtx pat;
- tree arg0 = TREE_VALUE (arglist);
- tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ tree arg1 = CALL_EXPR_ARG (exp, 1);
rtx op0 = expand_normal (arg0);
rtx op1 = expand_normal (arg1);
enum machine_mode mode0 = insn_data[icode].operand[0].mode;
/* Subroutine of ix86_expand_builtin to take care of unop insns. */
static rtx
-ix86_expand_unop_builtin (enum insn_code icode, tree arglist,
+ix86_expand_unop_builtin (enum insn_code icode, tree exp,
rtx target, int do_load)
{
rtx pat;
- tree arg0 = TREE_VALUE (arglist);
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
rtx op0 = expand_normal (arg0);
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
sqrtss, rsqrtss, rcpss. */
static rtx
-ix86_expand_unop1_builtin (enum insn_code icode, tree arglist, rtx target)
+ix86_expand_unop1_builtin (enum insn_code icode, tree exp, rtx target)
{
rtx pat;
- tree arg0 = TREE_VALUE (arglist);
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
rtx op1, op0 = expand_normal (arg0);
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
/* Subroutine of ix86_expand_builtin to take care of comparison insns. */
static rtx
-ix86_expand_sse_compare (const struct builtin_description *d, tree arglist,
+ix86_expand_sse_compare (const struct builtin_description *d, tree exp,
rtx target)
{
rtx pat;
- tree arg0 = TREE_VALUE (arglist);
- tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ tree arg1 = CALL_EXPR_ARG (exp, 1);
rtx op0 = expand_normal (arg0);
rtx op1 = expand_normal (arg1);
rtx op2;
/* Subroutine of ix86_expand_builtin to take care of comi insns. */
static rtx
-ix86_expand_sse_comi (const struct builtin_description *d, tree arglist,
+ix86_expand_sse_comi (const struct builtin_description *d, tree exp,
rtx target)
{
rtx pat;
- tree arg0 = TREE_VALUE (arglist);
- tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ tree arg1 = CALL_EXPR_ARG (exp, 1);
rtx op0 = expand_normal (arg0);
rtx op1 = expand_normal (arg1);
rtx op2;
these sorts of instructions. */
static rtx
-ix86_expand_vec_init_builtin (tree type, tree arglist, rtx target)
+ix86_expand_vec_init_builtin (tree type, tree exp, rtx target)
{
enum machine_mode tmode = TYPE_MODE (type);
enum machine_mode inner_mode = GET_MODE_INNER (tmode);
rtvec v = rtvec_alloc (n_elt);
gcc_assert (VECTOR_MODE_P (tmode));
+ gcc_assert (call_expr_nargs (exp) == n_elt);
- for (i = 0; i < n_elt; ++i, arglist = TREE_CHAIN (arglist))
+ for (i = 0; i < n_elt; ++i)
{
- rtx x = expand_normal (TREE_VALUE (arglist));
+ rtx x = expand_normal (CALL_EXPR_ARG (exp, i));
RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
}
- gcc_assert (arglist == NULL);
-
if (!target || !register_operand (target, tmode))
target = gen_reg_rtx (tmode);
had a language-level syntax for referencing vector elements. */
static rtx
-ix86_expand_vec_ext_builtin (tree arglist, rtx target)
+ix86_expand_vec_ext_builtin (tree exp, rtx target)
{
enum machine_mode tmode, mode0;
tree arg0, arg1;
int elt;
rtx op0;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
op0 = expand_normal (arg0);
elt = get_element_number (TREE_TYPE (arg0), arg1);
a language-level syntax for referencing vector elements. */
static rtx
-ix86_expand_vec_set_builtin (tree arglist)
+ix86_expand_vec_set_builtin (tree exp)
{
enum machine_mode tmode, mode1;
tree arg0, arg1, arg2;
int elt;
rtx op0, op1;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ arg2 = CALL_EXPR_ARG (exp, 2);
tmode = TYPE_MODE (TREE_TYPE (arg0));
mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
const struct builtin_description *d;
size_t i;
enum insn_code icode;
- tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
- tree arglist = TREE_OPERAND (exp, 1);
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
tree arg0, arg1, arg2, arg3;
rtx op0, op1, op2, op3, pat;
enum machine_mode tmode, mode0, mode1, mode2, mode3, mode4;
? CODE_FOR_mmx_maskmovq
: CODE_FOR_sse2_maskmovdqu);
/* Note the arg order is different from the operand order. */
- arg1 = TREE_VALUE (arglist);
- arg2 = TREE_VALUE (TREE_CHAIN (arglist));
- arg0 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ arg1 = CALL_EXPR_ARG (exp, 0);
+ arg2 = CALL_EXPR_ARG (exp, 1);
+ arg0 = CALL_EXPR_ARG (exp, 2);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
op2 = expand_normal (arg2);
return 0;
case IX86_BUILTIN_SQRTSS:
- return ix86_expand_unop1_builtin (CODE_FOR_sse_vmsqrtv4sf2, arglist, target);
+ return ix86_expand_unop1_builtin (CODE_FOR_sse_vmsqrtv4sf2, exp, target);
case IX86_BUILTIN_RSQRTSS:
- return ix86_expand_unop1_builtin (CODE_FOR_sse_vmrsqrtv4sf2, arglist, target);
+ return ix86_expand_unop1_builtin (CODE_FOR_sse_vmrsqrtv4sf2, exp, target);
case IX86_BUILTIN_RCPSS:
- return ix86_expand_unop1_builtin (CODE_FOR_sse_vmrcpv4sf2, arglist, target);
+ return ix86_expand_unop1_builtin (CODE_FOR_sse_vmrcpv4sf2, exp, target);
case IX86_BUILTIN_LOADUPS:
- return ix86_expand_unop_builtin (CODE_FOR_sse_movups, arglist, target, 1);
+ return ix86_expand_unop_builtin (CODE_FOR_sse_movups, exp, target, 1);
case IX86_BUILTIN_STOREUPS:
- return ix86_expand_store_builtin (CODE_FOR_sse_movups, arglist);
+ return ix86_expand_store_builtin (CODE_FOR_sse_movups, exp);
case IX86_BUILTIN_LOADHPS:
case IX86_BUILTIN_LOADLPS:
: fcode == IX86_BUILTIN_LOADLPS ? CODE_FOR_sse_loadlps
: fcode == IX86_BUILTIN_LOADHPD ? CODE_FOR_sse2_loadhpd
: CODE_FOR_sse2_loadlpd);
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
tmode = insn_data[icode].operand[0].mode;
case IX86_BUILTIN_STORELPS:
icode = (fcode == IX86_BUILTIN_STOREHPS ? CODE_FOR_sse_storehps
: CODE_FOR_sse_storelps);
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
mode0 = insn_data[icode].operand[0].mode;
return const0_rtx;
case IX86_BUILTIN_MOVNTPS:
- return ix86_expand_store_builtin (CODE_FOR_sse_movntv4sf, arglist);
+ return ix86_expand_store_builtin (CODE_FOR_sse_movntv4sf, exp);
case IX86_BUILTIN_MOVNTQ:
- return ix86_expand_store_builtin (CODE_FOR_sse_movntdi, arglist);
+ return ix86_expand_store_builtin (CODE_FOR_sse_movntdi, exp);
case IX86_BUILTIN_LDMXCSR:
- op0 = expand_normal (TREE_VALUE (arglist));
+ op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
target = assign_386_stack_local (SImode, SLOT_TEMP);
emit_move_insn (target, op0);
emit_insn (gen_sse_ldmxcsr (target));
icode = (fcode == IX86_BUILTIN_SHUFPS
? CODE_FOR_sse_shufps
: CODE_FOR_sse2_shufpd);
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ arg2 = CALL_EXPR_ARG (exp, 2);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
op2 = expand_normal (arg2);
: fcode == IX86_BUILTIN_PSHUFLW ? CODE_FOR_sse2_pshuflw
: fcode == IX86_BUILTIN_PSHUFD ? CODE_FOR_sse2_pshufd
: CODE_FOR_mmx_pshufw);
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
tmode = insn_data[icode].operand[0].mode;
case IX86_BUILTIN_PSRLDQI128:
icode = ( fcode == IX86_BUILTIN_PSLLDQI128 ? CODE_FOR_sse2_ashlti3
: CODE_FOR_sse2_lshrti3);
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
tmode = insn_data[icode].operand[0].mode;
return NULL_RTX;
case IX86_BUILTIN_PAVGUSB:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_uavgv8qi3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_uavgv8qi3, exp, target);
case IX86_BUILTIN_PF2ID:
- return ix86_expand_unop_builtin (CODE_FOR_mmx_pf2id, arglist, target, 0);
+ return ix86_expand_unop_builtin (CODE_FOR_mmx_pf2id, exp, target, 0);
case IX86_BUILTIN_PFACC:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_haddv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_haddv2sf3, exp, target);
case IX86_BUILTIN_PFADD:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_addv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_addv2sf3, exp, target);
case IX86_BUILTIN_PFCMPEQ:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_eqv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_eqv2sf3, exp, target);
case IX86_BUILTIN_PFCMPGE:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_gev2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_gev2sf3, exp, target);
case IX86_BUILTIN_PFCMPGT:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_gtv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_gtv2sf3, exp, target);
case IX86_BUILTIN_PFMAX:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_smaxv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_smaxv2sf3, exp, target);
case IX86_BUILTIN_PFMIN:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_sminv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_sminv2sf3, exp, target);
case IX86_BUILTIN_PFMUL:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_mulv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_mulv2sf3, exp, target);
case IX86_BUILTIN_PFRCP:
- return ix86_expand_unop_builtin (CODE_FOR_mmx_rcpv2sf2, arglist, target, 0);
+ return ix86_expand_unop_builtin (CODE_FOR_mmx_rcpv2sf2, exp, target, 0);
case IX86_BUILTIN_PFRCPIT1:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_rcpit1v2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_rcpit1v2sf3, exp, target);
case IX86_BUILTIN_PFRCPIT2:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_rcpit2v2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_rcpit2v2sf3, exp, target);
case IX86_BUILTIN_PFRSQIT1:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_rsqit1v2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_rsqit1v2sf3, exp, target);
case IX86_BUILTIN_PFRSQRT:
- return ix86_expand_unop_builtin (CODE_FOR_mmx_rsqrtv2sf2, arglist, target, 0);
+ return ix86_expand_unop_builtin (CODE_FOR_mmx_rsqrtv2sf2, exp, target, 0);
case IX86_BUILTIN_PFSUB:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_subv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_subv2sf3, exp, target);
case IX86_BUILTIN_PFSUBR:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_subrv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_subrv2sf3, exp, target);
case IX86_BUILTIN_PI2FD:
- return ix86_expand_unop_builtin (CODE_FOR_mmx_floatv2si2, arglist, target, 0);
+ return ix86_expand_unop_builtin (CODE_FOR_mmx_floatv2si2, exp, target, 0);
case IX86_BUILTIN_PMULHRW:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_pmulhrwv4hi3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_pmulhrwv4hi3, exp, target);
case IX86_BUILTIN_PF2IW:
- return ix86_expand_unop_builtin (CODE_FOR_mmx_pf2iw, arglist, target, 0);
+ return ix86_expand_unop_builtin (CODE_FOR_mmx_pf2iw, exp, target, 0);
case IX86_BUILTIN_PFNACC:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_hsubv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_hsubv2sf3, exp, target);
case IX86_BUILTIN_PFPNACC:
- return ix86_expand_binop_builtin (CODE_FOR_mmx_addsubv2sf3, arglist, target);
+ return ix86_expand_binop_builtin (CODE_FOR_mmx_addsubv2sf3, exp, target);
case IX86_BUILTIN_PI2FW:
- return ix86_expand_unop_builtin (CODE_FOR_mmx_pi2fw, arglist, target, 0);
+ return ix86_expand_unop_builtin (CODE_FOR_mmx_pi2fw, exp, target, 0);
case IX86_BUILTIN_PSWAPDSI:
- return ix86_expand_unop_builtin (CODE_FOR_mmx_pswapdv2si2, arglist, target, 0);
+ return ix86_expand_unop_builtin (CODE_FOR_mmx_pswapdv2si2, exp, target, 0);
case IX86_BUILTIN_PSWAPDSF:
- return ix86_expand_unop_builtin (CODE_FOR_mmx_pswapdv2sf2, arglist, target, 0);
+ return ix86_expand_unop_builtin (CODE_FOR_mmx_pswapdv2sf2, exp, target, 0);
case IX86_BUILTIN_SQRTSD:
- return ix86_expand_unop1_builtin (CODE_FOR_sse2_vmsqrtv2df2, arglist, target);
+ return ix86_expand_unop1_builtin (CODE_FOR_sse2_vmsqrtv2df2, exp, target);
case IX86_BUILTIN_LOADUPD:
- return ix86_expand_unop_builtin (CODE_FOR_sse2_movupd, arglist, target, 1);
+ return ix86_expand_unop_builtin (CODE_FOR_sse2_movupd, exp, target, 1);
case IX86_BUILTIN_STOREUPD:
- return ix86_expand_store_builtin (CODE_FOR_sse2_movupd, arglist);
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movupd, exp);
case IX86_BUILTIN_MFENCE:
emit_insn (gen_sse2_mfence ());
return 0;
case IX86_BUILTIN_CLFLUSH:
- arg0 = TREE_VALUE (arglist);
+ arg0 = CALL_EXPR_ARG (exp, 0);
op0 = expand_normal (arg0);
icode = CODE_FOR_sse2_clflush;
if (! (*insn_data[icode].operand[0].predicate) (op0, Pmode))
return 0;
case IX86_BUILTIN_MOVNTPD:
- return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2df, arglist);
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2df, exp);
case IX86_BUILTIN_MOVNTDQ:
- return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2di, arglist);
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2di, exp);
case IX86_BUILTIN_MOVNTI:
- return ix86_expand_store_builtin (CODE_FOR_sse2_movntsi, arglist);
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movntsi, exp);
case IX86_BUILTIN_LOADDQU:
- return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqu, arglist, target, 1);
+ return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqu, exp, target, 1);
case IX86_BUILTIN_STOREDQU:
- return ix86_expand_store_builtin (CODE_FOR_sse2_movdqu, arglist);
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movdqu, exp);
case IX86_BUILTIN_MONITOR:
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ arg2 = CALL_EXPR_ARG (exp, 2);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
op2 = expand_normal (arg2);
return 0;
case IX86_BUILTIN_MWAIT:
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
if (!REG_P (op0))
return 0;
case IX86_BUILTIN_LDDQU:
- return ix86_expand_unop_builtin (CODE_FOR_sse3_lddqu, arglist,
+ return ix86_expand_unop_builtin (CODE_FOR_sse3_lddqu, exp,
target, 1);
case IX86_BUILTIN_PALIGNR:
icode = CODE_FOR_ssse3_palignrti;
mode = V2DImode;
}
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ arg2 = CALL_EXPR_ARG (exp, 2);
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
return target;
case IX86_BUILTIN_MOVNTSD:
- return ix86_expand_store_builtin (CODE_FOR_sse4a_vmmovntv2df, arglist);
+ return ix86_expand_store_builtin (CODE_FOR_sse4a_vmmovntv2df, exp);
case IX86_BUILTIN_MOVNTSS:
- return ix86_expand_store_builtin (CODE_FOR_sse4a_vmmovntv4sf, arglist);
+ return ix86_expand_store_builtin (CODE_FOR_sse4a_vmmovntv4sf, exp);
case IX86_BUILTIN_INSERTQ:
case IX86_BUILTIN_EXTRQ:
icode = (fcode == IX86_BUILTIN_EXTRQ
? CODE_FOR_sse4a_extrq
: CODE_FOR_sse4a_insertq);
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
tmode = insn_data[icode].operand[0].mode;
case IX86_BUILTIN_EXTRQI:
icode = CODE_FOR_sse4a_extrqi;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ arg2 = CALL_EXPR_ARG (exp, 2);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
op2 = expand_normal (arg2);
case IX86_BUILTIN_INSERTQI:
icode = CODE_FOR_sse4a_insertqi;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ arg2 = CALL_EXPR_ARG (exp, 2);
+ arg3 = CALL_EXPR_ARG (exp, 3);
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
op2 = expand_normal (arg2);
case IX86_BUILTIN_VEC_INIT_V2SI:
case IX86_BUILTIN_VEC_INIT_V4HI:
case IX86_BUILTIN_VEC_INIT_V8QI:
- return ix86_expand_vec_init_builtin (TREE_TYPE (exp), arglist, target);
+ return ix86_expand_vec_init_builtin (TREE_TYPE (exp), exp, target);
case IX86_BUILTIN_VEC_EXT_V2DF:
case IX86_BUILTIN_VEC_EXT_V2DI:
case IX86_BUILTIN_VEC_EXT_V8HI:
case IX86_BUILTIN_VEC_EXT_V2SI:
case IX86_BUILTIN_VEC_EXT_V4HI:
- return ix86_expand_vec_ext_builtin (arglist, target);
+ return ix86_expand_vec_ext_builtin (exp, target);
case IX86_BUILTIN_VEC_SET_V8HI:
case IX86_BUILTIN_VEC_SET_V4HI:
- return ix86_expand_vec_set_builtin (arglist);
+ return ix86_expand_vec_set_builtin (exp);
default:
break;
|| d->icode == CODE_FOR_sse_vmmaskcmpv4sf3
|| d->icode == CODE_FOR_sse2_maskcmpv2df3
|| d->icode == CODE_FOR_sse2_vmmaskcmpv2df3)
- return ix86_expand_sse_compare (d, arglist, target);
+ return ix86_expand_sse_compare (d, exp, target);
- return ix86_expand_binop_builtin (d->icode, arglist, target);
+ return ix86_expand_binop_builtin (d->icode, exp, target);
}
for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
if (d->code == fcode)
- return ix86_expand_unop_builtin (d->icode, arglist, target, 0);
+ return ix86_expand_unop_builtin (d->icode, exp, target, 0);
for (i = 0, d = bdesc_comi; i < ARRAY_SIZE (bdesc_comi); i++, d++)
if (d->code == fcode)
- return ix86_expand_sse_comi (d, arglist, target);
+ return ix86_expand_sse_comi (d, exp, target);
gcc_unreachable ();
}
return NULL_TREE;
}
+/* Returns a decl of a function that implements conversion of the
+ input vector of type TYPE, or NULL_TREE if it is not available. */
+
+static tree
+ix86_builtin_conversion (enum tree_code code, tree type)
+{
+ if (TREE_CODE (type) != VECTOR_TYPE)
+ return NULL_TREE;
+
+ switch (code)
+ {
+ case FLOAT_EXPR:
+ switch (TYPE_MODE (type))
+ {
+ case V4SImode:
+ return ix86_builtins[IX86_BUILTIN_CVTDQ2PS];
+ default:
+ return NULL_TREE;
+ }
+
+ case FIX_TRUNC_EXPR:
+ switch (TYPE_MODE (type))
+ {
+ case V4SFmode:
+ return ix86_builtins[IX86_BUILTIN_CVTTPS2DQ];
+ default:
+ return NULL_TREE;
+ }
+ default:
+ return NULL_TREE;
+
+ }
+}
+
/* Store OPERAND to the memory after reload is completed. This means
that we can't easily use assign_stack_local. */
rtx
/* If the target says that inter-unit moves are more expensive
than moving through memory, then don't generate them. */
- if (!TARGET_INTER_UNIT_MOVES && !optimize_size)
+ if (!TARGET_INTER_UNIT_MOVES)
return true;
/* Between SSE and general, we have moves no larger than word size. */
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
return true;
-
- /* ??? For the cost of one register reformat penalty, we could use
- the same instructions to move SFmode and DFmode data, but the
- relevant move patterns don't support those alternatives. */
- if (mode == SFmode || mode == DFmode)
- return true;
}
return false;
mode = GET_MODE (out);
neglab = gen_label_rtx ();
donelab = gen_label_rtx ();
- i1 = gen_reg_rtx (Pmode);
f0 = gen_reg_rtx (mode);
- emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, Pmode, 0, neglab);
+ emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, inmode, 0, neglab);
+
+ expand_float (out, in, 0);
- emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
emit_jump_insn (gen_jump (donelab));
emit_barrier ();
emit_label (neglab);
- i0 = expand_simple_binop (Pmode, LSHIFTRT, in, const1_rtx, NULL, 1, OPTAB_DIRECT);
- i1 = expand_simple_binop (Pmode, AND, in, const1_rtx, NULL, 1, OPTAB_DIRECT);
- i0 = expand_simple_binop (Pmode, IOR, i0, i1, i0, 1, OPTAB_DIRECT);
+ i0 = expand_simple_binop (inmode, LSHIFTRT, in, const1_rtx, NULL,
+ 1, OPTAB_DIRECT);
+ i1 = expand_simple_binop (inmode, AND, in, const1_rtx, NULL,
+ 1, OPTAB_DIRECT);
+ i0 = expand_simple_binop (inmode, IOR, i0, i1, i0, 1, OPTAB_DIRECT);
+
expand_float (f0, i0, 0);
+
emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
emit_label (donelab);