diff options
Diffstat (limited to 'gcc/config/i386/i386-expand.cc')
-rw-r--r-- | gcc/config/i386/i386-expand.cc | 188 |
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) |