diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 78 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 111 |
4 files changed, 109 insertions, 95 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ada9be7..6f559bc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2019-10-10 Andreas Krebbel <krebbel@linux.ibm.com> + + 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_<mode>", "split_stack_cond_call") + ("split_stack_cond_call_<mode>"): Remove. + ("@split_stack_call<mode>", "@split_stack_cond_call<mode>"): 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 <msebor@redhat.com> PR tree-optimization/90879 diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index ae70b2f..f760f15 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 062cbd8..8241bd5 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 e4516f6..01e5cf9 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_<mode>" - [(set (pc) (label_ref (match_operand 1 "" ""))) +(define_insn "@split_stack_call<mode>" + [(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_<mode>" +(define_insn "@split_stack_cond_call<mode>" [(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)] "" |