aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386/i386.c')
-rw-r--r--gcc/config/i386/i386.c102
1 files changed, 63 insertions, 39 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 605135fcf1c..8b5faac5129 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2675,7 +2675,7 @@ rest_of_handle_insert_vzeroupper (void)
int i;
/* vzeroupper instructions are inserted immediately after reload to
- account for possible spills from 256bit registers. The pass
+ account for possible spills from 256bit or 512bit registers. The pass
reuses mode switching infrastructure by re-running mode insertion
pass, so disable entities that have already been processed. */
for (i = 0; i < MAX_386_ENTITIES; i++)
@@ -3650,7 +3650,7 @@ public:
/* opt_pass methods: */
virtual bool gate (function *)
{
- return TARGET_AVX && !TARGET_AVX512F
+ return TARGET_AVX
&& TARGET_VZEROUPPER && flag_expensive_optimizations
&& !optimize_size;
}
@@ -5196,6 +5196,12 @@ ix86_option_override_internal (bool main_args_p,
opts->x_ix86_isa_flags
|= OPTION_MASK_ISA_LZCNT & ~opts->x_ix86_isa_flags_explicit;
+ /* Disable BMI, BMI2 and TBM instructions for -m16. */
+ if (TARGET_16BIT_P(opts->x_ix86_isa_flags))
+ opts->x_ix86_isa_flags
+ &= ~((OPTION_MASK_ISA_BMI | OPTION_MASK_ISA_BMI2 | OPTION_MASK_ISA_TBM)
+ & ~opts->x_ix86_isa_flags_explicit);
+
/* Validate -mpreferred-stack-boundary= value or default it to
PREFERRED_STACK_BOUNDARY_DEFAULT. */
ix86_preferred_stack_boundary = PREFERRED_STACK_BOUNDARY_DEFAULT;
@@ -5464,7 +5470,8 @@ ix86_option_override_internal (bool main_args_p,
#endif
}
- if (!(opts_set->x_target_flags & MASK_VZEROUPPER))
+ if (!(opts_set->x_target_flags & MASK_VZEROUPPER)
+ && TARGET_EMIT_VZEROUPPER)
opts->x_target_flags |= MASK_VZEROUPPER;
if (!(opts_set->x_target_flags & MASK_STV))
opts->x_target_flags |= MASK_STV;
@@ -5552,12 +5559,6 @@ ix86_option_override_internal (bool main_args_p,
gcc_assert ((opts->x_target_flags & MASK_LONG_DOUBLE_64) == 0
|| (opts->x_target_flags & MASK_LONG_DOUBLE_128) == 0);
- /* Save the initial options in case the user does function specific
- options. */
- if (main_args_p)
- target_option_default_node = target_option_current_node
- = build_target_option_node (opts);
-
/* Handle stack protector */
if (!opts_set->x_ix86_stack_protector_guard)
opts->x_ix86_stack_protector_guard
@@ -5577,6 +5578,12 @@ ix86_option_override_internal (bool main_args_p,
ix86_parse_stringop_strategy_string (str, true);
free (str);
}
+
+ /* Save the initial options in case the user does function specific
+ options. */
+ if (main_args_p)
+ target_option_default_node = target_option_current_node
+ = build_target_option_node (opts);
}
/* Implement the TARGET_OPTION_OVERRIDE hook. */
@@ -17521,7 +17528,7 @@ ix86_print_operand_address_as (FILE *file, rtx addr,
/* Displacement only requires special attention. */
if (CONST_INT_P (disp))
{
- if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == ADDR_SPACE_GENERIC)
+ if (ASSEMBLER_DIALECT == ASM_INTEL && ADDR_SPACE_GENERIC_P (as))
fputs ("ds:", file);
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (disp));
}
@@ -18019,16 +18026,17 @@ output_387_binary_op (rtx insn, rtx *operands)
return buf;
}
-/* Check if a 256bit AVX register is referenced inside of EXP. */
+/* Check if a 256bit or 512 bit AVX register is referenced inside of EXP. */
static bool
-ix86_check_avx256_register (const_rtx exp)
+ix86_check_avx_upper_register (const_rtx exp)
{
if (SUBREG_P (exp))
exp = SUBREG_REG (exp);
return (REG_P (exp)
- && VALID_AVX256_REG_OR_OI_MODE (GET_MODE (exp)));
+ && (VALID_AVX256_REG_OR_OI_MODE (GET_MODE (exp))
+ || VALID_AVX512F_REG_OR_XI_MODE (GET_MODE (exp))));
}
/* Return needed mode for entity in optimize_mode_switching pass. */
@@ -18041,7 +18049,7 @@ ix86_avx_u128_mode_needed (rtx_insn *insn)
rtx link;
/* Needed mode is set to AVX_U128_CLEAN if there are
- no 256bit modes used in function arguments. */
+ no 256bit or 512bit modes used in function arguments. */
for (link = CALL_INSN_FUNCTION_USAGE (insn);
link;
link = XEXP (link, 1))
@@ -18050,7 +18058,7 @@ ix86_avx_u128_mode_needed (rtx_insn *insn)
{
rtx arg = XEXP (XEXP (link, 0), 0);
- if (ix86_check_avx256_register (arg))
+ if (ix86_check_avx_upper_register (arg))
return AVX_U128_DIRTY;
}
}
@@ -18058,13 +18066,13 @@ ix86_avx_u128_mode_needed (rtx_insn *insn)
return AVX_U128_CLEAN;
}
- /* Require DIRTY mode if a 256bit AVX register is referenced. Hardware
- changes state only when a 256bit register is written to, but we need
- to prevent the compiler from moving optimal insertion point above
- eventual read from 256bit register. */
+ /* Require DIRTY mode if a 256bit or 512bit AVX register is referenced.
+ Hardware changes state only when a 256bit register is written to,
+ but we need to prevent the compiler from moving optimal insertion
+ point above eventual read from 256bit or 512 bit register. */
subrtx_iterator::array_type array;
FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
- if (ix86_check_avx256_register (*iter))
+ if (ix86_check_avx_upper_register (*iter))
return AVX_U128_DIRTY;
return AVX_U128_ANY;
@@ -18144,12 +18152,12 @@ ix86_mode_needed (int entity, rtx_insn *insn)
return 0;
}
-/* Check if a 256bit AVX register is referenced in stores. */
+/* Check if a 256bit or 512bit AVX register is referenced in stores. */
static void
-ix86_check_avx256_stores (rtx dest, const_rtx, void *data)
+ix86_check_avx_upper_stores (rtx dest, const_rtx, void *data)
{
- if (ix86_check_avx256_register (dest))
+ if (ix86_check_avx_upper_register (dest))
{
bool *used = (bool *) data;
*used = true;
@@ -18168,18 +18176,18 @@ ix86_avx_u128_mode_after (int mode, rtx_insn *insn)
return AVX_U128_CLEAN;
/* We know that state is clean after CALL insn if there are no
- 256bit registers used in the function return register. */
+ 256bit or 512bit registers used in the function return register. */
if (CALL_P (insn))
{
- bool avx_reg256_found = false;
- note_stores (pat, ix86_check_avx256_stores, &avx_reg256_found);
+ bool avx_upper_reg_found = false;
+ note_stores (pat, ix86_check_avx_upper_stores, &avx_upper_reg_found);
- return avx_reg256_found ? AVX_U128_DIRTY : AVX_U128_CLEAN;
+ return avx_upper_reg_found ? AVX_U128_DIRTY : AVX_U128_CLEAN;
}
/* Otherwise, return current mode. Remember that if insn
- references AVX 256bit registers, the mode was already changed
- to DIRTY from MODE_NEEDED. */
+ references AVX 256bit or 512bit registers, the mode was already
+ changed to DIRTY from MODE_NEEDED. */
return mode;
}
@@ -18208,13 +18216,13 @@ ix86_avx_u128_mode_entry (void)
tree arg;
/* Entry mode is set to AVX_U128_DIRTY if there are
- 256bit modes used in function arguments. */
+ 256bit or 512bit modes used in function arguments. */
for (arg = DECL_ARGUMENTS (current_function_decl); arg;
arg = TREE_CHAIN (arg))
{
rtx incoming = DECL_INCOMING_RTL (arg);
- if (incoming && ix86_check_avx256_register (incoming))
+ if (incoming && ix86_check_avx_upper_register (incoming))
return AVX_U128_DIRTY;
}
@@ -18246,9 +18254,9 @@ ix86_avx_u128_mode_exit (void)
{
rtx reg = crtl->return_rtx;
- /* Exit mode is set to AVX_U128_DIRTY if there are
- 256bit modes used in the function return register. */
- if (reg && ix86_check_avx256_register (reg))
+ /* Exit mode is set to AVX_U128_DIRTY if there are 256bit
+ or 512 bit modes used in the function return register. */
+ if (reg && ix86_check_avx_upper_register (reg))
return AVX_U128_DIRTY;
return AVX_U128_CLEAN;
@@ -19666,13 +19674,13 @@ ix86_split_idivmod (machine_mode mode, rtx operands[],
if (signed_p)
{
- div = gen_rtx_DIV (SImode, operands[2], operands[3]);
- mod = gen_rtx_MOD (SImode, operands[2], operands[3]);
+ div = gen_rtx_DIV (mode, operands[2], operands[3]);
+ mod = gen_rtx_MOD (mode, operands[2], operands[3]);
}
else
{
- div = gen_rtx_UDIV (SImode, operands[2], operands[3]);
- mod = gen_rtx_UMOD (SImode, operands[2], operands[3]);
+ div = gen_rtx_UDIV (mode, operands[2], operands[3]);
+ mod = gen_rtx_UMOD (mode, operands[2], operands[3]);
}
/* Extract remainder from AH. */
@@ -36760,6 +36768,9 @@ sorted_attr_string (tree arglist)
{
const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
size_t len = strlen (str);
+ /* Skip empty string. */
+ if (len == 0)
+ continue;
str_len_sum += len + 1;
if (arg != arglist)
argnum++;
@@ -36774,11 +36785,21 @@ sorted_attr_string (tree arglist)
{
const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
size_t len = strlen (str);
+ /* Skip empty string. */
+ if (len == 0)
+ continue;
memcpy (attr_str + str_len_sum, str, len);
attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
str_len_sum += len + 1;
}
+ /* Strip ',' character at the end. */
+ if (str_len_sum > 0 && attr_str[str_len_sum - 1] == ',')
+ {
+ attr_str[str_len_sum - 1] = '\0';
+ str_len_sum--;
+ }
+
/* Replace "=,-" with "_". */
for (i = 0; i < strlen (attr_str); i++)
if (attr_str[i] == '=' || attr_str[i]== '-')
@@ -37395,6 +37416,7 @@ fold_builtin_cpu (tree fndecl, tree *args)
M_INTEL_KNL,
M_AMD_BTVER1,
M_AMD_BTVER2,
+ M_AMDFAM17H,
M_CPU_SUBTYPE_START,
M_INTEL_COREI7_NEHALEM,
M_INTEL_COREI7_WESTMERE,
@@ -37449,6 +37471,7 @@ fold_builtin_cpu (tree fndecl, tree *args)
{"bdver3", M_AMDFAM15H_BDVER3},
{"bdver4", M_AMDFAM15H_BDVER4},
{"btver2", M_AMD_BTVER2},
+ {"amdfam17h", M_AMDFAM17H},
{"znver1", M_AMDFAM17H_ZNVER1},
};
@@ -45190,7 +45213,8 @@ static void
x86_print_call_or_nop (FILE *file, const char *target)
{
if (flag_nop_mcount)
- fprintf (file, "1:\tnopl 0x00(%%eax,%%eax,1)\n"); /* 5 byte nop. */
+ /* 5 byte nop: nopl 0(%[re]ax,%[re]ax,1) */
+ fprintf (file, "1:" ASM_BYTE "0x0f, 0x1f, 0x44, 0x00, 0x00\n");
else
fprintf (file, "1:\tcall\t%s\n", target);
}