+2015-01-16 Chung-Ju Wu <jasonwucj@gmail.com>
+
+ * 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 <jasonwucj@gmail.com>
* config/nds32/nds32-protos.h (nds32_can_use_return_insn): New.
/* Function for normal multiple pop epilogue. */
void
-nds32_expand_epilogue (void)
+nds32_expand_epilogue (bool sibcall_p)
{
int sp_adjust;
int en4_const;
/* 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;
}
}
/* Generate return instruction. */
- emit_jump_insn (gen_return_internal ());
+ if (!sibcall_p)
+ emit_jump_insn (gen_return_internal ());
}
/* Function for v3push prologue. */
/* Function for v3pop epilogue. */
void
-nds32_expand_epilogue_v3pop (void)
+nds32_expand_epilogue_v3pop (bool sibcall_p)
{
int sp_adjust;
{
/* 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;
}
(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)]
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;
})