From 051fb43f810d34a683a5112112757abf6998325a Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Thu, 10 Oct 2019 07:56:25 +0000 Subject: [PATCH] S/390: PR91035 Fix call to __morestack For the call to __morestack we use a special ABI in the S/390 back-end which requires us to emit a parameter block to the .rodata section. It contains the label whereto __morestack needs to return. The parameter block needs to be explicit in RTL since we also need to take the address of it loaded into r1 in order to pass its address to __morestack. In order to express correctly what __morestack does its RTX also contained the return label. Hence we had the return label to occur twice in the insn stream. This is problematic when it comes to redirecting edges. The correlation between these two occurrences of the label cannot be expressed so when doing a redirect only the label in the jump RTX gets modified while the parameter block label stays as is. The patch avoids having two instancs of the label by merging the parameter block generation and the __morestack call RTX into one. By doing this I could also get rid of the unspec which was required for the parameter block generation so far. gcc/ChangeLog: 2019-10-10 Andreas Krebbel PR target/91035 * config/s390/s390-protos.h (s390_output_split_stack_data): Add prototype. * config/s390/s390.md (UNSPECV_SPLIT_STACK_DATA): Remove. ("split_stack_data", "split_stack_call") ("split_stack_call_", "split_stack_cond_call") ("split_stack_cond_call_"): Remove. ("@split_stack_call", "@split_stack_cond_call"): New insn definition. * config/s390/s390.c (s390_output_split_stack_data): New function. (s390_expand_split_stack_prologue): Use the merged expander. From-SVN: r276790 --- gcc/ChangeLog | 14 +++++ gcc/config/s390/s390-protos.h | 1 + gcc/config/s390/s390.c | 78 ++++++++++++++++++------ gcc/config/s390/s390.md | 111 +++++++++++----------------------- 4 files changed, 109 insertions(+), 95 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ada9be7cc1f..6f559bc9b14 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2019-10-10 Andreas Krebbel + + PR target/91035 + * config/s390/s390-protos.h (s390_output_split_stack_data): Add + prototype. + * config/s390/s390.md (UNSPECV_SPLIT_STACK_DATA): Remove. + ("split_stack_data", "split_stack_call") + ("split_stack_call_", "split_stack_cond_call") + ("split_stack_cond_call_"): Remove. + ("@split_stack_call", "@split_stack_cond_call"): New + insn definition. + * config/s390/s390.c (s390_output_split_stack_data): New function. + (s390_expand_split_stack_prologue): Use the merged expander. + 2019-10-09 Martin Sebor PR tree-optimization/90879 diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index ae70b2fee18..f760f152932 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -146,6 +146,7 @@ extern int s390_branch_condition_mask (rtx); extern int s390_compare_and_branch_condition_mask (rtx); extern bool s390_extzv_shift_ok (int, int, unsigned HOST_WIDE_INT); extern void s390_asm_output_function_label (FILE *, const char *, tree); +extern void s390_output_split_stack_data (rtx, rtx, rtx, rtx); enum s390_indirect_branch_type { diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 062cbd8099d..8241bd5bbf8 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -11600,6 +11600,44 @@ static GTY(()) rtx morestack_ref; #define SPLIT_STACK_AVAILABLE 1024 +/* Emit the parmblock for __morestack into .rodata section. It + consists of 3 pointer size entries: + - frame size + - size of stack arguments + - offset between parm block and __morestack return label */ + +void +s390_output_split_stack_data (rtx parm_block, rtx call_done, + rtx frame_size, rtx args_size) +{ + rtx ops[] = { parm_block, call_done }; + + switch_to_section (targetm.asm_out.function_rodata_section + (current_function_decl)); + + if (TARGET_64BIT) + output_asm_insn (".align\t8", NULL); + else + output_asm_insn (".align\t4", NULL); + + (*targetm.asm_out.internal_label) (asm_out_file, "L", + CODE_LABEL_NUMBER (parm_block)); + if (TARGET_64BIT) + { + output_asm_insn (".quad\t%0", &frame_size); + output_asm_insn (".quad\t%0", &args_size); + output_asm_insn (".quad\t%1-%0", ops); + } + else + { + output_asm_insn (".long\t%0", &frame_size); + output_asm_insn (".long\t%0", &args_size); + output_asm_insn (".long\t%1-%0", ops); + } + + switch_to_section (current_function_section ()); +} + /* Emit -fsplit-stack prologue, which goes before the regular function prologue. */ @@ -11677,16 +11715,8 @@ s390_expand_split_stack_prologue (void) call_done = gen_label_rtx (); parm_base = gen_label_rtx (); - - /* Emit the parameter block. */ - tmp = gen_split_stack_data (parm_base, call_done, - GEN_INT (frame_size), - GEN_INT (args_size)); - insn = emit_insn (tmp); - add_reg_note (insn, REG_LABEL_OPERAND, call_done); - LABEL_NUSES (call_done)++; - add_reg_note (insn, REG_LABEL_OPERAND, parm_base); LABEL_NUSES (parm_base)++; + LABEL_NUSES (call_done)++; /* %r1 = litbase. */ insn = emit_move_insn (r1, gen_rtx_LABEL_REF (VOIDmode, parm_base)); @@ -11696,15 +11726,29 @@ s390_expand_split_stack_prologue (void) /* Now, we need to call __morestack. It has very special calling conventions: it preserves param/return/static chain registers for calling main function body, and looks for its own parameters at %r1. */ + if (cc != NULL) + tmp = gen_split_stack_cond_call (Pmode, + morestack_ref, + parm_base, + call_done, + GEN_INT (frame_size), + GEN_INT (args_size), + cc); + else + tmp = gen_split_stack_call (Pmode, + morestack_ref, + parm_base, + call_done, + GEN_INT (frame_size), + GEN_INT (args_size)); + + insn = emit_jump_insn (tmp); + JUMP_LABEL (insn) = call_done; + add_reg_note (insn, REG_LABEL_OPERAND, parm_base); + add_reg_note (insn, REG_LABEL_OPERAND, call_done); if (cc != NULL) { - tmp = gen_split_stack_cond_call (morestack_ref, cc, call_done); - - insn = emit_jump_insn (tmp); - JUMP_LABEL (insn) = call_done; - LABEL_NUSES (call_done)++; - /* Mark the jump as very unlikely to be taken. */ add_reg_br_prob_note (insn, profile_probability::very_unlikely ()); @@ -11720,10 +11764,6 @@ s390_expand_split_stack_prologue (void) } else { - tmp = gen_split_stack_call (morestack_ref, call_done); - insn = emit_jump_insn (tmp); - JUMP_LABEL (insn) = call_done; - LABEL_NUSES (call_done)++; emit_barrier (); } diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index e4516f6c378..01e5cf920cd 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -298,7 +298,6 @@ ; Split stack support UNSPECV_SPLIT_STACK_CALL - UNSPECV_SPLIT_STACK_DATA UNSPECV_OSC_BREAK ]) @@ -12000,99 +11999,59 @@ DONE; }) -;; __morestack parameter block for split stack prologue. Parameters are: -;; parameter block label, label to be called by __morestack, frame size, -;; stack parameter size. +;; Call to __morestack used by the split stack support -(define_insn "split_stack_data" - [(unspec_volatile [(match_operand 0 "" "X") - (match_operand 1 "" "X") - (match_operand 2 "const_int_operand" "X") - (match_operand 3 "const_int_operand" "X")] - UNSPECV_SPLIT_STACK_DATA)] - "" -{ - switch_to_section (targetm.asm_out.function_rodata_section - (current_function_decl)); +; The insn has 3 parts: +; 1. A jump to the call done label. The jump will be done as part of +; __morestack and will not be explicitly emitted to the insn stream. +; 2. The call of __morestack including a use for r1 which is supposed to +; point to the parameter block for __morestack. +; 3. 3 USES whose values together with the call done label will be +; used to emit the parameter block to the .rodata section. This +; needs to be tied into the same insn as 1. since the call done +; label is emitted also as part of the parm block. In order to +; allow the edge to the BB with the call done label to be +; redirected both need to make use of the same label_ref. - if (TARGET_64BIT) - output_asm_insn (".align\t8", operands); - else - output_asm_insn (".align\t4", operands); - (*targetm.asm_out.internal_label) (asm_out_file, "L", - CODE_LABEL_NUMBER (operands[0])); - if (TARGET_64BIT) - { - output_asm_insn (".quad\t%2", operands); - output_asm_insn (".quad\t%3", operands); - output_asm_insn (".quad\t%1-%0", operands); - } - else - { - output_asm_insn (".long\t%2", operands); - output_asm_insn (".long\t%3", operands); - output_asm_insn (".long\t%1-%0", operands); - } - - switch_to_section (current_function_section ()); - return ""; -} - [(set_attr "length" "0")]) - - -;; A jg with minimal fuss for use in split stack prologue. - -(define_expand "split_stack_call" - [(match_operand 0 "bras_sym_operand" "X") - (match_operand 1 "" "")] - "" -{ - if (TARGET_64BIT) - emit_jump_insn (gen_split_stack_call_di (operands[0], operands[1])); - else - emit_jump_insn (gen_split_stack_call_si (operands[0], operands[1])); - DONE; -}) - -(define_insn "split_stack_call_" - [(set (pc) (label_ref (match_operand 1 "" ""))) +(define_insn "@split_stack_call" + [(set (pc) (label_ref (match_operand 2 "" ""))) ; call done label (set (reg:P 1) (unspec_volatile [(match_operand 0 "bras_sym_operand" "X") (reg:P 1)] - UNSPECV_SPLIT_STACK_CALL))] + UNSPECV_SPLIT_STACK_CALL)) + (use (label_ref (match_operand 1 "" "X"))) ; parm block label + (use (match_operand 3 "const_int_operand" "X")) ; frame size + (use (match_operand 4 "const_int_operand" "X"))] ; arg size "" - "jg\t%0" +{ + s390_output_split_stack_data (operands[1], operands[2], operands[3], operands[4]); + return "jg\t%0"; +} [(set_attr "op_type" "RIL") (set_attr "type" "branch")]) -;; Also a conditional one. - -(define_expand "split_stack_cond_call" - [(match_operand 0 "bras_sym_operand" "X") - (match_operand 1 "" "") - (match_operand 2 "" "")] - "" -{ - if (TARGET_64BIT) - emit_jump_insn (gen_split_stack_cond_call_di (operands[0], operands[1], operands[2])); - else - emit_jump_insn (gen_split_stack_cond_call_si (operands[0], operands[1], operands[2])); - DONE; -}) +; As above but with a conditional jump -(define_insn "split_stack_cond_call_" +(define_insn "@split_stack_cond_call" [(set (pc) (if_then_else - (match_operand 1 "" "") - (label_ref (match_operand 2 "" "")) + (match_operand 5 "" "") ; condition + (label_ref (match_operand 2 "" "")) ; call done label (pc))) (set (reg:P 1) (unspec_volatile [(match_operand 0 "bras_sym_operand" "X") (reg:P 1)] - UNSPECV_SPLIT_STACK_CALL))] + UNSPECV_SPLIT_STACK_CALL)) + (use (label_ref (match_operand 1 "" "X"))) ; parm block label + (use (match_operand 3 "const_int_operand" "X")) ; frame size + (use (match_operand 4 "const_int_operand" "X"))] ; arg size "" - "jg%C1\t%0" +{ + s390_output_split_stack_data (operands[1], operands[2], operands[3], operands[4]); + return "jg%C5\t%0"; +} [(set_attr "op_type" "RIL") (set_attr "type" "branch")]) + (define_insn "osc_break" [(unspec_volatile [(const_int 0)] UNSPECV_OSC_BREAK)] "" -- 2.30.2