summaryrefslogtreecommitdiff
path: root/gcc/config/nds32
diff options
context:
space:
mode:
authorjasonwucj <jasonwucj@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-16 06:45:09 +0000
committerjasonwucj <jasonwucj@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-16 06:45:09 +0000
commit7ea565c0eeaece4d662c2120d0b113fcf5c640cc (patch)
tree9ad5242156362721d37d48216c9c8867faa73af6 /gcc/config/nds32
parentc29277862679d425598253f5d9c1edfb4ec577f3 (diff)
downloadgcc-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.h4
-rw-r--r--gcc/config/nds32/nds32.c13
-rw-r--r--gcc/config/nds32/nds32.md114
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;
})