aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386-expand.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386/i386-expand.cc')
-rw-r--r--gcc/config/i386/i386-expand.cc188
1 files changed, 106 insertions, 82 deletions
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 7f0fdb6..83076ad 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -3396,8 +3396,7 @@ ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop)
too common scenario. */
start_sequence ();
compare_op = ix86_expand_fp_compare (code, op0, op1);
- compare_seq = get_insns ();
- end_sequence ();
+ compare_seq = end_sequence ();
if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode)
code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op));
@@ -3561,8 +3560,7 @@ ix86_expand_int_movcc (rtx operands[])
start_sequence ();
compare_op = ix86_expand_compare (code, op0, op1);
- compare_seq = get_insns ();
- end_sequence ();
+ compare_seq = end_sequence ();
compare_code = GET_CODE (compare_op);
@@ -3611,7 +3609,11 @@ ix86_expand_int_movcc (rtx operands[])
negate_cc_compare_p = true;
}
- diff = ct - cf;
+ diff = (unsigned HOST_WIDE_INT) ct - cf;
+ /* Make sure we can represent the difference between the two values. */
+ if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
+ return false;
+
/* Sign bit compares are better done using shifts than we do by using
sbb. */
if (sign_bit_compare_p
@@ -3669,7 +3671,12 @@ ix86_expand_int_movcc (rtx operands[])
PUT_CODE (compare_op,
reverse_condition (GET_CODE (compare_op)));
}
- diff = ct - cf;
+
+ diff = (unsigned HOST_WIDE_INT) ct - cf;
+ /* Make sure we can represent the difference
+ between the two values. */
+ if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
+ return false;
if (reg_overlap_mentioned_p (out, compare_op))
tmp = gen_reg_rtx (mode);
@@ -3687,7 +3694,12 @@ ix86_expand_int_movcc (rtx operands[])
else
{
std::swap (ct, cf);
- diff = ct - cf;
+
+ diff = (unsigned HOST_WIDE_INT) ct - cf;
+ /* Make sure we can represent the difference
+ between the two values. */
+ if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
+ return false;
}
tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
}
@@ -3754,9 +3766,15 @@ ix86_expand_int_movcc (rtx operands[])
tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
}
+ HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
+ /* Make sure we can represent the difference
+ between the two values. */
+ if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
+ return false;
+
tmp = expand_simple_binop (mode, AND,
copy_rtx (tmp),
- gen_int_mode (cf - ct, mode),
+ gen_int_mode (ival, mode),
copy_rtx (tmp), 1, OPTAB_DIRECT);
if (ct)
tmp = expand_simple_binop (mode, PLUS,
@@ -3793,7 +3811,13 @@ ix86_expand_int_movcc (rtx operands[])
if (new_code != UNKNOWN)
{
std::swap (ct, cf);
- diff = -diff;
+
+ diff = (unsigned HOST_WIDE_INT) ct - cf;
+ /* Make sure we can represent the difference
+ between the two values. */
+ if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
+ return false;
+
code = new_code;
}
}
@@ -3996,8 +4020,14 @@ ix86_expand_int_movcc (rtx operands[])
copy_rtx (out), 1, OPTAB_DIRECT);
}
+ HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
+ /* Make sure we can represent the difference
+ between the two values. */
+ if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
+ return false;
+
out = expand_simple_binop (mode, AND, copy_rtx (out),
- gen_int_mode (cf - ct, mode),
+ gen_int_mode (ival, mode),
copy_rtx (out), 1, OPTAB_DIRECT);
if (ct)
out = expand_simple_binop (mode, PLUS, copy_rtx (out), GEN_INT (ct),
@@ -4190,7 +4220,7 @@ ix86_valid_mask_cmp_mode (machine_mode mode)
if ((inner_mode == QImode || inner_mode == HImode) && !TARGET_AVX512BW)
return false;
- return (vector_size == 64 && TARGET_EVEX512) || TARGET_AVX512VL;
+ return vector_size == 64 || TARGET_AVX512VL;
}
/* Return true if integer mask comparison should be used. */
@@ -5028,7 +5058,7 @@ ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
&& GET_MODE_SIZE (GET_MODE_INNER (mode)) >= 4
/* Don't do it if not using integer masks and we'd end up with
the right values in the registers though. */
- && ((GET_MODE_SIZE (mode) == 64 && TARGET_EVEX512)
+ && (GET_MODE_SIZE (mode) == 64
|| !vector_all_ones_operand (optrue, data_mode)
|| opfalse != CONST0_RTX (data_mode))))
{
@@ -9321,7 +9351,6 @@ ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
bool need_zero_guard = false;
bool noalign;
machine_mode move_mode = VOIDmode;
- machine_mode wider_mode;
int unroll_factor = 1;
/* TODO: Once value ranges are available, fill in proper data. */
unsigned HOST_WIDE_INT min_size = 0;
@@ -9397,6 +9426,7 @@ ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
unroll_factor = 1;
move_mode = word_mode;
+ int nunits;
switch (alg)
{
case libcall:
@@ -9417,27 +9447,14 @@ ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
case vector_loop:
need_zero_guard = true;
unroll_factor = 4;
- /* Find the widest supported mode. */
- move_mode = word_mode;
- while (GET_MODE_WIDER_MODE (move_mode).exists (&wider_mode)
- && optab_handler (mov_optab, wider_mode) != CODE_FOR_nothing)
- move_mode = wider_mode;
-
- if (TARGET_AVX256_SPLIT_REGS && GET_MODE_BITSIZE (move_mode) > 128)
- move_mode = TImode;
- if (TARGET_AVX512_SPLIT_REGS && GET_MODE_BITSIZE (move_mode) > 256)
- move_mode = OImode;
-
- /* Find the corresponding vector mode with the same size as MOVE_MODE.
- MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */
- if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
+ /* Get the vector mode to move MOVE_MAX bytes. */
+ nunits = MOVE_MAX / GET_MODE_SIZE (word_mode);
+ if (nunits > 1)
{
- int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
- if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
- || optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
- move_mode = word_mode;
+ move_mode = mode_for_vector (word_mode, nunits).require ();
+ gcc_assert (optab_handler (mov_optab, move_mode)
+ != CODE_FOR_nothing);
}
- gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
break;
case rep_prefix_8_byte:
move_mode = DImode;
@@ -10121,9 +10138,11 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
if (lookup_attribute ("interrupt",
TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
error ("interrupt service routine cannot be called directly");
- else if (lookup_attribute ("no_callee_saved_registers",
- TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
+ else if (ix86_type_no_callee_saved_registers_p (TREE_TYPE (fndecl)))
call_no_callee_saved_registers = true;
+ if (fndecl == current_function_decl
+ && decl_binds_to_current_def_p (fndecl))
+ cfun->machine->recursive_function = true;
}
}
else
@@ -10133,8 +10152,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
tree mem_expr = MEM_EXPR (fnaddr);
if (mem_expr != nullptr
&& TREE_CODE (mem_expr) == MEM_REF
- && lookup_attribute ("no_callee_saved_registers",
- TYPE_ATTRIBUTES (TREE_TYPE (mem_expr))))
+ && ix86_type_no_callee_saved_registers_p (TREE_TYPE (mem_expr)))
call_no_callee_saved_registers = true;
}
@@ -10359,6 +10377,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi);
for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (!fixed_regs[i]
+ && i != HARD_FRAME_POINTER_REGNUM
&& !(ix86_call_used_regs[i] == 1
|| (ix86_call_used_regs[i] & c_mask))
&& !STACK_REGNO_P (i)
@@ -16191,7 +16210,7 @@ ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
{
case VEC_BCAST_PXOR:
if ((mode == V8SImode && !TARGET_AVX2)
- || (mode == V16SImode && !(TARGET_AVX512F && TARGET_EVEX512)))
+ || (mode == V16SImode && !TARGET_AVX512F))
return false;
emit_move_insn (target, CONST0_RTX (mode));
return true;
@@ -16199,7 +16218,7 @@ ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
case VEC_BCAST_PCMPEQ:
if ((mode == V4SImode && !TARGET_SSE2)
|| (mode == V8SImode && !TARGET_AVX2)
- || (mode == V16SImode && !(TARGET_AVX512F && TARGET_EVEX512)))
+ || (mode == V16SImode && !TARGET_AVX512F))
return false;
emit_move_insn (target, CONSTM1_RTX (mode));
return true;
@@ -16219,7 +16238,7 @@ ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
tmp2 = gen_reg_rtx (V32QImode);
emit_insn (gen_absv32qi2 (tmp2, tmp1));
}
- else if (mode == V16SImode && TARGET_AVX512BW && TARGET_EVEX512)
+ else if (mode == V16SImode && TARGET_AVX512BW)
{
tmp1 = gen_reg_rtx (V64QImode);
emit_move_insn (tmp1, CONSTM1_RTX (V64QImode));
@@ -16245,7 +16264,7 @@ ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
tmp2 = gen_reg_rtx (V32QImode);
emit_insn (gen_addv32qi3 (tmp2, tmp1, tmp1));
}
- else if (mode == V16SImode && TARGET_AVX512BW && TARGET_EVEX512)
+ else if (mode == V16SImode && TARGET_AVX512BW)
{
tmp1 = gen_reg_rtx (V64QImode);
emit_move_insn (tmp1, CONSTM1_RTX (V64QImode));
@@ -16271,7 +16290,7 @@ ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
tmp2 = gen_reg_rtx (V16HImode);
emit_insn (gen_lshrv16hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
}
- else if (mode == V16SImode && TARGET_AVX512BW && TARGET_EVEX512)
+ else if (mode == V16SImode && TARGET_AVX512BW)
{
tmp1 = gen_reg_rtx (V32HImode);
emit_move_insn (tmp1, CONSTM1_RTX (V32HImode));
@@ -16297,7 +16316,7 @@ ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
emit_insn (gen_lshrv8si3 (target, tmp1, GEN_INT (entry->arg)));
return true;
}
- else if (mode == V16SImode && TARGET_AVX512F && TARGET_EVEX512)
+ else if (mode == V16SImode && TARGET_AVX512F)
{
tmp1 = gen_reg_rtx (V16SImode);
emit_move_insn (tmp1, CONSTM1_RTX (V16SImode));
@@ -16323,7 +16342,7 @@ ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
tmp2 = gen_reg_rtx (V16HImode);
emit_insn (gen_ashlv16hi3 (tmp2, tmp1, GEN_INT (entry->arg)));
}
- else if (mode == V16SImode && TARGET_AVX512BW && TARGET_EVEX512)
+ else if (mode == V16SImode && TARGET_AVX512BW)
{
tmp1 = gen_reg_rtx (V32HImode);
emit_move_insn (tmp1, CONSTM1_RTX (V32HImode));
@@ -16349,7 +16368,7 @@ ix86_vector_duplicate_simode_const (machine_mode mode, rtx target,
emit_insn (gen_ashlv8si3 (target, tmp1, GEN_INT (entry->arg)));
return true;
}
- else if (mode == V16SImode && TARGET_AVX512F && TARGET_EVEX512)
+ else if (mode == V16SImode && TARGET_AVX512F)
{
tmp1 = gen_reg_rtx (V16SImode);
emit_move_insn (tmp1, CONSTM1_RTX (V16SImode));
@@ -16403,8 +16422,7 @@ ix86_vector_duplicate_value (machine_mode mode, rtx target, rtx val)
if (GET_MODE (reg) != innermode)
reg = gen_lowpart (innermode, reg);
SET_SRC (PATTERN (insn)) = gen_vec_duplicate (mode, reg);
- seq = get_insns ();
- end_sequence ();
+ seq = end_sequence ();
if (seq)
emit_insn_before (seq, insn);
@@ -16720,7 +16738,6 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, machine_mode mode,
case E_V32HFmode:
case E_V32BFmode:
- gcc_assert (TARGET_EVEX512);
if (TARGET_AVX512BW)
return ix86_vector_duplicate_value (mode, target, val);
else
@@ -16773,9 +16790,6 @@ ix86_expand_vector_init_one_nonzero (bool mmx_ok, machine_mode mode,
bool use_vector_set = false;
rtx (*gen_vec_set_0) (rtx, rtx, rtx) = NULL;
- if (GET_MODE_SIZE (mode) == 64 && !TARGET_EVEX512)
- return false;
-
switch (mode)
{
case E_V2DImode:
@@ -18731,6 +18745,33 @@ emit_reduc_half (rtx dest, rtx src, int i)
case E_V8HFmode:
case E_V4SImode:
case E_V2DImode:
+ if (TARGET_SSE_REDUCTION_PREFER_PSHUF)
+ {
+ if (i == 128)
+ {
+ d = gen_reg_rtx (V4SImode);
+ tem = gen_sse2_pshufd_1 (
+ d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
+ GEN_INT (2), GEN_INT (3), GEN_INT (2), GEN_INT (3));
+ break;
+ }
+ else if (i == 64)
+ {
+ d = gen_reg_rtx (V4SImode);
+ tem = gen_sse2_pshufd_1 (
+ d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
+ GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
+ break;
+ }
+ else if (i == 32)
+ {
+ d = gen_reg_rtx (V8HImode);
+ tem = gen_sse2_pshuflw_1 (
+ d, force_reg (V8HImode, gen_lowpart (V8HImode, src)),
+ GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
+ break;
+ }
+ }
d = gen_reg_rtx (V1TImode);
tem = gen_sse2_lshrv1ti3 (d, gen_lowpart (V1TImode, src),
GEN_INT (i / 2));
@@ -19437,7 +19478,7 @@ ix86_emit_swsqrtsf (rtx res, rtx a, machine_mode mode, bool recip)
unsigned vector_size = GET_MODE_SIZE (mode);
if (TARGET_FMA
- || (TARGET_AVX512F && TARGET_EVEX512 && vector_size == 64)
+ || (TARGET_AVX512F && vector_size == 64)
|| (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
emit_insn (gen_rtx_SET (e2,
gen_rtx_FMA (mode, e0, x0, mthree)));
@@ -22099,8 +22140,7 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
V4SImode this *will* succeed. For V8HImode or V16QImode it may not. */
start_sequence ();
ok = expand_vec_perm_1 (&dfinal);
- seq = get_insns ();
- end_sequence ();
+ seq = end_sequence ();
if (!ok)
return false;
@@ -22436,8 +22476,7 @@ expand_vec_perm_vperm2f128_vblend (struct expand_vec_perm_d *d)
start_sequence ();
ok = expand_vec_perm_1 (&dfirst);
- seq = get_insns ();
- end_sequence ();
+ seq = end_sequence ();
if (!ok)
return false;
@@ -22545,8 +22584,7 @@ expand_vec_perm_2perm_interleave (struct expand_vec_perm_d *d, bool two_insn)
{
start_sequence ();
ok = expand_vec_perm_1 (&dfirst);
- seq1 = get_insns ();
- end_sequence ();
+ seq1 = end_sequence ();
if (!ok)
return false;
@@ -22556,8 +22594,7 @@ expand_vec_perm_2perm_interleave (struct expand_vec_perm_d *d, bool two_insn)
{
start_sequence ();
ok = expand_vec_perm_1 (&dsecond);
- seq2 = get_insns ();
- end_sequence ();
+ seq2 = end_sequence ();
if (!ok)
return false;
@@ -22671,8 +22708,7 @@ expand_vec_perm_2perm_pblendv (struct expand_vec_perm_d *d, bool two_insn)
{
start_sequence ();
ok = expand_vec_perm_1 (&dfirst);
- seq1 = get_insns ();
- end_sequence ();
+ seq1 = end_sequence ();
if (!ok)
return false;
@@ -22682,8 +22718,7 @@ expand_vec_perm_2perm_pblendv (struct expand_vec_perm_d *d, bool two_insn)
{
start_sequence ();
ok = expand_vec_perm_1 (&dsecond);
- seq2 = get_insns ();
- end_sequence ();
+ seq2 = end_sequence ();
if (!ok)
return false;
@@ -22877,8 +22912,7 @@ expand_vec_perm2_vperm2f128_vblend (struct expand_vec_perm_d *d)
canonicalize_perm (&dfirst);
start_sequence ();
ok = ix86_expand_vec_perm_const_1 (&dfirst);
- seq1 = get_insns ();
- end_sequence ();
+ seq1 = end_sequence ();
if (!ok)
return false;
@@ -22886,8 +22920,7 @@ expand_vec_perm2_vperm2f128_vblend (struct expand_vec_perm_d *d)
canonicalize_perm (&dsecond);
start_sequence ();
ok = ix86_expand_vec_perm_const_1 (&dsecond);
- seq2 = get_insns ();
- end_sequence ();
+ seq2 = end_sequence ();
if (!ok)
return false;
@@ -24371,9 +24404,6 @@ ix86_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode,
unsigned int i, nelt, which;
bool two_args;
- if (GET_MODE_SIZE (vmode) == 64 && !TARGET_EVEX512)
- return false;
-
/* For HF and BF mode vector, convert it to HI using subreg. */
if (GET_MODE_INNER (vmode) == HFmode || GET_MODE_INNER (vmode) == BFmode)
{
@@ -24915,7 +24945,6 @@ ix86_expand_vecop_qihi2 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
ix86_expand_vecop_qihi. */
if (!TARGET_AVX512BW
|| (qimode == V16QImode && !TARGET_AVX512VL)
- || (qimode == V32QImode && !TARGET_EVEX512)
/* There are no V64HImode instructions. */
|| qimode == V64QImode)
return false;
@@ -25384,7 +25413,7 @@ ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2)
machine_mode mode = GET_MODE (op0);
rtx t1, t2, t3, t4, t5, t6;
- if (TARGET_AVX512DQ && TARGET_EVEX512 && mode == V8DImode)
+ if (TARGET_AVX512DQ && mode == V8DImode)
emit_insn (gen_avx512dq_mulv8di3 (op0, op1, op2));
else if (TARGET_AVX512DQ && TARGET_AVX512VL && mode == V4DImode)
emit_insn (gen_avx512dq_mulv4di3 (op0, op1, op2));
@@ -26114,8 +26143,7 @@ ix86_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn **gen_seq,
}
}
- *prep_seq = get_insns ();
- end_sequence ();
+ *prep_seq = end_sequence ();
start_sequence ();
@@ -26126,8 +26154,7 @@ ix86_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn **gen_seq,
end_sequence ();
return NULL_RTX;
}
- *gen_seq = get_insns ();
- end_sequence ();
+ *gen_seq = end_sequence ();
return res;
}
@@ -26170,8 +26197,7 @@ ix86_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev,
return NULL_RTX;
}
- *prep_seq = get_insns ();
- end_sequence ();
+ *prep_seq = end_sequence ();
target = gen_rtx_REG (cc_mode, FLAGS_REG);
dfv = ix86_get_flags_cc ((rtx_code) cmp_code);
@@ -26202,8 +26228,7 @@ ix86_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev,
return NULL_RTX;
}
- *gen_seq = get_insns ();
- end_sequence ();
+ *gen_seq = end_sequence ();
return gen_rtx_fmt_ee ((rtx_code) cmp_code, VOIDmode, target, const0_rtx);
}
@@ -26217,8 +26242,7 @@ ix86_gen_bcst_mem (machine_mode mode, rtx x)
{
if (!TARGET_AVX512F
|| !CONST_VECTOR_P (x)
- || (!TARGET_AVX512VL
- && (GET_MODE_SIZE (mode) != 64 || !TARGET_EVEX512))
+ || (!TARGET_AVX512VL && GET_MODE_SIZE (mode) != 64)
|| !VALID_BCST_MODE_P (GET_MODE_INNER (mode))
/* Disallow HFmode broadcast. */
|| GET_MODE_SIZE (GET_MODE_INNER (mode)) < 4)