diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 010e7fc..e3fff38 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -25,12 +25,13 @@ extern enum unwind_info_type arm_except_unwind_info (struct gcc_options *); extern int use_return_insn (int, rtx); +extern bool use_simple_return_p (void); extern enum reg_class arm_regno_class (int); extern void arm_load_pic_register (unsigned long); extern int arm_volatile_func (void); extern void arm_expand_prologue (void); extern void arm_expand_epilogue (bool); -extern void thumb2_expand_return (void); +extern void thumb2_expand_return (bool); extern const char *arm_strip_name_encoding (const char *); extern void arm_asm_output_labelref (FILE *, const char *); extern void thumb2_asm_output_opcode (FILE *); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 866385c..995cdf1 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -2393,6 +2393,18 @@ use_return_insn (int iscond, rtx sibling) return 1; } +/* Return TRUE if we should try to use a simple_return insn, i.e. perform + shrink-wrapping if possible. This is the case if we need to emit a + prologue, which we can test by looking at the offsets. */ +bool +use_simple_return_p (void) +{ + arm_stack_offsets *offsets; + + offsets = arm_get_frame_offsets (); + return offsets->outgoing_args != 0; +} + /* Return TRUE if int I is a valid immediate ARM constant. */ int @@ -22539,7 +22551,7 @@ thumb1_expand_prologue (void) all we really need to check here is if single register is to be returned, or multiple register return. */ void -thumb2_expand_return (void) +thumb2_expand_return (bool simple_return) { int i, num_regs; unsigned long saved_regs_mask; @@ -22552,7 +22564,7 @@ thumb2_expand_return (void) if (saved_regs_mask & (1 << i)) num_regs++; - if (saved_regs_mask) + if (!simple_return && saved_regs_mask) { if (num_regs == 1) { diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index b45fea0..c75e8f2 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -8514,10 +8514,10 @@ }" ) -(define_insn "*sibcall_insn" +(define_insn "*sibcall_insn" [(call (mem:SI (match_operand:SI 0 "" "X")) (match_operand 1 "" "")) - (return) + (returns) (use (match_operand 2 "" ""))] "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF" "* @@ -8526,11 +8526,11 @@ [(set_attr "type" "call")] ) -(define_insn "*sibcall_value_insn" +(define_insn "*sibcall_value_insn" [(set (match_operand 0 "" "") (call (mem:SI (match_operand:SI 1 "" "X")) (match_operand 2 "" ""))) - (return) + (returns) (use (match_operand 3 "" ""))] "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF" "* @@ -8539,17 +8539,17 @@ [(set_attr "type" "call")] ) -(define_expand "return" - [(return)] +(define_expand "return" + [(returns)] "(TARGET_ARM || (TARGET_THUMB2 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL && !IS_STACKALIGN (arm_current_func_type ()))) - && USE_RETURN_INSN (FALSE)" + " " { if (TARGET_THUMB2) { - thumb2_expand_return (); + thumb2_expand_return (); DONE; } } @@ -8574,13 +8574,13 @@ (set_attr "predicable" "yes")] ) -(define_insn "*cond_return" +(define_insn "*cond_return" [(set (pc) (if_then_else (match_operator 0 "arm_comparison_operator" [(match_operand 1 "cc_register" "") (const_int 0)]) - (return) + (returns) (pc)))] - "TARGET_ARM && USE_RETURN_INSN (TRUE)" + "TARGET_ARM " "* { if (arm_ccfsm_state == 2) @@ -8588,20 +8588,20 @@ arm_ccfsm_state += 2; return \"\"; } - return output_return_instruction (operands[0], true, false, false); + return output_return_instruction (operands[0], true, false, ); }" [(set_attr "conds" "use") (set_attr "length" "12") (set_attr "type" "load1")] ) -(define_insn "*cond_return_inverted" +(define_insn "*cond_return_inverted" [(set (pc) (if_then_else (match_operator 0 "arm_comparison_operator" [(match_operand 1 "cc_register" "") (const_int 0)]) (pc) - (return)))] - "TARGET_ARM && USE_RETURN_INSN (TRUE)" + (returns)))] + "TARGET_ARM " "* { if (arm_ccfsm_state == 2) @@ -8609,7 +8609,7 @@ arm_ccfsm_state += 2; return \"\"; } - return output_return_instruction (operands[0], true, true, false); + return output_return_instruction (operands[0], true, true, ); }" [(set_attr "conds" "use") (set_attr "length" "12") @@ -8617,7 +8617,7 @@ ) (define_insn "*arm_simple_return" - [(simple_return)] + [(returns)] "TARGET_ARM" "* { diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index def8d9f..0092ee7 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -449,3 +449,12 @@ ;; Assembler mnemonics for signedness of widening operations. (define_code_attr US [(sign_extend "s") (zero_extend "u")]) + +;; Both kinds of return insn. +(define_code_iterator returns [return simple_return]) +(define_code_attr return_str [(return "") (simple_return "simple_")]) +(define_code_attr return_simple_p [(return "false") (simple_return "true")]) +(define_code_attr return_cond_false [(return " && USE_RETURN_INSN (FALSE)") + (simple_return " && use_simple_return_p ()")]) +(define_code_attr return_cond_true [(return " && USE_RETURN_INSN (TRUE)") + (simple_return " && use_simple_return_p ()")]) diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md index 57d1539..2f2746e 100644 --- a/gcc/config/arm/thumb2.md +++ b/gcc/config/arm/thumb2.md @@ -635,8 +635,8 @@ (set_attr "length" "20")] ) -(define_insn "*thumb2_return" - [(simple_return)] +(define_insn "*thumb2_return" + [(returns)] "TARGET_THUMB2" "* return output_return_instruction (const_true_rtx, true, false, true);" [(set_attr "type" "branch")