Hello! Attached patch prevents red-zone with -fPIC for leaf functions on i686. The idea is to mark when set_got is expanded as a call to a pc thunk, and use this flag to prevent red-zone in the current function.
Please note that using red-zone with i686 violates all known ABIs, but some future ABI can trip on this limitation. The failure mode is quite tricky, so IMO it warrants a couple of lines as a safety net. The testcase is not suitable for the testsuite (it uses -mred-zone for i686 target), but I have checked that the testcase works OK when compiled with the patched compiler even when -mred-zone is used together with -fPIC. Jakub, HJ - what do you think? 2016-03-01 Uros Bizjak <ubiz...@gmail.com> PR target/70064 * config/i386/i386.h (machine_function): Add pc_thunk_call_expanded flag. (ix86_pc_thunk_call_expanded): New define. * config/i386/i386.md (set_got, set_got_labelled): New expanders. (*set_got): Rename insn pattern from set_got. (*set_got_labelled): Rename inst pattern from set_got_labelled. * config/i386/i386.c (ix86_compute_frame_layout): Use ix86_pc_thunk_call_expanded to prevent red-zone. The patch is bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Uros.
Index: i386.c =================================================================== --- i386.c (revision 234014) +++ i386.c (working copy) @@ -11524,6 +11524,7 @@ ix86_compute_frame_layout (struct ix86_frame *fram if (ix86_using_red_zone () && crtl->sp_is_unchanging && crtl->is_leaf + && !ix86_pc_thunk_call_expanded && !ix86_current_function_calls_tls_descriptor) { frame->red_zone_size = to_allocate; Index: i386.h =================================================================== --- i386.h (revision 234014) +++ i386.h (working copy) @@ -2494,6 +2494,10 @@ struct GTY(()) machine_function { expander to determine the style used. */ BOOL_BITFIELD use_fast_prologue_epilogue : 1; + /* Nonzero if the current function calls pc thunk and + must not use the red zone. */ + BOOL_BITFIELD pc_thunk_call_expanded : 1; + /* If true, the current function needs the default PIC register, not an alternate register (on x86) and must not use the red zone (on x86_64), even if it's a leaf function. We don't want the @@ -2533,6 +2537,7 @@ struct GTY(()) machine_function { #define ix86_varargs_fpr_size (cfun->machine->varargs_fpr_size) #define ix86_optimize_mode_switching (cfun->machine->optimize_mode_switching) #define ix86_current_function_needs_cld (cfun->machine->needs_cld) +#define ix86_pc_thunk_call_expanded (cfun->machine->pc_thunk_call_expanded) #define ix86_tls_descriptor_calls_expanded_in_cfun \ (cfun->machine->tls_descriptor_call_expanded_p) /* Since tls_descriptor_call_expanded is not cleared, even if all TLS Index: i386.md =================================================================== --- i386.md (revision 234014) +++ i386.md (working copy) @@ -12470,7 +12470,18 @@ "" "ix86_expand_prologue (); DONE;") -(define_insn "set_got" +(define_expand "set_got" + [(parallel + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) + (clobber (reg:CC FLAGS_REG))])] + "!TARGET_64BIT" +{ + if (flag_pic && !TARGET_VXWORKS_RTP) + ix86_pc_thunk_call_expanded = true; +}) + +(define_insn "*set_got" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) (clobber (reg:CC FLAGS_REG))] @@ -12479,7 +12490,19 @@ [(set_attr "type" "multi") (set_attr "length" "12")]) -(define_insn "set_got_labelled" +(define_expand "set_got_labelled" + [(parallel + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(label_ref (match_operand 1))] + UNSPEC_SET_GOT)) + (clobber (reg:CC FLAGS_REG))])] + "!TARGET_64BIT" +{ + if (flag_pic && !TARGET_VXWORKS_RTP) + ix86_pc_thunk_call_expanded = true; +}) + +(define_insn "*set_got_labelled" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(label_ref (match_operand 1))] UNSPEC_SET_GOT))