diff options
author | jasonwucj <jasonwucj@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-01-16 06:45:09 +0000 |
---|---|---|
committer | jasonwucj <jasonwucj@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-01-16 06:45:09 +0000 |
commit | 7ea565c0eeaece4d662c2120d0b113fcf5c640cc (patch) | |
tree | 9ad5242156362721d37d48216c9c8867faa73af6 /gcc/config/nds32 | |
parent | c29277862679d425598253f5d9c1edfb4ec577f3 (diff) | |
download | gcc-7ea565c0eeaece4d662c2120d0b113fcf5c640cc.tar.gz |
[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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219712 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/nds32')
-rw-r--r-- | gcc/config/nds32/nds32-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/nds32/nds32.c | 13 | ||||
-rw-r--r-- | gcc/config/nds32/nds32.md | 114 |
3 files changed, 122 insertions, 9 deletions
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; }) |