aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/i386
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386')
-rw-r--r--gcc/config/i386/constraints.md8
-rw-r--r--gcc/config/i386/cygming.opt4
-rw-r--r--gcc/config/i386/cygwin.h4
-rw-r--r--gcc/config/i386/gstabs.h7
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c487
-rw-r--r--gcc/config/i386/i386.h63
-rw-r--r--gcc/config/i386/i386.md66
-rw-r--r--gcc/config/i386/i386.opt18
-rw-r--r--gcc/config/i386/mingw.opt4
-rw-r--r--gcc/config/i386/mmx.md16
-rw-r--r--gcc/config/i386/openbsd.h101
-rw-r--r--gcc/config/i386/rtemself.h29
-rw-r--r--gcc/config/i386/sse.md160
-rw-r--r--gcc/config/i386/t-openbsd4
-rw-r--r--gcc/config/i386/winnt-cxx.c25
-rw-r--r--gcc/config/i386/winnt.c1
17 files changed, 575 insertions, 424 deletions
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index f94e274358b..98c05c9ebab 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -138,19 +138,19 @@
(define_register_constraint "Yd"
"TARGET_INTER_UNIT_MOVES_TO_VEC
- ? (TARGET_AVX512BW
+ ? (TARGET_AVX512DQ
? ALL_SSE_REGS
: (TARGET_SSE4_1 ? SSE_REGS : NO_REGS))
: NO_REGS"
- "@internal Any EVEX encodable SSE register (@code{%xmm0-%xmm31}) for AVX512BW target or any SSE register for SSE4_1 target, when inter-unit moves to vector registers are enabled.")
+ "@internal Any EVEX encodable SSE register (@code{%xmm0-%xmm31}) for AVX512DQ target or any SSE register for SSE4_1 target, when inter-unit moves to vector registers are enabled.")
(define_register_constraint "Ye"
"TARGET_INTER_UNIT_MOVES_FROM_VEC
- ? (TARGET_AVX512BW
+ ? (TARGET_AVX512DQ
? ALL_SSE_REGS
: (TARGET_SSE4_1 ? SSE_REGS : NO_REGS))
: NO_REGS"
- "@internal Any EVEX encodable SSE register (@code{%xmm0-%xmm31}) for AVX512BW target or any SSE register for SSE4_1 target, when inter-unit moves from vector registers are enabled.")
+ "@internal Any EVEX encodable SSE register (@code{%xmm0-%xmm31}) for AVX512DQ target or any SSE register for SSE4_1 target, when inter-unit moves from vector registers are enabled.")
(define_register_constraint "Ym"
"TARGET_MMX && TARGET_INTER_UNIT_MOVES_TO_VEC ? MMX_REGS : NO_REGS"
diff --git a/gcc/config/i386/cygming.opt b/gcc/config/i386/cygming.opt
index 2d7c7d2b674..abe59321040 100644
--- a/gcc/config/i386/cygming.opt
+++ b/gcc/config/i386/cygming.opt
@@ -50,6 +50,10 @@ muse-libstdc-wrappers
Target Condition({defined (USE_CYGWIN_LIBSTDCXX_WRAPPERS)})
Compile code that relies on Cygwin DLL wrappers to support C++ operator new/delete replacement.
+fset-stack-executable
+Common Report Var(flag_setstackexecutable) Init(1) Optimization
+For nested functions on stack executable permission is set.
+
posix
Driver
diff --git a/gcc/config/i386/cygwin.h b/gcc/config/i386/cygwin.h
index a4683b4662e..7e34bb799c3 100644
--- a/gcc/config/i386/cygwin.h
+++ b/gcc/config/i386/cygwin.h
@@ -153,3 +153,7 @@ along with GCC; see the file COPYING3. If not see
#endif
#define LIBGCC_SONAME "cyggcc_s" LIBGCC_EH_EXTN "-1.dll"
+/* Make stack executable to avoid DEP problems with trampolines. */
+#define HAVE_ENABLE_EXECUTE_STACK
+#undef CHECK_EXECUTE_STACK_ENABLED
+#define CHECK_EXECUTE_STACK_ENABLED flag_setstackexecutable
diff --git a/gcc/config/i386/gstabs.h b/gcc/config/i386/gstabs.h
deleted file mode 100644
index e9a621871e3..00000000000
--- a/gcc/config/i386/gstabs.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* We do not want to output SDB debugging information. */
-
-#undef SDB_DEBUGGING_INFO
-
-/* We want to output DBX debugging information. */
-
-#define DBX_DEBUGGING_INFO 1
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index bf8a0492592..2c15ba8505c 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -201,6 +201,8 @@ extern void ix86_expand_truncdf_32 (rtx, rtx);
extern void ix86_expand_vecop_qihi (enum rtx_code, rtx, rtx, rtx);
+extern rtx ix86_split_stack_guard (void);
+
#ifdef TREE_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
#endif /* TREE_CODE */
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index eac76815287..b04321a8d40 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -94,6 +94,7 @@ static rtx legitimize_pe_coff_extern_decl (rtx, bool);
static rtx legitimize_pe_coff_symbol (rtx, bool);
static void ix86_print_operand_address_as (FILE *, rtx, addr_space_t, bool);
static bool ix86_save_reg (unsigned int, bool, bool);
+static bool ix86_function_naked (const_tree);
#ifndef CHECK_STACK_LIMIT
#define CHECK_STACK_LIMIT (-1)
@@ -2491,9 +2492,7 @@ public:
unsigned last_reg = m->call_ms2sysv_extra_regs + MIN_REGS - 1;
gcc_assert (m->call_ms2sysv_extra_regs <= MAX_EXTRA_REGS);
- return m_regs[last_reg].offset
- + (m->call_ms2sysv_pad_out ? 8 : 0)
- + STUB_INDEX_OFFSET;
+ return m_regs[last_reg].offset + STUB_INDEX_OFFSET;
}
/* Returns the offset for the base pointer used by the stub. */
@@ -6284,6 +6283,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;
@@ -6657,6 +6662,69 @@ ix86_option_override_internal (bool main_args_p,
opts->x_ix86_stack_protector_guard
= TARGET_HAS_BIONIC ? SSP_GLOBAL : SSP_TLS;
+#ifdef TARGET_THREAD_SSP_OFFSET
+ ix86_stack_protector_guard_offset = TARGET_THREAD_SSP_OFFSET;
+#endif
+
+ if (global_options_set.x_ix86_stack_protector_guard_offset_str)
+ {
+ char *endp;
+ const char *str = ix86_stack_protector_guard_offset_str;
+
+ errno = 0;
+ int64_t offset;
+
+#if defined(INT64_T_IS_LONG)
+ offset = strtol (str, &endp, 0);
+#else
+ offset = strtoll (str, &endp, 0);
+#endif
+
+ if (!*str || *endp || errno)
+ error ("%qs is not a valid number "
+ "in -mstack-protector-guard-offset=", str);
+
+ if (!IN_RANGE (offset, HOST_WIDE_INT_C (-0x80000000),
+ HOST_WIDE_INT_C (0x7fffffff)))
+ error ("%qs is not a valid offset "
+ "in -mstack-protector-guard-offset=", str);
+
+ ix86_stack_protector_guard_offset = offset;
+ }
+
+ ix86_stack_protector_guard_reg = DEFAULT_TLS_SEG_REG;
+
+ /* The kernel uses a different segment register for performance
+ reasons; a system call would not have to trash the userspace
+ segment register, which would be expensive. */
+ if (ix86_cmodel == CM_KERNEL)
+ ix86_stack_protector_guard_reg = ADDR_SPACE_SEG_GS;
+
+ if (global_options_set.x_ix86_stack_protector_guard_reg_str)
+ {
+ const char *str = ix86_stack_protector_guard_reg_str;
+ addr_space_t seg = ADDR_SPACE_GENERIC;
+
+ /* Discard optional register prefix. */
+ if (str[0] == '%')
+ str++;
+
+ if (strlen (str) == 2 && str[1] == 's')
+ {
+ if (str[0] == 'f')
+ seg = ADDR_SPACE_SEG_FS;
+ else if (str[0] == 'g')
+ seg = ADDR_SPACE_SEG_GS;
+ }
+
+ if (seg == ADDR_SPACE_GENERIC)
+ error ("%qs is not a valid base register "
+ "in -mstack-protector-guard-reg=",
+ ix86_stack_protector_guard_reg_str);
+
+ ix86_stack_protector_guard_reg = seg;
+ }
+
/* Handle -mmemcpy-strategy= and -mmemset-strategy= */
if (opts->x_ix86_tune_memcpy_strategy)
{
@@ -7516,6 +7584,10 @@ ix86_set_func_type (tree fndecl)
if (lookup_attribute ("interrupt",
TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
{
+ if (ix86_function_naked (fndecl))
+ error_at (DECL_SOURCE_LOCATION (fndecl),
+ "interrupt and naked attributes are not compatible");
+
int nargs = 0;
for (tree arg = DECL_ARGUMENTS (fndecl);
arg;
@@ -7923,6 +7995,9 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
rtx a, b;
bool bind_global = decl && !targetm.binds_local_p (decl);
+ if (ix86_function_naked (current_function_decl))
+ return false;
+
/* Sibling call isn't OK if there are no caller-saved registers
since all registers must be preserved before return. */
if (cfun->machine->no_caller_saved_registers)
@@ -8742,6 +8817,15 @@ ix86_function_ms_hook_prologue (const_tree fn)
return false;
}
+static bool
+ix86_function_naked (const_tree fn)
+{
+ if (fn && lookup_attribute ("naked", DECL_ATTRIBUTES (fn)))
+ return true;
+
+ return false;
+}
+
/* Write the extra assembler code needed to declare a function properly. */
void
@@ -8771,16 +8855,15 @@ ix86_asm_output_function_label (FILE *asm_out_file, const char *fname,
if (TARGET_64BIT)
{
/* leaq [%rsp + 0], %rsp */
- asm_fprintf (asm_out_file, ASM_BYTE
- "0x48, 0x8d, 0xa4, 0x24, 0x00, 0x00, 0x00, 0x00\n");
+ fputs (ASM_BYTE "0x48, 0x8d, 0xa4, 0x24, 0x00, 0x00, 0x00, 0x00\n",
+ asm_out_file);
}
else
{
/* movl.s %edi, %edi
push %ebp
movl.s %esp, %ebp */
- asm_fprintf (asm_out_file, ASM_BYTE
- "0x8b, 0xff, 0x55, 0x8b, 0xec\n");
+ fputs (ASM_BYTE "0x8b, 0xff, 0x55, 0x8b, 0xec\n", asm_out_file);
}
}
}
@@ -10416,25 +10499,22 @@ ix86_function_arg (cumulative_args_t cum_v, machine_mode omode,
{
/* This is the pointer argument. */
gcc_assert (TYPE_MODE (type) == Pmode);
- if (cfun->machine->func_type == TYPE_INTERRUPT)
- /* -WORD(AP) in the current frame in interrupt handler. */
- arg = plus_constant (Pmode, arg_pointer_rtx,
- -UNITS_PER_WORD);
- else
- /* (AP) in the current frame in exception handler. */
- arg = arg_pointer_rtx;
+ /* It is at -WORD(AP) in the current frame in interrupt and
+ exception handlers. */
+ arg = plus_constant (Pmode, arg_pointer_rtx, -UNITS_PER_WORD);
}
else
{
gcc_assert (cfun->machine->func_type == TYPE_EXCEPTION
&& TREE_CODE (type) == INTEGER_TYPE
&& TYPE_MODE (type) == word_mode);
- /* The integer argument is the error code at -WORD(AP) in
- the current frame in exception handler. */
+ /* The error code is the word-mode integer argument at
+ -2 * WORD(AP) in the current frame of the exception
+ handler. */
arg = gen_rtx_MEM (word_mode,
plus_constant (Pmode,
arg_pointer_rtx,
- -UNITS_PER_WORD));
+ -2 * UNITS_PER_WORD));
}
return arg;
}
@@ -12247,6 +12327,9 @@ ix86_can_use_return_insn_p (void)
{
struct ix86_frame frame;
+ if (ix86_function_naked (current_function_decl))
+ return false;
+
/* Don't use `ret' instruction in interrupt handler. */
if (! reload_completed
|| frame_pointer_needed
@@ -12843,13 +12926,12 @@ ix86_compute_frame_layout (void)
{
unsigned count = xlogue_layout::count_stub_managed_regs ();
m->call_ms2sysv_extra_regs = count - xlogue_layout::MIN_REGS;
+ m->call_ms2sysv_pad_in = 0;
}
}
frame->nregs = ix86_nsaved_regs ();
frame->nsseregs = ix86_nsaved_sseregs ();
- m->call_ms2sysv_pad_in = 0;
- m->call_ms2sysv_pad_out = 0;
/* 64-bit MS ABI seem to require stack alignment to be always 16,
except for function prologues, leaf functions and when the defult
@@ -12909,8 +12991,8 @@ ix86_compute_frame_layout (void)
the registers need to be saved before allocating the frame. */
&& flag_stack_check != STATIC_BUILTIN_STACK_CHECK);
- /* Skip return address. */
- offset = UNITS_PER_WORD;
+ /* Skip return address and error code in exception handler. */
+ offset = INCOMING_FRAME_SP_OFFSET;
/* Skip pushed static chain. */
if (ix86_static_chain_on_stack)
@@ -12951,16 +13033,7 @@ ix86_compute_frame_layout (void)
gcc_assert (!frame->nsseregs);
m->call_ms2sysv_pad_in = !!(offset & UNITS_PER_WORD);
-
- /* Select an appropriate layout for incoming stack offset. */
- const struct xlogue_layout &xlogue = xlogue_layout::get_instance ();
-
- if ((offset + xlogue.get_stack_space_used ()) & UNITS_PER_WORD)
- m->call_ms2sysv_pad_out = 1;
-
- offset += xlogue.get_stack_space_used ();
- gcc_assert (!(offset & 0xf));
- frame->outlined_save_offset = offset;
+ offset += xlogue_layout::get_instance ().get_stack_space_used ();
}
/* Align and set SSE register save area. */
@@ -12988,6 +13061,7 @@ ix86_compute_frame_layout (void)
/* Align start of frame for local function. */
if (stack_realign_fp
+ || m->call_ms2sysv
|| offset != frame->sse_reg_save_offset
|| size != 0
|| !crtl->is_leaf
@@ -13096,24 +13170,26 @@ choose_baseaddr_len (unsigned int regno, HOST_WIDE_INT offset)
return len;
}
-/* Determine if the stack pointer is valid for accessing the cfa_offset. */
+/* Determine if the stack pointer is valid for accessing the cfa_offset.
+ The register is saved at CFA - CFA_OFFSET. */
static inline bool
sp_valid_at (HOST_WIDE_INT cfa_offset)
{
const struct machine_frame_state &fs = cfun->machine->fs;
return fs.sp_valid && !(fs.sp_realigned
- && cfa_offset < fs.sp_realigned_offset);
+ && cfa_offset <= fs.sp_realigned_offset);
}
-/* Determine if the frame pointer is valid for accessing the cfa_offset. */
+/* Determine if the frame pointer is valid for accessing the cfa_offset.
+ The register is saved at CFA - CFA_OFFSET. */
static inline bool
fp_valid_at (HOST_WIDE_INT cfa_offset)
{
const struct machine_frame_state &fs = cfun->machine->fs;
return fs.fp_valid && !(fs.sp_valid && fs.sp_realigned
- && cfa_offset >= fs.sp_realigned_offset);
+ && cfa_offset > fs.sp_realigned_offset);
}
/* Choose a base register based upon alignment requested, speed and/or
@@ -13588,8 +13664,7 @@ ix86_minimum_incoming_stack_boundary (bool sibcall)
{
unsigned int incoming_stack_boundary;
- /* Stack of interrupt handler is aligned to 128 bits in 64bit
- mode. */
+ /* Stack of interrupt handler is aligned to 128 bits in 64bit mode. */
if (cfun->machine->func_type != TYPE_NORMAL)
incoming_stack_boundary = TARGET_64BIT ? 128 : MIN_STACK_BOUNDARY;
/* Prefer the one specified at command line. */
@@ -14104,10 +14179,11 @@ output_probe_stack_range (rtx reg, rtx end)
return "";
}
-/* Finalize stack_realign_needed flag, which will guide prologue/epilogue
- to be generated in correct form. */
+/* Finalize stack_realign_needed and frame_pointer_needed flags, which
+ will guide prologue/epilogue to be generated in correct form. */
+
static void
-ix86_finalize_stack_realign_flags (void)
+ix86_finalize_stack_frame_flags (void)
{
/* Check if stack realign is really needed after reload, and
stores result in cfun */
@@ -14130,13 +14206,13 @@ ix86_finalize_stack_realign_flags (void)
}
/* If the only reason for frame_pointer_needed is that we conservatively
- assumed stack realignment might be needed, but in the end nothing that
- needed the stack alignment had been spilled, clear frame_pointer_needed
- and say we don't need stack realignment. */
- if (stack_realign
+ assumed stack realignment might be needed or -fno-omit-frame-pointer
+ is used, but in the end nothing that needed the stack alignment had
+ been spilled nor stack access, clear frame_pointer_needed and say we
+ don't need stack realignment. */
+ if ((stack_realign || !flag_omit_frame_pointer)
&& frame_pointer_needed
&& crtl->is_leaf
- && flag_omit_frame_pointer
&& crtl->sp_is_unchanging
&& !ix86_current_function_calls_tls_descriptor
&& !crtl->accesses_prior_frames
@@ -14324,7 +14400,10 @@ ix86_expand_prologue (void)
bool sse_registers_saved;
rtx static_chain = NULL_RTX;
- ix86_finalize_stack_realign_flags ();
+ if (ix86_function_naked (current_function_decl))
+ return;
+
+ ix86_finalize_stack_frame_flags ();
/* DRAP should not coexist with stack_realign_fp */
gcc_assert (!(crtl->drap_reg && stack_realign_fp));
@@ -15181,7 +15260,14 @@ ix86_expand_epilogue (int style)
bool using_drap;
bool restore_stub_is_tail = false;
- ix86_finalize_stack_realign_flags ();
+ if (ix86_function_naked (current_function_decl))
+ {
+ /* The program should not reach this point. */
+ emit_insn (gen_ud2 ());
+ return;
+ }
+
+ ix86_finalize_stack_frame_flags ();
frame = m->frame;
m->fs.sp_realigned = stack_realign_fp;
@@ -15214,8 +15300,9 @@ ix86_expand_epilogue (int style)
m->fs.red_zone_offset = 0;
if (ix86_using_red_zone () && crtl->args.pops_args < 65536)
{
- /* The red-zone begins below the return address. */
- m->fs.red_zone_offset = RED_ZONE_SIZE + UNITS_PER_WORD;
+ /* The red-zone begins below return address and error code in
+ exception handler. */
+ m->fs.red_zone_offset = RED_ZONE_SIZE + INCOMING_FRAME_SP_OFFSET;
/* When the register save area is in the aligned portion of
the stack, determine the maximum runtime displacement that
@@ -15510,18 +15597,7 @@ ix86_expand_epilogue (int style)
}
if (cfun->machine->func_type != TYPE_NORMAL)
- {
- /* Return with the "IRET" instruction from interrupt handler.
- Pop the 'ERROR_CODE' off the stack before the 'IRET'
- instruction in exception handler. */
- if (cfun->machine->func_type == TYPE_EXCEPTION)
- {
- rtx r = plus_constant (Pmode, stack_pointer_rtx,
- UNITS_PER_WORD);
- emit_insn (gen_rtx_SET (stack_pointer_rtx, r));
- }
- emit_jump_insn (gen_interrupt_return ());
- }
+ emit_jump_insn (gen_interrupt_return ());
else if (crtl->args.pops_args && crtl->args.size)
{
rtx popc = GEN_INT (crtl->args.pops_args);
@@ -15709,6 +15785,30 @@ static GTY(()) rtx split_stack_fn;
static GTY(()) rtx split_stack_fn_large;
+/* Return location of the stack guard value in the TLS block. */
+
+rtx
+ix86_split_stack_guard (void)
+{
+ int offset;
+ addr_space_t as = DEFAULT_TLS_SEG_REG;
+ rtx r;
+
+ gcc_assert (flag_split_stack);
+
+#ifdef TARGET_THREAD_SPLIT_STACK_OFFSET
+ offset = TARGET_THREAD_SPLIT_STACK_OFFSET;
+#else
+ gcc_unreachable ();
+#endif
+
+ r = GEN_INT (offset);
+ r = gen_const_mem (Pmode, r);
+ set_mem_addr_space (r, as);
+
+ return r;
+}
+
/* Handle -fsplit-stack. These are the first instructions in the
function, even before the regular prologue. */
@@ -15726,7 +15826,7 @@ ix86_expand_split_stack_prologue (void)
gcc_assert (flag_split_stack && reload_completed);
- ix86_finalize_stack_realign_flags ();
+ ix86_finalize_stack_frame_flags ();
frame = cfun->machine->frame;
allocate = frame.stack_pointer_offset - INCOMING_FRAME_SP_OFFSET;
@@ -15740,10 +15840,8 @@ ix86_expand_split_stack_prologue (void)
us SPLIT_STACK_AVAILABLE bytes, so if we need less than that we
can compare directly. Otherwise we need to do an addition. */
- limit = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
- UNSPEC_STACK_CHECK);
- limit = gen_rtx_CONST (Pmode, limit);
- limit = gen_rtx_MEM (Pmode, limit);
+ limit = ix86_split_stack_guard ();
+
if (allocate < SPLIT_STACK_AVAILABLE)
current = stack_pointer_rtx;
else
@@ -16181,9 +16279,9 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
/* Allow arg pointer and stack pointer as index if there is not scaling. */
if (base_reg && index_reg && scale == 1
- && (index_reg == arg_pointer_rtx
- || index_reg == frame_pointer_rtx
- || (REG_P (index_reg) && REGNO (index_reg) == STACK_POINTER_REGNUM)))
+ && (REGNO (index_reg) == ARG_POINTER_REGNUM
+ || REGNO (index_reg) == FRAME_POINTER_REGNUM
+ || REGNO (index_reg) == SP_REG))
{
std::swap (base, index);
std::swap (base_reg, index_reg);
@@ -16191,14 +16289,11 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
/* Special case: %ebp cannot be encoded as a base without a displacement.
Similarly %r13. */
- if (!disp
- && base_reg
- && (base_reg == hard_frame_pointer_rtx
- || base_reg == frame_pointer_rtx
- || base_reg == arg_pointer_rtx
- || (REG_P (base_reg)
- && (REGNO (base_reg) == HARD_FRAME_POINTER_REGNUM
- || REGNO (base_reg) == R13_REG))))
+ if (!disp && base_reg
+ && (REGNO (base_reg) == ARG_POINTER_REGNUM
+ || REGNO (base_reg) == FRAME_POINTER_REGNUM
+ || REGNO (base_reg) == BP_REG
+ || REGNO (base_reg) == R13_REG))
disp = const0_rtx;
/* Special case: on K6, [%esi] makes the instruction vector decoded.
@@ -16207,7 +16302,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
to test cfun for being non-NULL. */
if (TARGET_K6 && cfun && optimize_function_for_speed_p (cfun)
&& base_reg && !index_reg && !disp
- && REG_P (base_reg) && REGNO (base_reg) == SI_REG)
+ && REGNO (base_reg) == SI_REG)
disp = const0_rtx;
/* Special case: encode reg+reg instead of reg*2. */
@@ -16819,10 +16914,6 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict)
case UNSPEC_DTPOFF:
break;
- case UNSPEC_STACK_CHECK:
- gcc_assert (flag_split_stack);
- break;
-
default:
/* Invalid address unspec. */
return false;
@@ -17912,17 +18003,10 @@ output_pic_addr_const (FILE *file, rtx x, int code)
putc (ASSEMBLER_DIALECT == ASM_INTEL ? ')' : ']', file);
break;
- case UNSPEC:
- if (XINT (x, 1) == UNSPEC_STACK_CHECK)
- {
- bool f = i386_asm_output_addr_const_extra (file, x);
- gcc_assert (f);
- break;
- }
-
- gcc_assert (XVECLEN (x, 0) == 1);
- output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
- switch (XINT (x, 1))
+ case UNSPEC:
+ gcc_assert (XVECLEN (x, 0) == 1);
+ output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
+ switch (XINT (x, 1))
{
case UNSPEC_GOT:
fputs ("@GOT", file);
@@ -18615,7 +18699,6 @@ print_reg (rtx x, int code, FILE *file)
+ -- print a branch hint as 'cs' or 'ds' prefix
; -- print a semicolon (after prefixes due to bug in older gas).
~ -- print "i" if TARGET_AVX2, "f" otherwise.
- @ -- print a segment register of thread base pointer load
^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
! -- print MPX prefix for jxx/call/ret instructions if required.
*/
@@ -19159,19 +19242,6 @@ ix86_print_operand (FILE *file, rtx x, int code)
#endif
return;
- case '@':
- if (ASSEMBLER_DIALECT == ASM_ATT)
- putc ('%', file);
-
- /* The kernel uses a different segment register for performance
- reasons; a system call would not have to trash the userspace
- segment register, which would be expensive. */
- if (TARGET_64BIT && ix86_cmodel != CM_KERNEL)
- fputs ("fs", file);
- else
- fputs ("gs", file);
- return;
-
case '~':
putc (TARGET_AVX2 ? 'i' : 'f', file);
return;
@@ -19330,8 +19400,8 @@ ix86_print_operand (FILE *file, rtx x, int code)
static bool
ix86_print_operand_punct_valid_p (unsigned char code)
{
- return (code == '@' || code == '*' || code == '+' || code == '&'
- || code == ';' || code == '~' || code == '^' || code == '!');
+ return (code == '*' || code == '+' || code == '&' || code == ';'
+ || code == '~' || code == '^' || code == '!');
}
/* Print a memory operand whose address is ADDR. */
@@ -19430,7 +19500,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));
}
@@ -19632,22 +19702,6 @@ i386_asm_output_addr_const_extra (FILE *file, rtx x)
break;
#endif
- case UNSPEC_STACK_CHECK:
- {
- int offset;
-
- gcc_assert (flag_split_stack);
-
-#ifdef TARGET_THREAD_SPLIT_STACK_OFFSET
- offset = TARGET_THREAD_SPLIT_STACK_OFFSET;
-#else
- gcc_unreachable ();
-#endif
-
- fprintf (file, "%s:%d", TARGET_64BIT ? "%fs" : "%gs", offset);
- }
- break;
-
default:
return false;
}
@@ -31662,6 +31716,21 @@ ix86_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode);
#endif
}
+
+static bool
+ix86_allocate_stack_slots_for_args (void)
+{
+ /* Naked functions should not allocate stack slots for arguments. */
+ return !ix86_function_naked (current_function_decl);
+}
+
+static bool
+ix86_warn_func_return (tree decl)
+{
+ /* Naked functions are implemented entirely in assembly, including the
+ return sequence, so suppress warnings about this. */
+ return !ix86_function_naked (decl);
+}
/* The following file contains several enumerations and data structures
built from the definitions in i386-builtin-types.def. */
@@ -33393,13 +33462,18 @@ get_builtin_code_for_version (tree decl, tree *predicate_list)
break;
case PROCESSOR_NEHALEM:
if (new_target->x_ix86_isa_flags & OPTION_MASK_ISA_AES)
- arg_str = "westmere";
+ {
+ arg_str = "westmere";
+ priority = P_AES;
+ }
else
- /* We translate "arch=corei7" and "arch=nehalem" to
- "corei7" so that it will be mapped to M_INTEL_COREI7
- as cpu type to cover all M_INTEL_COREI7_XXXs. */
- arg_str = "corei7";
- priority = P_PROC_SSE4_2;
+ {
+ /* We translate "arch=corei7" and "arch=nehalem" to
+ "corei7" so that it will be mapped to M_INTEL_COREI7
+ as cpu type to cover all M_INTEL_COREI7_XXXs. */
+ arg_str = "corei7";
+ priority = P_PROC_SSE4_2;
+ }
break;
case PROCESSOR_SANDYBRIDGE:
if (new_target->x_ix86_isa_flags & OPTION_MASK_ISA_F16C)
@@ -33839,30 +33913,30 @@ ix86_get_function_versions_dispatcher (void *decl)
}
/* Make the resolver function decl to dispatch the versions of
- a multi-versioned function, DEFAULT_DECL. Create an
+ a multi-versioned function, DEFAULT_DECL. IFUNC_ALIAS_DECL is
+ ifunc alias that will point to the created resolver. Create an
empty basic block in the resolver and store the pointer in
EMPTY_BB. Return the decl of the resolver function. */
static tree
make_resolver_func (const tree default_decl,
- const tree dispatch_decl,
+ const tree ifunc_alias_decl,
basic_block *empty_bb)
{
char *resolver_name;
tree decl, type, decl_name, t;
- bool is_uniq = false;
/* IFUNC's have to be globally visible. So, if the default_decl is
not, then the name of the IFUNC should be made unique. */
if (TREE_PUBLIC (default_decl) == 0)
- is_uniq = true;
+ {
+ char *ifunc_name = make_unique_name (default_decl, "ifunc", true);
+ symtab->change_decl_assembler_name (ifunc_alias_decl,
+ get_identifier (ifunc_name));
+ XDELETEVEC (ifunc_name);
+ }
- /* Append the filename to the resolver function if the versions are
- not externally visible. This is because the resolver function has
- to be externally visible for the loader to find it. So, appending
- the filename will prevent conflicts with a resolver function from
- another module which is based on the same version name. */
- resolver_name = make_unique_name (default_decl, "resolver", is_uniq);
+ resolver_name = make_unique_name (default_decl, "resolver", false);
/* The resolver function should return a (void *). */
type = build_function_type_list (ptr_type_node, NULL_TREE);
@@ -33875,13 +33949,12 @@ make_resolver_func (const tree default_decl,
TREE_USED (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 0;
- /* IFUNC resolvers have to be externally visible. */
- TREE_PUBLIC (decl) = 1;
+ TREE_PUBLIC (decl) = 0;
DECL_UNINLINABLE (decl) = 1;
/* Resolver is not external, body is generated. */
DECL_EXTERNAL (decl) = 0;
- DECL_EXTERNAL (dispatch_decl) = 0;
+ DECL_EXTERNAL (ifunc_alias_decl) = 0;
DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = make_node (BLOCK);
@@ -33912,14 +33985,14 @@ make_resolver_func (const tree default_decl,
pop_cfun ();
- gcc_assert (dispatch_decl != NULL);
- /* Mark dispatch_decl as "ifunc" with resolver as resolver_name. */
- DECL_ATTRIBUTES (dispatch_decl)
- = make_attribute ("ifunc", resolver_name, DECL_ATTRIBUTES (dispatch_decl));
+ gcc_assert (ifunc_alias_decl != NULL);
+ /* Mark ifunc_alias_decl as "ifunc" with resolver as resolver_name. */
+ DECL_ATTRIBUTES (ifunc_alias_decl)
+ = make_attribute ("ifunc", resolver_name,
+ DECL_ATTRIBUTES (ifunc_alias_decl));
/* Create the alias for dispatch to resolver here. */
- /*cgraph_create_function_alias (dispatch_decl, decl);*/
- cgraph_node::create_same_body_alias (dispatch_decl, decl);
+ cgraph_node::create_same_body_alias (ifunc_alias_decl, decl);
XDELETEVEC (resolver_name);
return decl;
}
@@ -44118,6 +44191,26 @@ ix86_expand_vector_init_general (bool mmx_ok, machine_mode mode,
ix86_expand_vector_init_concat (mode, target, ops, n);
return;
+ case V2TImode:
+ for (i = 0; i < 2; i++)
+ ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
+ op0 = gen_reg_rtx (V4DImode);
+ ix86_expand_vector_init_concat (V4DImode, op0, ops, 2);
+ emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
+ return;
+
+ case V4TImode:
+ for (i = 0; i < 4; i++)
+ ops[i] = gen_lowpart (V2DImode, XVECEXP (vals, 0, i));
+ ops[4] = gen_reg_rtx (V4DImode);
+ ix86_expand_vector_init_concat (V4DImode, ops[4], ops, 2);
+ ops[5] = gen_reg_rtx (V4DImode);
+ ix86_expand_vector_init_concat (V4DImode, ops[5], ops + 2, 2);
+ op0 = gen_reg_rtx (V8DImode);
+ ix86_expand_vector_init_concat (V8DImode, op0, ops + 4, 2);
+ emit_move_insn (target, gen_lowpart (GET_MODE (target), op0));
+ return;
+
case V32QImode:
half_mode = V16QImode;
goto half;
@@ -44271,6 +44364,34 @@ ix86_expand_vector_init (bool mmx_ok, rtx target, rtx vals)
int i;
rtx x;
+ /* Handle first initialization from vector elts. */
+ if (n_elts != XVECLEN (vals, 0))
+ {
+ rtx subtarget = target;
+ x = XVECEXP (vals, 0, 0);
+ gcc_assert (GET_MODE_INNER (GET_MODE (x)) == inner_mode);
+ if (GET_MODE_NUNITS (GET_MODE (x)) * 2 == n_elts)
+ {
+ rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
+ if (inner_mode == QImode || inner_mode == HImode)
+ {
+ mode = mode_for_vector (SImode,
+ n_elts * GET_MODE_SIZE (inner_mode) / 4);
+ inner_mode
+ = mode_for_vector (SImode,
+ n_elts * GET_MODE_SIZE (inner_mode) / 8);
+ ops[0] = gen_lowpart (inner_mode, ops[0]);
+ ops[1] = gen_lowpart (inner_mode, ops[1]);
+ subtarget = gen_reg_rtx (mode);
+ }
+ ix86_expand_vector_init_concat (mode, subtarget, ops, 2);
+ if (subtarget != target)
+ emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
+ return;
+ }
+ gcc_unreachable ();
+ }
+
for (i = 0; i < n_elts; ++i)
{
x = XVECEXP (vals, 0, i);
@@ -44659,6 +44780,8 @@ ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
case V2DFmode:
case V2DImode:
+ case V2TImode:
+ case V4TImode:
use_vec_extr = true;
break;
@@ -45730,17 +45853,60 @@ ix86_mangle_type (const_tree type)
}
}
-#ifdef TARGET_THREAD_SSP_OFFSET
-/* If using TLS guards, don't waste time creating and expanding
- __stack_chk_guard decl and MEM as we are going to ignore it. */
+static GTY(()) tree ix86_tls_stack_chk_guard_decl;
+
static tree
ix86_stack_protect_guard (void)
{
if (TARGET_SSP_TLS_GUARD)
- return NULL_TREE;
+ {
+ tree type_node = lang_hooks.types.type_for_mode (ptr_mode, 1);
+ int qual = ENCODE_QUAL_ADDR_SPACE (ix86_stack_protector_guard_reg);
+ tree type = build_qualified_type (type_node, qual);
+ tree t;
+
+ if (global_options_set.x_ix86_stack_protector_guard_symbol_str)
+ {
+ t = ix86_tls_stack_chk_guard_decl;
+
+ if (t == NULL)
+ {
+ rtx x;
+
+ t = build_decl
+ (UNKNOWN_LOCATION, VAR_DECL,
+ get_identifier (ix86_stack_protector_guard_symbol_str),
+ type);
+ TREE_STATIC (t) = 1;
+ TREE_PUBLIC (t) = 1;
+ DECL_EXTERNAL (t) = 1;
+ TREE_USED (t) = 1;
+ TREE_THIS_VOLATILE (t) = 1;
+ DECL_ARTIFICIAL (t) = 1;
+ DECL_IGNORED_P (t) = 1;
+
+ /* Do not share RTL as the declaration is visible outside of
+ current function. */
+ x = DECL_RTL (t);
+ RTX_FLAG (x, used) = 1;
+
+ ix86_tls_stack_chk_guard_decl = t;
+ }
+ }
+ else
+ {
+ tree asptrtype = build_pointer_type (type);
+
+ t = build_int_cst (asptrtype, ix86_stack_protector_guard_offset);
+ t = build2 (MEM_REF, asptrtype, t,
+ build_int_cst (asptrtype, 0));
+ }
+
+ return t;
+ }
+
return default_stack_protect_guard ();
}
-#endif
/* For 32-bit code we can save PIC register setup by using
__stack_chk_fail_local hidden function instead of calling
@@ -46474,6 +46640,8 @@ static const struct attribute_spec ix86_attribute_table[] =
ix86_handle_interrupt_attribute, false },
{ "no_caller_saved_registers", 0, 0, false, true, true,
ix86_handle_no_caller_saved_registers_attribute, false },
+ { "naked", 0, 0, true, false, false,
+ ix86_handle_fndecl_attribute, false },
/* End element. */
{ NULL, 0, 0, false, false, false, NULL, false }
@@ -52683,6 +52851,8 @@ ix86_run_selftests (void)
#define TARGET_SETUP_INCOMING_VARARGS ix86_setup_incoming_varargs
#undef TARGET_MUST_PASS_IN_STACK
#define TARGET_MUST_PASS_IN_STACK ix86_must_pass_in_stack
+#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
+#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS ix86_allocate_stack_slots_for_args
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE ix86_function_arg_advance
#undef TARGET_FUNCTION_ARG
@@ -52710,6 +52880,9 @@ ix86_run_selftests (void)
#undef TARGET_RETURN_POPS_ARGS
#define TARGET_RETURN_POPS_ARGS ix86_return_pops_args
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN ix86_warn_func_return
+
#undef TARGET_LEGITIMATE_COMBINED_INSN
#define TARGET_LEGITIMATE_COMBINED_INSN ix86_legitimate_combined_insn
@@ -52741,10 +52914,8 @@ ix86_run_selftests (void)
#undef TARGET_MANGLE_TYPE
#define TARGET_MANGLE_TYPE ix86_mangle_type
-#ifdef TARGET_THREAD_SSP_OFFSET
#undef TARGET_STACK_PROTECT_GUARD
#define TARGET_STACK_PROTECT_GUARD ix86_stack_protect_guard
-#endif
#if !TARGET_MACHO
#undef TARGET_STACK_PROTECT_FAIL
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index a2ae9b4e242..e8ae3e3b3cc 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2165,7 +2165,7 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
/* Before the prologue, RA is at 0(%esp). */
#define INCOMING_RETURN_ADDR_RTX \
- gen_rtx_MEM (Pmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM))
+ gen_rtx_MEM (Pmode, stack_pointer_rtx)
/* After the prologue, RA is at -4(AP) in the current frame. */
#define RETURN_ADDR_RTX(COUNT, FRAME) \
@@ -2177,8 +2177,11 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
/* PC is dbx register 8; let's use that column for RA. */
#define DWARF_FRAME_RETURN_COLUMN (TARGET_64BIT ? 16 : 8)
-/* Before the prologue, the top of the frame is at 4(%esp). */
-#define INCOMING_FRAME_SP_OFFSET UNITS_PER_WORD
+/* Before the prologue, there are return address and error code for
+ exception handler on the top of the frame. */
+#define INCOMING_FRAME_SP_OFFSET \
+ (cfun->machine->func_type == TYPE_EXCEPTION \
+ ? 2 * UNITS_PER_WORD : UNITS_PER_WORD)
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) ((N) <= DX_REG ? (N) : INVALID_REGNUM)
@@ -2196,29 +2199,33 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
asm_preferred_eh_data_format ((CODE), (GLOBAL))
-/* This is how to output an insn to push a register on the stack.
- It need not be very fast code. */
+/* These are a couple of extensions to the formats accepted
+ by asm_fprintf:
+ %z prints out opcode suffix for word-mode instruction
+ %r prints out word-mode name for reg_names[arg] */
+#define ASM_FPRINTF_EXTENSIONS(FILE, ARGS, P) \
+ case 'z': \
+ fputc (TARGET_64BIT ? 'q' : 'l', (FILE)); \
+ break; \
+ \
+ case 'r': \
+ { \
+ unsigned int regno = va_arg ((ARGS), int); \
+ if (LEGACY_INT_REGNO_P (regno)) \
+ fputc (TARGET_64BIT ? 'r' : 'e', (FILE)); \
+ fputs (reg_names[regno], (FILE)); \
+ break; \
+ }
-#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \
-do { \
- if (TARGET_64BIT) \
- asm_fprintf ((FILE), "\tpush{q}\t%%r%s\n", \
- reg_names[(REGNO)] + (REX_INT_REGNO_P (REGNO) != 0)); \
- else \
- asm_fprintf ((FILE), "\tpush{l}\t%%e%s\n", reg_names[(REGNO)]); \
-} while (0)
+/* This is how to output an insn to push a register on the stack. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \
+ asm_fprintf ((FILE), "\tpush%z\t%%%r\n", (REGNO))
-/* This is how to output an insn to pop a register from the stack.
- It need not be very fast code. */
+/* This is how to output an insn to pop a register from the stack. */
#define ASM_OUTPUT_REG_POP(FILE, REGNO) \
-do { \
- if (TARGET_64BIT) \
- asm_fprintf ((FILE), "\tpop{q}\t%%r%s\n", \
- reg_names[(REGNO)] + (REX_INT_REGNO_P (REGNO) != 0)); \
- else \
- asm_fprintf ((FILE), "\tpop{l}\t%%e%s\n", reg_names[(REGNO)]); \
-} while (0)
+ asm_fprintf ((FILE), "\tpop%z\t%%%r\n", (REGNO))
/* This is how to output an element of a case-vector that is absolute. */
@@ -2477,8 +2484,7 @@ enum avx_u128_state
<- end of stub-saved/restored regs
[padding1]
]
- <- outlined_save_offset
- <- sse_regs_save_offset
+ <- sse_reg_save_offset
[padding2]
| <- FRAME_POINTER
[va_arg registers] |
@@ -2504,7 +2510,6 @@ struct GTY(()) ix86_frame
HOST_WIDE_INT reg_save_offset;
HOST_WIDE_INT stack_realign_allocate_offset;
HOST_WIDE_INT stack_realign_offset;
- HOST_WIDE_INT outlined_save_offset;
HOST_WIDE_INT sse_reg_save_offset;
/* When save_regs_using_mov is set, emit prologue using
@@ -2640,17 +2645,13 @@ struct GTY(()) machine_function {
BOOL_BITFIELD arg_reg_available : 1;
/* If true, we're out-of-lining reg save/restore for regs clobbered
- by ms_abi functions calling a sysv function. */
+ by 64-bit ms_abi functions calling a sysv_abi function. */
BOOL_BITFIELD call_ms2sysv : 1;
/* If true, the incoming 16-byte aligned stack has an offset (of 8) and
- needs padding. */
+ needs padding prior to out-of-line stub save/restore area. */
BOOL_BITFIELD call_ms2sysv_pad_in : 1;
- /* If true, the size of the stub save area plus inline int reg saves will
- result in an 8 byte offset, so needs padding. */
- BOOL_BITFIELD call_ms2sysv_pad_out : 1;
-
/* This is the number of extra registers saved by stub (valid range is
0-6). Each additional register is only saved/restored by the stubs
if all successive ones are. (Will always be zero when using a hard
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 5eff4e46fff..3af3b7aed4f 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -61,7 +61,6 @@
;; + -- print a branch hint as 'cs' or 'ds' prefix
;; ; -- print a semicolon (after prefixes due to bug in older gas).
;; ~ -- print "i" if TARGET_AVX2, "f" otherwise.
-;; @ -- print a segment register of thread base pointer load
;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
;; ! -- print MPX prefix for jxx/call/ret instructions if required.
@@ -87,7 +86,6 @@
UNSPEC_SET_RIP
UNSPEC_SET_GOT_OFFSET
UNSPEC_MEMORY_BLOCKAGE
- UNSPEC_STACK_CHECK
UNSPEC_PROBE_STACK
;; TLS support
@@ -166,8 +164,6 @@
;; SSP patterns
UNSPEC_SP_SET
UNSPEC_SP_TEST
- UNSPEC_SP_TLS_SET
- UNSPEC_SP_TLS_TEST
;; For ROUND support
UNSPEC_ROUND
@@ -201,6 +197,7 @@
])
(define_c_enum "unspecv" [
+ UNSPECV_UD2
UNSPECV_BLOCKAGE
UNSPECV_STACK_PROBE
UNSPECV_PROBE_STACK_RANGE
@@ -12632,20 +12629,17 @@
[(set (pc) (if_then_else
(ltu (minus (reg SP_REG)
(match_operand 0 "register_operand"))
- (unspec [(const_int 0)] UNSPEC_STACK_CHECK))
+ (match_dup 2))
(label_ref (match_operand 1))
(pc)))]
""
{
- rtx reg, size, limit;
+ rtx reg = gen_reg_rtx (Pmode);
- reg = gen_reg_rtx (Pmode);
- size = force_reg (Pmode, operands[0]);
- emit_insn (gen_sub3_insn (reg, stack_pointer_rtx, size));
- limit = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
- UNSPEC_STACK_CHECK);
- limit = gen_rtx_MEM (Pmode, gen_rtx_CONST (Pmode, limit));
- ix86_expand_branch (GEU, reg, limit, operands[1]);
+ emit_insn (gen_sub3_insn (reg, stack_pointer_rtx, operands[0]));
+
+ operands[2] = ix86_split_stack_guard ();
+ ix86_expand_branch (GEU, reg, operands[2], operands[1]);
DONE;
})
@@ -18606,6 +18600,18 @@
}
[(set_attr "length" "2")])
+(define_insn "ud2"
+ [(unspec_volatile [(const_int 0)] UNSPECV_UD2)]
+ ""
+{
+#ifdef HAVE_AS_IX86_UD2
+ return "ud2";
+#else
+ return ASM_SHORT "0x0b0f";
+#endif
+}
+ [(set_attr "length" "2")])
+
(define_expand "prefetch"
[(prefetch (match_operand 0 "address_operand")
(match_operand:SI 1 "const_int_operand")
@@ -18705,16 +18711,9 @@
{
rtx (*insn)(rtx, rtx);
-#ifdef TARGET_THREAD_SSP_OFFSET
- operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET);
- insn = (TARGET_LP64
- ? gen_stack_tls_protect_set_di
- : gen_stack_tls_protect_set_si);
-#else
insn = (TARGET_LP64
? gen_stack_protect_set_di
: gen_stack_protect_set_si);
-#endif
emit_insn (insn (operands[0], operands[1]));
DONE;
@@ -18730,16 +18729,6 @@
"mov{<imodesuffix>}\t{%1, %2|%2, %1}\;mov{<imodesuffix>}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
[(set_attr "type" "multi")])
-(define_insn "stack_tls_protect_set_<mode>"
- [(set (match_operand:PTR 0 "memory_operand" "=m")
- (unspec:PTR [(match_operand:PTR 1 "const_int_operand" "i")]
- UNSPEC_SP_TLS_SET))
- (set (match_scratch:PTR 2 "=&r") (const_int 0))
- (clobber (reg:CC FLAGS_REG))]
- ""
- "mov{<imodesuffix>}\t{%@:%P1, %2|%2, <iptrsize> PTR %@:%P1}\;mov{<imodesuffix>}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
- [(set_attr "type" "multi")])
-
(define_expand "stack_protect_test"
[(match_operand 0 "memory_operand")
(match_operand 1 "memory_operand")
@@ -18750,16 +18739,9 @@
rtx (*insn)(rtx, rtx, rtx);
-#ifdef TARGET_THREAD_SSP_OFFSET
- operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET);
- insn = (TARGET_LP64
- ? gen_stack_tls_protect_test_di
- : gen_stack_tls_protect_test_si);
-#else
insn = (TARGET_LP64
? gen_stack_protect_test_di
: gen_stack_protect_test_si);
-#endif
emit_insn (insn (flags, operands[0], operands[1]));
@@ -18778,16 +18760,6 @@
"mov{<imodesuffix>}\t{%1, %3|%3, %1}\;xor{<imodesuffix>}\t{%2, %3|%3, %2}"
[(set_attr "type" "multi")])
-(define_insn "stack_tls_protect_test_<mode>"
- [(set (match_operand:CCZ 0 "flags_reg_operand")
- (unspec:CCZ [(match_operand:PTR 1 "memory_operand" "m")
- (match_operand:PTR 2 "const_int_operand" "i")]
- UNSPEC_SP_TLS_TEST))
- (clobber (match_scratch:PTR 3 "=r"))]
- ""
- "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;xor{<imodesuffix>}\t{%@:%P2, %3|%3, <iptrsize> PTR %@:%P2}"
- [(set_attr "type" "multi")])
-
(define_insn "sse4_2_crc32<mode>"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index adc75f36602..cd564315f04 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -924,6 +924,24 @@ Enum(stack_protector_guard) String(tls) Value(SSP_TLS)
EnumValue
Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL)
+mstack-protector-guard-reg=
+Target RejectNegative Joined Var(ix86_stack_protector_guard_reg_str)
+Use the given base register for addressing the stack-protector guard.
+
+TargetVariable
+addr_space_t ix86_stack_protector_guard_reg = ADDR_SPACE_GENERIC
+
+mstack-protector-guard-offset=
+Target RejectNegative Joined Integer Var(ix86_stack_protector_guard_offset_str)
+Use the given offset for addressing the stack-protector guard.
+
+TargetVariable
+HOST_WIDE_INT ix86_stack_protector_guard_offset = 0
+
+mstack-protector-guard-symbol=
+Target RejectNegative Joined Integer Var(ix86_stack_protector_guard_symbol_str)
+Use the given symbol for addressing the stack-protector guard.
+
mmitigate-rop
Target Var(flag_mitigate_rop) Init(0)
Attempt to avoid generating instruction sequences containing ret bytes.
diff --git a/gcc/config/i386/mingw.opt b/gcc/config/i386/mingw.opt
index 210c14f549e..97a9baa6d7a 100644
--- a/gcc/config/i386/mingw.opt
+++ b/gcc/config/i386/mingw.opt
@@ -28,8 +28,4 @@ Wpedantic-ms-format
C ObjC C++ ObjC++ Var(warn_pedantic_ms_format) Init(1) Warning
Warn about none ISO msvcrt scanf/printf width extensions.
-fset-stack-executable
-Common Report Var(flag_setstackexecutable) Init(1) Optimization
-For nested functions on stack executable permission is set.
-
; Need to retain blank line above.
diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index 7a1789f0b47..b3f3633e964 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -641,7 +641,7 @@
[(set (match_dup 0) (match_dup 1))]
"operands[1] = adjust_address (operands[1], SFmode, 4);")
-(define_expand "vec_extractv2sf"
+(define_expand "vec_extractv2sfsf"
[(match_operand:SF 0 "register_operand")
(match_operand:V2SF 1 "register_operand")
(match_operand 2 "const_int_operand")]
@@ -652,7 +652,7 @@
DONE;
})
-(define_expand "vec_initv2sf"
+(define_expand "vec_initv2sfsf"
[(match_operand:V2SF 0 "register_operand")
(match_operand 1)]
"TARGET_SSE"
@@ -1344,7 +1344,7 @@
operands[1] = adjust_address (operands[1], SImode, INTVAL (operands[2]) * 4);
})
-(define_expand "vec_extractv2si"
+(define_expand "vec_extractv2sisi"
[(match_operand:SI 0 "register_operand")
(match_operand:V2SI 1 "register_operand")
(match_operand 2 "const_int_operand")]
@@ -1355,7 +1355,7 @@
DONE;
})
-(define_expand "vec_initv2si"
+(define_expand "vec_initv2sisi"
[(match_operand:V2SI 0 "register_operand")
(match_operand 1)]
"TARGET_SSE"
@@ -1375,7 +1375,7 @@
DONE;
})
-(define_expand "vec_extractv4hi"
+(define_expand "vec_extractv4hihi"
[(match_operand:HI 0 "register_operand")
(match_operand:V4HI 1 "register_operand")
(match_operand 2 "const_int_operand")]
@@ -1386,7 +1386,7 @@
DONE;
})
-(define_expand "vec_initv4hi"
+(define_expand "vec_initv4hihi"
[(match_operand:V4HI 0 "register_operand")
(match_operand 1)]
"TARGET_SSE"
@@ -1406,7 +1406,7 @@
DONE;
})
-(define_expand "vec_extractv8qi"
+(define_expand "vec_extractv8qiqi"
[(match_operand:QI 0 "register_operand")
(match_operand:V8QI 1 "register_operand")
(match_operand 2 "const_int_operand")]
@@ -1417,7 +1417,7 @@
DONE;
})
-(define_expand "vec_initv8qi"
+(define_expand "vec_initv8qiqi"
[(match_operand:V8QI 0 "register_operand")
(match_operand 1)]
"TARGET_SSE"
diff --git a/gcc/config/i386/openbsd.h b/gcc/config/i386/openbsd.h
deleted file mode 100644
index 7d37c0de922..00000000000
--- a/gcc/config/i386/openbsd.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Configuration for an OpenBSD i386 target.
- Copyright (C) 1999-2017 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-/* This goes away when the math-emulator is fixed */
-#undef TARGET_SUBTARGET_DEFAULT
-#define TARGET_SUBTARGET_DEFAULT \
- (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("__unix__"); \
- builtin_define ("__OpenBSD__"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=bsd"); \
- builtin_assert ("system=OpenBSD"); \
- } \
- while (0)
-
-/* Layout of source language data types. */
-
-/* This must agree with <machine/ansi.h> */
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 32
-
-/* Assembler format: overall framework. */
-
-#undef ASM_APP_ON
-#define ASM_APP_ON "#APP\n"
-
-#undef ASM_APP_OFF
-#define ASM_APP_OFF "#NO_APP\n"
-
-/* Stack & calling: aggregate returns. */
-
-/* Don't default to pcc-struct-return, because gcc is the only compiler, and
- we want to retain compatibility with older gcc versions. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-
-/* Assembler format: alignment output. */
-
-/* Kludgy test: when gas is upgraded, it will have p2align, and no problems
- with nops. */
-#ifndef HAVE_GAS_MAX_SKIP_P2ALIGN
-/* i386 OpenBSD still uses an older gas that doesn't insert nops by default
- when the .align directive demands to insert extra space in the text
- segment. */
-#undef ASM_OUTPUT_ALIGN
-#define ASM_OUTPUT_ALIGN(FILE,LOG) \
- if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG))
-#endif
-
-/* Stack & calling: profiling. */
-
-/* OpenBSD's profiler recovers all information from the stack pointer.
- The icky part is not here, but in machine/profile.h. */
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- fputs (flag_pic ? "\tcall mcount@PLT\n": "\tcall mcount\n", FILE);
-
-/* Assembler format: exception region output. */
-
-/* All configurations that don't use elf must be explicit about not using
- dwarf unwind information. */
-#define DWARF2_UNWIND_INFO 0
-
-#undef ASM_PREFERRED_EH_DATA_FORMAT
-
-#undef ASM_COMMENT_START
-#define ASM_COMMENT_START ";#"
-
-/* OpenBSD gas currently does not support quad, so do not use it. */
-#undef ASM_QUAD
-
-#define TARGET_HAVE_NAMED_SECTIONS false
diff --git a/gcc/config/i386/rtemself.h b/gcc/config/i386/rtemself.h
index e8eade28a5c..a68e8b30f62 100644
--- a/gcc/config/i386/rtemself.h
+++ b/gcc/config/i386/rtemself.h
@@ -2,21 +2,26 @@
Copyright (C) 1996-2017 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
/* Specify predefined symbols in preprocessor. */
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index e2db3b17f05..253ff5d5a7d 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -175,7 +175,7 @@
(V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI
(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
- (V4TI "TARGET_AVX512BW") (V2TI "TARGET_AVX") V1TI
+ (V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX") V1TI
(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF])
@@ -658,13 +658,21 @@
;; Mapping of vector modes to a vector mode of half size
(define_mode_attr ssehalfvecmode
- [(V64QI "V32QI") (V32HI "V16HI") (V16SI "V8SI") (V8DI "V4DI")
+ [(V64QI "V32QI") (V32HI "V16HI") (V16SI "V8SI") (V8DI "V4DI") (V4TI "V2TI")
(V32QI "V16QI") (V16HI "V8HI") (V8SI "V4SI") (V4DI "V2DI")
(V16QI "V8QI") (V8HI "V4HI") (V4SI "V2SI")
(V16SF "V8SF") (V8DF "V4DF")
(V8SF "V4SF") (V4DF "V2DF")
(V4SF "V2SF")])
+(define_mode_attr ssehalfvecmodelower
+ [(V64QI "v32qi") (V32HI "v16hi") (V16SI "v8si") (V8DI "v4di") (V4TI "v2ti")
+ (V32QI "v16qi") (V16HI "v8hi") (V8SI "v4si") (V4DI "v2di")
+ (V16QI "v8qi") (V8HI "v4hi") (V4SI "v2si")
+ (V16SF "v8sf") (V8DF "v4df")
+ (V8SF "v4sf") (V4DF "v2df")
+ (V4SF "v2sf")])
+
;; Mapping of vector modes ti packed single mode of the same size
(define_mode_attr ssePSmode
[(V16SI "V16SF") (V8DF "V16SF")
@@ -687,7 +695,18 @@
(V16SI "SI") (V8SI "SI") (V4SI "SI")
(V8DI "DI") (V4DI "DI") (V2DI "DI")
(V16SF "SF") (V8SF "SF") (V4SF "SF")
- (V8DF "DF") (V4DF "DF") (V2DF "DF")])
+ (V8DF "DF") (V4DF "DF") (V2DF "DF")
+ (V4TI "TI") (V2TI "TI")])
+
+;; Mapping of vector modes back to the scalar modes
+(define_mode_attr ssescalarmodelower
+ [(V64QI "qi") (V32QI "qi") (V16QI "qi")
+ (V32HI "hi") (V16HI "hi") (V8HI "hi")
+ (V16SI "si") (V8SI "si") (V4SI "si")
+ (V8DI "di") (V4DI "di") (V2DI "di")
+ (V16SF "sf") (V8SF "sf") (V4SF "sf")
+ (V8DF "df") (V4DF "df") (V2DF "df")
+ (V4TI "ti") (V2TI "ti")])
;; Mapping of vector modes to the 128bit modes
(define_mode_attr ssexmmmode
@@ -2355,7 +2374,7 @@
{
rtx tmp = gen_reg_rtx (V8DFmode);
ix86_expand_reduc (gen_addv8df3, tmp, operands[1]);
- emit_insn (gen_vec_extractv8df (operands[0], tmp, const0_rtx));
+ emit_insn (gen_vec_extractv8dfdf (operands[0], tmp, const0_rtx));
DONE;
})
@@ -2370,7 +2389,7 @@
emit_insn (gen_avx_haddv4df3 (tmp, operands[1], operands[1]));
emit_insn (gen_avx_vperm2f128v4df3 (tmp2, tmp, tmp, GEN_INT (1)));
emit_insn (gen_addv4df3 (vec_res, tmp, tmp2));
- emit_insn (gen_vec_extractv4df (operands[0], vec_res, const0_rtx));
+ emit_insn (gen_vec_extractv4dfdf (operands[0], vec_res, const0_rtx));
DONE;
})
@@ -2381,7 +2400,7 @@
{
rtx tmp = gen_reg_rtx (V2DFmode);
emit_insn (gen_sse3_haddv2df3 (tmp, operands[1], operands[1]));
- emit_insn (gen_vec_extractv2df (operands[0], tmp, const0_rtx));
+ emit_insn (gen_vec_extractv2dfdf (operands[0], tmp, const0_rtx));
DONE;
})
@@ -2392,7 +2411,7 @@
{
rtx tmp = gen_reg_rtx (V16SFmode);
ix86_expand_reduc (gen_addv16sf3, tmp, operands[1]);
- emit_insn (gen_vec_extractv16sf (operands[0], tmp, const0_rtx));
+ emit_insn (gen_vec_extractv16sfsf (operands[0], tmp, const0_rtx));
DONE;
})
@@ -2408,7 +2427,7 @@
emit_insn (gen_avx_haddv8sf3 (tmp2, tmp, tmp));
emit_insn (gen_avx_vperm2f128v8sf3 (tmp, tmp2, tmp2, GEN_INT (1)));
emit_insn (gen_addv8sf3 (vec_res, tmp, tmp2));
- emit_insn (gen_vec_extractv8sf (operands[0], vec_res, const0_rtx));
+ emit_insn (gen_vec_extractv8sfsf (operands[0], vec_res, const0_rtx));
DONE;
})
@@ -2426,7 +2445,7 @@
}
else
ix86_expand_reduc (gen_addv4sf3, vec_res, operands[1]);
- emit_insn (gen_vec_extractv4sf (operands[0], vec_res, const0_rtx));
+ emit_insn (gen_vec_extractv4sfsf (operands[0], vec_res, const0_rtx));
DONE;
})
@@ -2448,7 +2467,8 @@
{
rtx tmp = gen_reg_rtx (<MODE>mode);
ix86_expand_reduc (gen_<code><mode>3, tmp, operands[1]);
- emit_insn (gen_vec_extract<mode> (operands[0], tmp, const0_rtx));
+ emit_insn (gen_vec_extract<mode><ssescalarmodelower> (operands[0], tmp,
+ const0_rtx));
DONE;
})
@@ -2460,7 +2480,8 @@
{
rtx tmp = gen_reg_rtx (<MODE>mode);
ix86_expand_reduc (gen_<code><mode>3, tmp, operands[1]);
- emit_insn (gen_vec_extract<mode> (operands[0], tmp, const0_rtx));
+ emit_insn (gen_vec_extract<mode><ssescalarmodelower> (operands[0], tmp,
+ const0_rtx));
DONE;
})
@@ -2472,7 +2493,8 @@
{
rtx tmp = gen_reg_rtx (<MODE>mode);
ix86_expand_reduc (gen_<code><mode>3, tmp, operands[1]);
- emit_insn (gen_vec_extract<mode> (operands[0], tmp, const0_rtx));
+ emit_insn (gen_vec_extract<mode><ssescalarmodelower> (operands[0], tmp,
+ const0_rtx));
DONE;
})
@@ -2484,7 +2506,7 @@
{
rtx tmp = gen_reg_rtx (V8HImode);
ix86_expand_reduc (gen_uminv8hi3, tmp, operands[1]);
- emit_insn (gen_vec_extractv8hi (operands[0], tmp, const0_rtx));
+ emit_insn (gen_vec_extractv8hihi (operands[0], tmp, const0_rtx));
DONE;
})
@@ -6920,15 +6942,6 @@
(set_attr "prefix" "orig,maybe_evex,orig,maybe_evex")
(set_attr "mode" "V4SF,V4SF,V2SF,V2SF")])
-(define_expand "vec_init<mode>"
- [(match_operand:V_128 0 "register_operand")
- (match_operand 1)]
- "TARGET_SSE"
-{
- ix86_expand_vector_init (false, operands[0], operands[1]);
- DONE;
-})
-
;; Avoid combining registers from different units in a single alternative,
;; see comment above inline_secondary_memory_needed function in i386.c
(define_insn "vec_set<mode>_0"
@@ -7886,9 +7899,10 @@
(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
- (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF])
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF
+ (V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX")])
-(define_expand "vec_extract<mode>"
+(define_expand "vec_extract<mode><ssescalarmodelower>"
[(match_operand:<ssescalarmode> 0 "register_operand")
(match_operand:VEC_EXTRACT_MODE 1 "register_operand")
(match_operand 2 "const_int_operand")]
@@ -7899,6 +7913,19 @@
DONE;
})
+(define_expand "vec_extract<mode><ssehalfvecmodelower>"
+ [(match_operand:<ssehalfvecmode> 0 "nonimmediate_operand")
+ (match_operand:V_512 1 "register_operand")
+ (match_operand 2 "const_0_to_1_operand")]
+ "TARGET_AVX512F"
+{
+ if (INTVAL (operands[2]))
+ emit_insn (gen_vec_extract_hi_<mode> (operands[0], operands[1]));
+ else
+ emit_insn (gen_vec_extract_lo_<mode> (operands[0], operands[1]));
+ DONE;
+})
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel double-precision floating point element swizzling
@@ -13734,6 +13761,50 @@
operands[1] = adjust_address (operands[1], <ssescalarmode>mode, offs);
})
+(define_insn "*vec_extractv2ti"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=xm,vm")
+ (vec_select:TI
+ (match_operand:V2TI 1 "register_operand" "x,v")
+ (parallel
+ [(match_operand:SI 2 "const_0_to_1_operand")])))]
+ "TARGET_AVX"
+ "@
+ vextract%~128\t{%2, %1, %0|%0, %1, %2}
+ vextracti32x4\t{%2, %g1, %0|%0, %g1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex,evex")
+ (set_attr "mode" "OI")])
+
+(define_insn "*vec_extractv4ti"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=vm")
+ (vec_select:TI
+ (match_operand:V4TI 1 "register_operand" "v")
+ (parallel
+ [(match_operand:SI 2 "const_0_to_3_operand")])))]
+ "TARGET_AVX512F"
+ "vextracti32x4\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_mode_iterator VEXTRACTI128_MODE
+ [(V4TI "TARGET_AVX512F") V2TI])
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand")
+ (vec_select:TI
+ (match_operand:VEXTRACTI128_MODE 1 "register_operand")
+ (parallel [(const_int 0)])))]
+ "TARGET_AVX
+ && reload_completed
+ && (TARGET_AVX512VL || !EXT_REX_SSE_REG_P (operands[1]))"
+ [(set (match_dup 0) (match_dup 1))]
+ "operands[1] = gen_lowpart (TImode, operands[1]);")
+
;; Turn SImode or DImode extraction from arbitrary SSE/AVX/AVX512F
;; vector modes into vec_extract*.
(define_split
@@ -16656,7 +16727,7 @@
for (i = 0; i < <ssescalarnum>; i++)
RTVEC_ELT (vs, i) = op2;
- emit_insn (gen_vec_init<mode> (reg, par));
+ emit_insn (gen_vec_init<mode><ssescalarmodelower> (reg, par));
emit_insn (gen_xop_vrotl<mode>3 (operands[0], operands[1], reg));
DONE;
}
@@ -16688,7 +16759,7 @@
for (i = 0; i < <ssescalarnum>; i++)
RTVEC_ELT (vs, i) = op2;
- emit_insn (gen_vec_init<mode> (reg, par));
+ emit_insn (gen_vec_init<mode><ssescalarmodelower> (reg, par));
emit_insn (gen_neg<mode>2 (neg, reg));
emit_insn (gen_xop_vrotl<mode>3 (operands[0], operands[1], neg));
DONE;
@@ -16982,7 +17053,7 @@
XVECEXP (par, 0, i) = operands[2];
tmp = gen_reg_rtx (V16QImode);
- emit_insn (gen_vec_initv16qi (tmp, par));
+ emit_insn (gen_vec_initv16qiqi (tmp, par));
if (negate)
emit_insn (gen_negv16qi2 (tmp, tmp));
@@ -17018,7 +17089,7 @@
for (i = 0; i < 2; i++)
XVECEXP (par, 0, i) = operands[2];
- emit_insn (gen_vec_initv2di (reg, par));
+ emit_insn (gen_vec_initv2didi (reg, par));
if (negate)
emit_insn (gen_negv2di2 (reg, reg));
@@ -18738,19 +18809,40 @@
<ssehalfvecmode>mode);
})
-(define_expand "vec_init<mode>"
- [(match_operand:V_256 0 "register_operand")
+;; Modes handled by vec_init expanders.
+(define_mode_iterator VEC_INIT_MODE
+ [(V64QI "TARGET_AVX512F") (V32QI "TARGET_AVX") V16QI
+ (V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI
+ (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
+ (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
+ (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")
+ (V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX")])
+
+;; Likewise, but for initialization from half sized vectors.
+;; Thus, these are all VEC_INIT_MODE modes except V2??.
+(define_mode_iterator VEC_INIT_HALF_MODE
+ [(V64QI "TARGET_AVX512F") (V32QI "TARGET_AVX") V16QI
+ (V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI
+ (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
+ (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX")
+ (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX")
+ (V4TI "TARGET_AVX512F")])
+
+(define_expand "vec_init<mode><ssescalarmodelower>"
+ [(match_operand:VEC_INIT_MODE 0 "register_operand")
(match_operand 1)]
- "TARGET_AVX"
+ "TARGET_SSE"
{
ix86_expand_vector_init (false, operands[0], operands[1]);
DONE;
})
-(define_expand "vec_init<mode>"
- [(match_operand:VF48_I1248 0 "register_operand")
+(define_expand "vec_init<mode><ssehalfvecmodelower>"
+ [(match_operand:VEC_INIT_HALF_MODE 0 "register_operand")
(match_operand 1)]
- "TARGET_AVX512F"
+ "TARGET_SSE"
{
ix86_expand_vector_init (false, operands[0], operands[1]);
DONE;
diff --git a/gcc/config/i386/t-openbsd b/gcc/config/i386/t-openbsd
deleted file mode 100644
index 4f8ff657a93..00000000000
--- a/gcc/config/i386/t-openbsd
+++ /dev/null
@@ -1,4 +0,0 @@
-# gdb gets confused if pic code is linked with non pic
-# We cope by building variants of libgcc.
-MULTILIB_OPTIONS = fpic
-MULTILIB_MATCHES=fpic=fPIC
diff --git a/gcc/config/i386/winnt-cxx.c b/gcc/config/i386/winnt-cxx.c
index d6bf0afbab0..a3569fb1b56 100644
--- a/gcc/config/i386/winnt-cxx.c
+++ b/gcc/config/i386/winnt-cxx.c
@@ -114,14 +114,11 @@ i386_pe_adjust_class_at_definition (tree t)
decl_attributes (&ti_decl, na, 0);
}
- /* Check static VAR_DECL's. */
+ /* Check FUNCTION_DECL's and static VAR_DECL's. */
for (member = TYPE_FIELDS (t); member; member = DECL_CHAIN (member))
if (TREE_CODE (member) == VAR_DECL)
maybe_add_dllexport (member);
-
- /* Check FUNCTION_DECL's. */
- for (member = TYPE_METHODS (t); member; member = DECL_CHAIN (member))
- if (TREE_CODE (member) == FUNCTION_DECL)
+ else if (TREE_CODE (member) == FUNCTION_DECL)
{
tree thunk;
maybe_add_dllexport (member);
@@ -130,9 +127,11 @@ i386_pe_adjust_class_at_definition (tree t)
for (thunk = DECL_THUNKS (member); thunk;
thunk = TREE_CHAIN (thunk))
maybe_add_dllexport (thunk);
- }
+ }
+
/* Check vtables */
- for (member = CLASSTYPE_VTABLES (t); member; member = DECL_CHAIN (member))
+ for (member = CLASSTYPE_VTABLES (t);
+ member; member = DECL_CHAIN (member))
if (TREE_CODE (member) == VAR_DECL)
maybe_add_dllexport (member);
}
@@ -147,14 +146,11 @@ i386_pe_adjust_class_at_definition (tree t)
That is just right since out-of class declarations can only be a
definition. */
- /* Check static VAR_DECL's. */
+ /* Check FUNCTION_DECL's and static VAR_DECL's. */
for (member = TYPE_FIELDS (t); member; member = DECL_CHAIN (member))
if (TREE_CODE (member) == VAR_DECL)
maybe_add_dllimport (member);
-
- /* Check FUNCTION_DECL's. */
- for (member = TYPE_METHODS (t); member; member = DECL_CHAIN (member))
- if (TREE_CODE (member) == FUNCTION_DECL)
+ else if (TREE_CODE (member) == FUNCTION_DECL)
{
tree thunk;
maybe_add_dllimport (member);
@@ -163,10 +159,11 @@ i386_pe_adjust_class_at_definition (tree t)
for (thunk = DECL_THUNKS (member); thunk;
thunk = DECL_CHAIN (thunk))
maybe_add_dllimport (thunk);
- }
+ }
/* Check vtables */
- for (member = CLASSTYPE_VTABLES (t); member; member = DECL_CHAIN (member))
+ for (member = CLASSTYPE_VTABLES (t);
+ member; member = DECL_CHAIN (member))
if (TREE_CODE (member) == VAR_DECL)
maybe_add_dllimport (member);
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index 8272c7fddc1..405f74a7597 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "memmodel.h"
#include "tm_p.h"
#include "stringpool.h"
+#include "attribs.h"
#include "emit-rtl.h"
#include "cgraph.h"
#include "lto-streamer.h"