diff options
Diffstat (limited to 'gcc/config/i386/i386.c')
-rw-r--r-- | gcc/config/i386/i386.c | 102 |
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); } |