From f46706733954c2868af5e91687931538600b2a92 Mon Sep 17 00:00:00 2001 From: Chung-Ju Wu Date: Fri, 6 Apr 2018 18:27:51 +0000 Subject: [PATCH] [NDS32] Refine call and return patterns. gcc/ * config/nds32/nds32-md-auxiliary.c (nds32_output_return, nds32_output_call, nds32_symbol_binds_local_p): New functions. * config/nds32/nds32-protos.h (nds32_output_call, nds32_output_return): Declare. * config/nds32/nds32.md: Refine all the call and return patterns. Co-Authored-By: Kito Cheng From-SVN: r259186 --- gcc/ChangeLog | 9 ++ gcc/config/nds32/nds32-md-auxiliary.c | 92 +++++++++++++++ gcc/config/nds32/nds32-protos.h | 4 + gcc/config/nds32/nds32.md | 159 +++++++++++++++++--------- 4 files changed, 211 insertions(+), 53 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c82d2bc57f8..a261a45986d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2018-04-06 Chung-Ju Wu + Kito Cheng + + * config/nds32/nds32-md-auxiliary.c (nds32_output_return, + nds32_output_call, nds32_symbol_binds_local_p): New functions. + * config/nds32/nds32-protos.h (nds32_output_call, + nds32_output_return): Declare. + * config/nds32/nds32.md: Refine all the call and return patterns. + 2018-04-06 Jakub Jelinek PR debug/85252 diff --git a/gcc/config/nds32/nds32-md-auxiliary.c b/gcc/config/nds32/nds32-md-auxiliary.c index dca1c9f959b..01ce38b5980 100644 --- a/gcc/config/nds32/nds32-md-auxiliary.c +++ b/gcc/config/nds32/nds32-md-auxiliary.c @@ -1938,6 +1938,48 @@ nds32_output_stack_pop (rtx par_rtx ATTRIBUTE_UNUSED) return ""; } +/* Function to output return operation. */ +const char * +nds32_output_return (void) +{ + /* A string pattern for output_asm_insn(). */ + char pattern[100]; + /* The operands array which will be used in output_asm_insn(). */ + rtx operands[2]; + /* For stack v3pop: + operands[0]: Re + operands[1]: imm8u */ + int re_callee_saved = cfun->machine->callee_saved_last_gpr_regno; + int sp_adjust; + + /* Set operands[0]. */ + operands[0] = gen_rtx_REG (SImode, re_callee_saved); + + /* Check if we can generate 'pop25 Re,imm8u', + otherwise, generate 'pop25 Re,0'. + We have to consider alloca issue as well. + If the function does call alloca(), the stack pointer is not fixed. + In that case, we cannot use 'pop25 Re,imm8u' directly. + We have to caculate stack pointer from frame pointer + and then use 'pop25 Re,0'. */ + sp_adjust = cfun->machine->local_size + + cfun->machine->out_args_size + + cfun->machine->callee_saved_area_gpr_padding_bytes + + cfun->machine->callee_saved_fpr_regs_size; + if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) + && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust) + && !cfun->calls_alloca) + operands[1] = GEN_INT (sp_adjust); + else + operands[1] = GEN_INT (0); + + /* Create assembly code pattern. */ + snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1"); + /* We use output_asm_insn() to output assembly code by ourself. */ + output_asm_insn (pattern, operands); + return ""; +} + /* Function to generate PC relative jump table. Refer to nds32.md for more details. @@ -2681,6 +2723,56 @@ nds32_output_cbranchsi4_greater_less_zero (rtx_insn *insn, rtx *operands) return ""; } +/* Return true if SYMBOL_REF X binds locally. */ + +static bool +nds32_symbol_binds_local_p (const_rtx x) +{ + return (SYMBOL_REF_DECL (x) + ? targetm.binds_local_p (SYMBOL_REF_DECL (x)) + : SYMBOL_REF_LOCAL_P (x)); +} + +const char * +nds32_output_call (rtx insn, rtx *operands, rtx symbol, const char *long_call, + const char *call, bool align_p) +{ + char pattern[100]; + bool noreturn_p; + + if (GET_CODE (symbol) == CONST) + { + symbol= XEXP (symbol, 0); + + if (GET_CODE (symbol) == PLUS) + symbol = XEXP (symbol, 0); + } + + gcc_assert (GET_CODE (symbol) == SYMBOL_REF + || REG_P (symbol)); + + if (nds32_long_call_p (symbol)) + strcpy (pattern, long_call); + else + strcpy (pattern, call); + + if (align_p) + strcat (pattern, "\n\t.align 2"); + + noreturn_p = find_reg_note (insn, REG_NORETURN, NULL_RTX) != NULL_RTX; + + if (noreturn_p) + { + if (TARGET_16_BIT) + strcat (pattern, "\n\tnop16"); + else + strcat (pattern, "\n\tnop"); + } + + output_asm_insn (pattern, operands); + return ""; +} + /* Spilt a doubleword instrucion to two single word instructions. */ void nds32_spilt_doubleword (rtx *operands, bool load_p) diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h index aebec3b0b34..0b460dadec9 100644 --- a/gcc/config/nds32/nds32-protos.h +++ b/gcc/config/nds32/nds32-protos.h @@ -172,11 +172,15 @@ extern const char *nds32_output_cbranchsi4_equality_reg_or_const_int (rtx_insn * rtx *); extern const char *nds32_output_cbranchsi4_greater_less_zero (rtx_insn *, rtx *); +extern const char *nds32_output_call (rtx, rtx *, rtx, + const char *, const char *, bool); + /* Auxiliary functions to output stack push/pop instruction. */ extern const char *nds32_output_stack_push (rtx); extern const char *nds32_output_stack_pop (rtx); +extern const char *nds32_output_return (void); /* Auxiliary functions to split double word RTX pattern. */ diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md index cb42d04773a..67d0d5f0755 100644 --- a/gcc/config/nds32/nds32.md +++ b/gcc/config/nds32/nds32.md @@ -1419,36 +1419,41 @@ "" ) -(define_insn "*call_register" - [(parallel [(call (mem (match_operand:SI 0 "register_operand" "r, r")) - (match_operand 1)) - (clobber (reg:SI LP_REGNUM)) - (clobber (reg:SI TA_REGNUM))])] - "" - "@ - jral5\t%0 - jral\t%0" - [(set_attr "type" "branch,branch") - (set_attr "length" " 2, 4")]) - -(define_insn "*call_immediate" - [(parallel [(call (mem (match_operand:SI 0 "immediate_operand" "i")) +(define_insn "call_internal" + [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i")) (match_operand 1)) (clobber (reg:SI LP_REGNUM)) (clobber (reg:SI TA_REGNUM))])] "" { - if (TARGET_CMODEL_LARGE) - return "bal\t%0"; - else - return "jal\t%0"; + switch (which_alternative) + { + case 0: + if (TARGET_16_BIT) + return "jral5\t%0"; + else + return "jral\t%0"; + case 1: + return nds32_output_call (insn, operands, operands[0], + "bal\t%0", "jal\t%0", false); + default: + gcc_unreachable (); + } } - [(set_attr "type" "branch") - (set (attr "length") - (if_then_else (match_test "TARGET_CMODEL_LARGE") - (const_int 12) - (const_int 4)))]) - + [(set_attr "enabled" "yes") + (set_attr "type" "branch") + (set_attr_alternative "length" + [ + ;; Alternative 0 + (if_then_else (match_test "TARGET_16_BIT") + (const_int 2) + (const_int 4)) + ;; Alternative 1 + (if_then_else (match_test "nds32_long_call_p (operands[0])") + (const_int 12) + (const_int 4)) + ])] +) ;; Subroutine call instruction returning a value. ;; operands[0]: It is the hard regiser in which the value is returned. @@ -1462,42 +1467,71 @@ (match_operand 2))) (clobber (reg:SI LP_REGNUM)) (clobber (reg:SI TA_REGNUM))])] - "" - "" -) + "") -(define_insn "*call_value_register" +(define_insn "call_value_internal" [(parallel [(set (match_operand 0) - (call (mem (match_operand:SI 1 "register_operand" "r, r")) + (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i")) (match_operand 2))) (clobber (reg:SI LP_REGNUM)) (clobber (reg:SI TA_REGNUM))])] "" - "@ - jral5\t%1 - jral\t%1" - [(set_attr "type" "branch,branch") - (set_attr "length" " 2, 4")]) +{ + switch (which_alternative) + { + case 0: + if (TARGET_16_BIT) + return "jral5\t%1"; + else + return "jral\t%1"; + case 1: + return nds32_output_call (insn, operands, operands[1], + "bal\t%1", "jal\t%1", false); + default: + gcc_unreachable (); + } +} + [(set_attr "enabled" "yes") + (set_attr "type" "branch") + (set_attr_alternative "length" + [ + ;; Alternative 0 + (if_then_else (match_test "TARGET_16_BIT") + (const_int 2) + (const_int 4)) + ;; Alternative 1 + (if_then_else (match_test "nds32_long_call_p (operands[1])") + (const_int 12) + (const_int 4)) + ])] +) -(define_insn "*call_value_immediate" - [(parallel [(set (match_operand 0) - (call (mem (match_operand:SI 1 "immediate_operand" "i")) - (match_operand 2))) - (clobber (reg:SI LP_REGNUM)) - (clobber (reg:SI TA_REGNUM))])] +;; Call subroutine returning any type. + +(define_expand "untyped_call" + [(parallel [(call (match_operand 0 "" "") + (const_int 0)) + (match_operand 1 "" "") + (match_operand 2 "" "")])] "" { - if (TARGET_CMODEL_LARGE) - return "bal\t%1"; - else - return "jal\t%1"; -} - [(set_attr "type" "branch") - (set (attr "length") - (if_then_else (match_test "TARGET_CMODEL_LARGE") - (const_int 12) - (const_int 4)))]) + int i; + emit_call_insn (gen_call (operands[0], const0_rtx)); + + for (i = 0; i < XVECLEN (operands[2], 0); i++) + { + rtx set = XVECEXP (operands[2], 0, i); + emit_move_insn (SET_DEST (set), SET_SRC (set)); + } + + /* The optimizer does not know that the call sets the function value + registers we stored in the result block. We avoid problems by + claiming that all hard registers are used and clobbered at this + point. */ + emit_insn (gen_blockage ()); + DONE; +}) ;; ---------------------------------------------------------------------------- @@ -1715,10 +1749,18 @@ ;; Use this pattern to expand a return instruction ;; with simple_return rtx if no epilogue is required. (define_expand "return" - [(simple_return)] + [(parallel [(return) + (clobber (reg:SI FP_REGNUM))])] "nds32_can_use_return_insn ()" - "" -) +{ + /* Emit as the simple return. */ + if (cfun->machine->naked_p + && (cfun->machine->va_args_size == 0)) + { + emit_jump_insn (gen_return_internal ()); + DONE; + } +}) ;; This pattern is expanded only by the shrink-wrapping optimization ;; on paths where the function prologue has not been executed. @@ -1728,6 +1770,17 @@ "" ) +(define_insn "*nds32_return" + [(parallel [(return) + (clobber (reg:SI FP_REGNUM))])] + "" +{ + return nds32_output_return (); +} + [(set_attr "type" "branch") + (set_attr "enabled" "yes") + (set_attr "length" "4")]) + (define_insn "return_internal" [(simple_return)] "" -- 2.30.2