... and use address spaces to load boundary value from TLS block. The patch removes special handling for boundary value location.
2017-08-10 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386-protos.h (ix86_split_stack_boundary): New prototype. * config/i386/i386.c (ix86_split_stack_boundary): New function. (ix86_xpand_split_stack_prologue): Call ix86_split_stack_boundary. (ix86_legitimate_address_p) <case UNSPEC_STACK_CHECK>: Remove. (i386_asm_output_addr_const_extra) <case UNSPEC_STACK_CHECK>: Ditto. (optput_pic_addr_const): Remove UNSPEC_STACK_CHECK handling. * config/i386/i386.md (unspec): Remove UNSPEC_STACK_CHECK. (split_stack_space_check): Call ix86_split_stack_boundary. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32} with all default languages plus go. Committed to mainline SVN. Uros.
Index: config/i386/i386-protos.h =================================================================== --- config/i386/i386-protos.h (revision 251027) +++ config/i386/i386-protos.h (working copy) @@ -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_boundary (void); + #ifdef TREE_CODE extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); #endif /* TREE_CODE */ Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 251027) +++ config/i386/i386.c (working copy) @@ -15784,6 +15784,28 @@ static GTY(()) rtx split_stack_fn; static GTY(()) rtx split_stack_fn_large; +/* */ + +rtx +ix86_split_stack_boundary (void) +{ + int offset; + addr_space_t as = DEFAULT_TLS_SEG_REG; + rtx r; + +#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. */ @@ -15815,10 +15837,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_boundary (); + if (allocate < SPLIT_STACK_AVAILABLE) current = stack_pointer_rtx; else @@ -16891,10 +16911,6 @@ ix86_legitimate_address_p (machine_mode, rtx addr, case UNSPEC_DTPOFF: break; - case UNSPEC_STACK_CHECK: - gcc_assert (flag_split_stack); - break; - default: /* Invalid address unspec. */ return false; @@ -17984,17 +18000,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); @@ -19690,22 +19699,6 @@ i386_asm_output_addr_const_extra (FILE *file, rtx 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; } Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 251027) +++ config/i386/i386.md (working copy) @@ -86,7 +86,6 @@ UNSPEC_SET_RIP UNSPEC_SET_GOT_OFFSET UNSPEC_MEMORY_BLOCKAGE - UNSPEC_STACK_CHECK UNSPEC_PROBE_STACK ;; TLS support @@ -12630,21 +12629,18 @@ [(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_boundary (); + ix86_expand_branch (GEU, reg, operands[2], operands[1]); + DONE; })