[NDS32] Refine implementation of sibcall patterns.

gcc/
	* config/nds32/nds32-md-auxiliary.c (nds32_long_call_p): New function.
	* config/nds32/nds32-protos.h (nds32_long_call_p): Declare.
	* config/nds32/nds32.c (nds32_function_ok_for_sibcall): New function.
	(TARGET_FUNCTION_OK_FOR_SIBCALL): Define.
	* config/nds32/nds32.md (sibcall_internal): New.
	(sibcall_register): Remove.
	(sibcall_immediate): Remove.
	(sibcall_value_internal): New.
	(sibcall_value_register): Remove.
	(sibcall_value_immediate): Remove.
	* config/nds32/predicates.md (nds32_general_register_operand): New.
	(nds32_call_address_operand): New.

Co-Authored-By: Kito Cheng <kito.cheng@gmail.com>

From-SVN: r259065
This commit is contained in:
Chung-Ju Wu 2018-04-04 00:56:16 +00:00 committed by Chung-Ju Wu
parent a1b81a0320
commit cc48a87f9d
6 changed files with 130 additions and 57 deletions

View File

@ -1,3 +1,19 @@
2018-04-04 Chung-Ju Wu <jasonwucj@gmail.com>
Kito Cheng <kito.cheng@gmail.com>
* config/nds32/nds32-md-auxiliary.c (nds32_long_call_p): New function.
* config/nds32/nds32-protos.h (nds32_long_call_p): Declare.
* config/nds32/nds32.c (nds32_function_ok_for_sibcall): New function.
(TARGET_FUNCTION_OK_FOR_SIBCALL): Define.
* config/nds32/nds32.md (sibcall_internal): New.
(sibcall_register): Remove.
(sibcall_immediate): Remove.
(sibcall_value_internal): New.
(sibcall_value_register): Remove.
(sibcall_value_immediate): Remove.
* config/nds32/predicates.md (nds32_general_register_operand): New.
(nds32_call_address_operand): New.
2018-04-03 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/85167

View File

@ -1145,3 +1145,10 @@ nds32_expand_unaligned_store (rtx *operands, enum machine_mode mode)
}
}
}
/* Return true X is need use long call. */
bool
nds32_long_call_p (rtx symbol)
{
return TARGET_CMODEL_LARGE;
}

View File

@ -116,6 +116,9 @@ extern bool nds32_symbol_load_store_p (rtx_insn *);
extern const char *nds32_output_casesi_pc_relative (rtx *);
extern const char *nds32_output_casesi (rtx *);
/* Auxiliary functions to identify long-call symbol. */
extern bool nds32_long_call_p (rtx);
/* Auxiliary functions to identify 16 bit addresing mode. */
extern enum nds32_16bit_address_type nds32_mem_format (rtx);

View File

@ -1762,6 +1762,26 @@ nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
/* -- Permitting tail calls. */
/* Return true if it is ok to do sibling call optimization. */
static bool
nds32_function_ok_for_sibcall (tree decl,
tree exp ATTRIBUTE_UNUSED)
{
/* The DECL is NULL if it is an indirect call. */
/* 1. Do not apply sibling call if -mv3push is enabled,
because pop25 instruction also represents return behavior.
2. If this function is a variadic function, do not apply sibling call
because the stack layout may be a mess.
3. We don't want to apply sibling call optimization for indirect
sibcall because the pop behavior in epilogue may pollute the
content of caller-saved regsiter when the register is used for
indirect sibcall. */
return (!TARGET_V3PUSH
&& (cfun->machine->va_args_size == 0)
&& decl);
}
/* Determine whether we need to enable warning for function return check. */
static bool
nds32_warn_func_return (tree decl)
@ -3764,6 +3784,9 @@ nds32_target_alignment (rtx_insn *label)
/* -- Permitting tail calls. */
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL nds32_function_ok_for_sibcall
#undef TARGET_WARN_FUNC_RETURN
#define TARGET_WARN_FUNC_RETURN nds32_warn_func_return

View File

@ -1996,50 +1996,55 @@ create_template:
;; The sibcall patterns.
;; sibcall
;; sibcall_register
;; sibcall_immediate
;; sibcall_internal
(define_expand "sibcall"
[(parallel [(call (match_operand 0 "memory_operand" "")
(const_int 0))
(clobber (reg:SI TA_REGNUM))
(return)])]
""
""
)
"")
(define_insn "*sibcall_register"
[(parallel [(call (mem (match_operand:SI 0 "register_operand" "r, r"))
(match_operand 1))
(clobber (reg:SI TA_REGNUM))
(return)])]
""
"@
jr5\t%0
jr\t%0"
[(set_attr "type" "branch,branch")
(set_attr "length" " 2, 4")])
(define_insn "*sibcall_immediate"
[(parallel [(call (mem (match_operand:SI 0 "immediate_operand" "i"))
(define_insn "sibcall_internal"
[(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i"))
(match_operand 1))
(clobber (reg:SI TA_REGNUM))
(return)])]
""
{
if (TARGET_CMODEL_LARGE)
return "b\t%0";
else
return "j\t%0";
switch (which_alternative)
{
case 0:
if (TARGET_16_BIT)
return "jr5\t%0";
else
return "jr\t%0";
case 1:
if (nds32_long_call_p (operands[0]))
return "b\t%0";
else
return "j\t%0";
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" "1")
(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))
])]
)
;; sibcall_value
;; sibcall_value_register
;; sibcall_value_internal
;; sibcall_value_immediate
(define_expand "sibcall_value"
@ -2048,42 +2053,46 @@ create_template:
(const_int 0)))
(clobber (reg:SI TA_REGNUM))
(return)])]
""
""
)
"")
(define_insn "*sibcall_value_register"
(define_insn "sibcall_value_internal"
[(parallel [(set (match_operand 0)
(call (mem (match_operand:SI 1 "register_operand" "r, r"))
(match_operand 2)))
(clobber (reg:SI TA_REGNUM))
(return)])]
""
"@
jr5\t%1
jr\t%1"
[(set_attr "type" "branch,branch")
(set_attr "length" " 2, 4")])
(define_insn "*sibcall_value_immediate"
[(parallel [(set (match_operand 0)
(call (mem (match_operand:SI 1 "immediate_operand" "i"))
(call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i"))
(match_operand 2)))
(clobber (reg:SI TA_REGNUM))
(return)])]
""
{
if (TARGET_CMODEL_LARGE)
return "b\t%1";
else
return "j\t%1";
switch (which_alternative)
{
case 0:
if (TARGET_16_BIT)
return "jr5\t%1";
else
return "jr\t%1";
case 1:
if (nds32_long_call_p (operands[1]))
return "b\t%1";
else
return "j\t%1";
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" "1")
(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))
])]
)
;; ----------------------------------------------------------------------------

View File

@ -57,6 +57,21 @@
return true;
})
(define_predicate "nds32_general_register_operand"
(match_code "reg,subreg")
{
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
return (REG_P (op)
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO (op) <= NDS32_LAST_GPR_REGNUM));
})
(define_predicate "nds32_call_address_operand"
(ior (match_operand 0 "nds32_symbolic_operand")
(match_operand 0 "nds32_general_register_operand")))
(define_predicate "nds32_lmw_smw_base_operand"
(and (match_code "mem")
(match_test "nds32_valid_smw_lwm_base_p (op)")))