From d6529176b21a9e7402da40032a25247e69f91124 Mon Sep 17 00:00:00 2001 From: Chung-Ju Wu Date: Fri, 16 Jan 2015 06:45:09 +0000 Subject: [PATCH] [NDS32] Have sibling calls optmization to be performed on nds32 target. gcc/ * config/nds32/nds32-protos.h (nds32_expand_epilogue): Change prototype. (nds32_expand_epilogue_v3pop): Likewise. * config/nds32/nds32.md (sibcall): Define this for sibling call optimization. (sibcall_register): Likewise. (sibcall_immediate): Likewise. (sibcall_value): Likewise. (sibcall_value_register): Likewise. (sibcall_value_immediate): Likewise. (sibcall_epilogue): Likewise. (epilogue): Pass false to indicate this is not a sibcall epilogue. * config/nds32/nds32.c (nds32_expand_epilogue): Consider sibcall case. (nds32_expand_epilogue_v3pop): Likewise. From-SVN: r219712 --- gcc/ChangeLog | 17 +++++ gcc/config/nds32/nds32-protos.h | 4 +- gcc/config/nds32/nds32.c | 13 ++-- gcc/config/nds32/nds32.md | 114 +++++++++++++++++++++++++++++++- 4 files changed, 139 insertions(+), 9 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5d0313dffdf..09a0c986430 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2015-01-16 Chung-Ju Wu + + * config/nds32/nds32-protos.h (nds32_expand_epilogue): Change + prototype. + (nds32_expand_epilogue_v3pop): Likewise. + * config/nds32/nds32.md (sibcall): Define this for sibling call + optimization. + (sibcall_register): Likewise. + (sibcall_immediate): Likewise. + (sibcall_value): Likewise. + (sibcall_value_register): Likewise. + (sibcall_value_immediate): Likewise. + (sibcall_epilogue): Likewise. + (epilogue): Pass false to indicate this is not a sibcall epilogue. + * config/nds32/nds32.c (nds32_expand_epilogue): Consider sibcall case. + (nds32_expand_epilogue_v3pop): Likewise. + 2015-01-16 Chung-Ju Wu * config/nds32/nds32-protos.h (nds32_can_use_return_insn): New. diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h index 91f8d9ab0b2..620d897535a 100644 --- a/gcc/config/nds32/nds32-protos.h +++ b/gcc/config/nds32/nds32-protos.h @@ -58,9 +58,9 @@ extern void nds32_init_cumulative_args (CUMULATIVE_ARGS *, /* -- Function Entry and Exit. */ extern void nds32_expand_prologue (void); -extern void nds32_expand_epilogue (void); +extern void nds32_expand_epilogue (bool); extern void nds32_expand_prologue_v3push (void); -extern void nds32_expand_epilogue_v3pop (void); +extern void nds32_expand_epilogue_v3pop (bool); /* ------------------------------------------------------------------------ */ diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index 538495fb298..1845bc21812 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -3044,7 +3044,7 @@ nds32_expand_prologue (void) /* Function for normal multiple pop epilogue. */ void -nds32_expand_epilogue (void) +nds32_expand_epilogue (bool sibcall_p) { int sp_adjust; int en4_const; @@ -3089,7 +3089,8 @@ nds32_expand_epilogue (void) /* Generate return instruction by using 'return_internal' pattern. Make sure this instruction is after gen_blockage(). */ - emit_jump_insn (gen_return_internal ()); + if (!sibcall_p) + emit_jump_insn (gen_return_internal ()); return; } @@ -3194,7 +3195,8 @@ nds32_expand_epilogue (void) } /* Generate return instruction. */ - emit_jump_insn (gen_return_internal ()); + if (!sibcall_p) + emit_jump_insn (gen_return_internal ()); } /* Function for v3push prologue. */ @@ -3327,7 +3329,7 @@ nds32_expand_prologue_v3push (void) /* Function for v3pop epilogue. */ void -nds32_expand_epilogue_v3pop (void) +nds32_expand_epilogue_v3pop (bool sibcall_p) { int sp_adjust; @@ -3348,7 +3350,8 @@ nds32_expand_epilogue_v3pop (void) { /* Generate return instruction by using 'return_internal' pattern. Make sure this instruction is after gen_blockage(). */ - emit_jump_insn (gen_return_internal ()); + if (!sibcall_p) + emit_jump_insn (gen_return_internal ()); return; } diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md index 1cf620288c7..64823a13a47 100644 --- a/gcc/config/nds32/nds32.md +++ b/gcc/config/nds32/nds32.md @@ -1988,6 +1988,102 @@ create_template: (const_int 4)))]) +;; ---------------------------------------------------------------------------- + +;; The sibcall patterns. + +;; sibcall +;; sibcall_register +;; sibcall_immediate + +(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")) + (match_operand 1)) + (clobber (reg:SI TA_REGNUM)) + (return)])] + "" +{ + if (TARGET_CMODEL_LARGE) + return "b\t%0"; + else + return "j\t%0"; +} + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (match_test "TARGET_CMODEL_LARGE") + (const_int 12) + (const_int 4)))]) + +;; sibcall_value +;; sibcall_value_register +;; sibcall_value_immediate + +(define_expand "sibcall_value" + [(parallel [(set (match_operand 0) + (call (match_operand 1 "memory_operand" "") + (const_int 0))) + (clobber (reg:SI TA_REGNUM)) + (return)])] + "" + "" +) + +(define_insn "*sibcall_value_register" + [(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")) + (match_operand 2))) + (clobber (reg:SI TA_REGNUM)) + (return)])] + "" +{ + if (TARGET_CMODEL_LARGE) + return "b\t%1"; + else + return "j\t%1"; +} + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (match_test "TARGET_CMODEL_LARGE") + (const_int 12) + (const_int 4)))]) + + +;; ---------------------------------------------------------------------------- + ;; prologue and epilogue. (define_expand "prologue" [(const_int 0)] @@ -2014,9 +2110,23 @@ create_template: if (TARGET_V3PUSH && !nds32_isr_function_p (current_function_decl) && (cfun->machine->va_args_size == 0)) - nds32_expand_epilogue_v3pop (); + nds32_expand_epilogue_v3pop (false); + else + nds32_expand_epilogue (false); + DONE; +}) + +(define_expand "sibcall_epilogue" [(const_int 0)] + "" +{ + /* Pass true to indicate that this is sibcall epilogue and + exit from a function without the final branch back to the + calling function. */ + if (TARGET_V3PUSH && !nds32_isr_function_p (current_function_decl)) + nds32_expand_epilogue_v3pop (true); else - nds32_expand_epilogue (); + nds32_expand_epilogue (true); + DONE; }) -- 2.30.2