diff options
Diffstat (limited to 'gcc/config/i386/i386.c')
-rw-r--r-- | gcc/config/i386/i386.c | 166 |
1 files changed, 107 insertions, 59 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index be94e4227c4..ae43ff8a515 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10762,11 +10762,11 @@ standard_80387_constant_rtx (int idx) XFmode); } -/* Return 1 if X is all 0s and 2 if x is all 1s +/* Return 1 if X is all bits 0 and 2 if X is all bits 1 in supported SSE/AVX vector mode. */ int -standard_sse_constant_p (rtx x) +standard_sse_constant_p (rtx x, machine_mode pred_mode) { machine_mode mode; @@ -10774,33 +10774,37 @@ standard_sse_constant_p (rtx x) return 0; mode = GET_MODE (x); - - if (x == const0_rtx || x == CONST0_RTX (mode)) + + if (x == const0_rtx || const0_operand (x, mode)) return 1; - if (vector_all_ones_operand (x, mode)) - switch (mode) - { - case V16QImode: - case V8HImode: - case V4SImode: - case V2DImode: - if (TARGET_SSE2) - return 2; - case V32QImode: - case V16HImode: - case V8SImode: - case V4DImode: - if (TARGET_AVX2) - return 2; - case V64QImode: - case V32HImode: - case V16SImode: - case V8DImode: - if (TARGET_AVX512F) - return 2; - default: - break; - } + + if (x == constm1_rtx || vector_all_ones_operand (x, mode)) + { + /* VOIDmode integer constant, get mode from the predicate. */ + if (mode == VOIDmode) + mode = pred_mode; + + switch (GET_MODE_SIZE (mode)) + { + case 64: + if (TARGET_AVX512F) + return 2; + break; + case 32: + if (TARGET_AVX2) + return 2; + break; + case 16: + if (TARGET_SSE2) + return 2; + break; + case 0: + /* VOIDmode */ + gcc_unreachable (); + default: + break; + } + } return 0; } @@ -10811,53 +10815,85 @@ standard_sse_constant_p (rtx x) const char * standard_sse_constant_opcode (rtx_insn *insn, rtx x) { - switch (standard_sse_constant_p (x)) + machine_mode mode; + + gcc_assert (TARGET_SSE); + + mode = GET_MODE (x); + + if (x == const0_rtx || const0_operand (x, mode)) { - case 1: switch (get_attr_mode (insn)) { case MODE_XI: return "vpxord\t%g0, %g0, %g0"; - case MODE_V16SF: - return TARGET_AVX512DQ ? "vxorps\t%g0, %g0, %g0" - : "vpxord\t%g0, %g0, %g0"; - case MODE_V8DF: - return TARGET_AVX512DQ ? "vxorpd\t%g0, %g0, %g0" - : "vpxorq\t%g0, %g0, %g0"; + case MODE_OI: + return (TARGET_AVX512VL + ? "vpxord\t%x0, %x0, %x0" + : "vpxor\t%x0, %x0, %x0"); case MODE_TI: - return TARGET_AVX512VL ? "vpxord\t%t0, %t0, %t0" - : "%vpxor\t%0, %d0"; + return (TARGET_AVX512VL + ? "vpxord\t%t0, %t0, %t0" + : "%vpxor\t%0, %d0"); + + case MODE_V8DF: + return (TARGET_AVX512DQ + ? "vxorpd\t%g0, %g0, %g0" + : "vpxorq\t%g0, %g0, %g0"); + case MODE_V4DF: + return "vxorpd\t%x0, %x0, %x0"; case MODE_V2DF: return "%vxorpd\t%0, %d0"; + + case MODE_V16SF: + return (TARGET_AVX512DQ + ? "vxorps\t%g0, %g0, %g0" + : "vpxord\t%g0, %g0, %g0"); + case MODE_V8SF: + return "vxorps\t%x0, %x0, %x0"; case MODE_V4SF: return "%vxorps\t%0, %d0"; + default: + gcc_unreachable (); + } + } + else if (x == constm1_rtx || vector_all_ones_operand (x, mode)) + { + enum attr_mode insn_mode = get_attr_mode (insn); + + switch (insn_mode) + { + case MODE_XI: + case MODE_V8DF: + case MODE_V16SF: + gcc_assert (TARGET_AVX512F); + break; case MODE_OI: - return TARGET_AVX512VL ? "vpxord\t%x0, %x0, %x0" - : "vpxor\t%x0, %x0, %x0"; case MODE_V4DF: - return "vxorpd\t%x0, %x0, %x0"; case MODE_V8SF: - return "vxorps\t%x0, %x0, %x0"; - - default: + gcc_assert (TARGET_AVX2); + break; + case MODE_TI: + case MODE_V2DF: + case MODE_V4SF: + gcc_assert (TARGET_SSE2); break; + default: + gcc_unreachable (); } - case 2: if (TARGET_AVX512VL - || get_attr_mode (insn) == MODE_XI - || get_attr_mode (insn) == MODE_V8DF - || get_attr_mode (insn) == MODE_V16SF) + || insn_mode == MODE_XI + || insn_mode == MODE_V8DF + || insn_mode == MODE_V16SF) return "vpternlogd\t{$0xFF, %g0, %g0, %g0|%g0, %g0, %g0, 0xFF}"; - if (TARGET_AVX) + else if (TARGET_AVX) return "vpcmpeqd\t%0, %0, %0"; else return "pcmpeqd\t%0, %0"; + } - default: - break; - } gcc_unreachable (); } @@ -14360,7 +14396,7 @@ darwin_local_data_pic (rtx disp) satisfies CONSTANT_P. */ static bool -ix86_legitimate_constant_p (machine_mode, rtx x) +ix86_legitimate_constant_p (machine_mode mode, rtx x) { /* Pointer bounds constants are not valid. */ if (POINTER_BOUNDS_MODE_P (GET_MODE (x))) @@ -14426,13 +14462,25 @@ ix86_legitimate_constant_p (machine_mode, rtx x) #endif break; + case CONST_INT: case CONST_WIDE_INT: - if (!TARGET_64BIT && !standard_sse_constant_p (x)) - return false; + switch (mode) + { + case TImode: + if (TARGET_64BIT) + return true; + /* FALLTHRU */ + case OImode: + case XImode: + if (!standard_sse_constant_p (x, mode)) + return false; + default: + break; + } break; case CONST_VECTOR: - if (!standard_sse_constant_p (x)) + if (!standard_sse_constant_p (x, mode)) return false; default: @@ -18759,7 +18807,7 @@ ix86_expand_vector_move (machine_mode mode, rtx operands[]) && (CONSTANT_P (op1) || (SUBREG_P (op1) && CONSTANT_P (SUBREG_REG (op1)))) - && !standard_sse_constant_p (op1)) + && !standard_sse_constant_p (op1, mode)) op1 = validize_mem (force_const_mem (mode, op1)); /* We need to check memory alignment for SSE mode since attribute @@ -43680,8 +43728,8 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno, } if (SSE_FLOAT_MODE_P (mode)) { - case CONST_VECTOR: - switch (standard_sse_constant_p (x)) + case CONST_VECTOR: + switch (standard_sse_constant_p (x, mode)) { case 0: break; |