[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:
parent
a1b81a0320
commit
cc48a87f9d
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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))
|
||||
])]
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -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)")))
|
||||
|
Loading…
x
Reference in New Issue
Block a user