[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 <kito.cheng@gmail.com>

From-SVN: r259186
This commit is contained in:
Chung-Ju Wu 2018-04-06 18:27:51 +00:00 committed by Chung-Ju Wu
parent 96975b1159
commit f467067339
4 changed files with 211 additions and 53 deletions

View file

@ -1,3 +1,12 @@
2018-04-06 Chung-Ju Wu <jasonwucj@gmail.com>
Kito Cheng <kito.cheng@gmail.com>
* 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 <jakub@redhat.com>
PR debug/85252

View file

@ -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)

View file

@ -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. */

View file

@ -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)]
""