+2015-01-16 Chung-Ju Wu <jasonwucj@gmail.com>
+
+ * config/nds32/nds32-protos.h (nds32_can_use_return_insn): New.
+ * config/nds32/nds32.md (unspec_volatile_func_return): Remove.
+ (return_internal): New.
+ (return): Define this named pattern.
+ (simple_return): Define this named pattern.
+ * config/nds32/nds32.c (nds32_expand_epilogue): Emit return_internal
+ pattern instead of unspec_volatile_func_return.
+ (nds32_expand_epilogue_v3pop): Likewise.
+ (nds32_can_use_return_insn): New function.
+
2015-01-16 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/constants.md (UNSPEC_VOLATILE_POP25_RETURN): New.
RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
}
- /* Generate return instruction by using
- unspec_volatile_func_return pattern.
- Make sure this instruction is after gen_blockage().
- NOTE that $lp will become 'live'
- after this instruction has been emitted. */
- emit_insn (gen_unspec_volatile_func_return ());
+ /* Generate return instruction by using 'return_internal' pattern.
+ Make sure this instruction is after gen_blockage(). */
+ emit_jump_insn (gen_return_internal ());
return;
}
RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
}
- /* Generate return instruction by using
- unspec_volatile_func_return pattern. */
- emit_insn (gen_unspec_volatile_func_return ());
+ /* Generate return instruction. */
+ emit_jump_insn (gen_return_internal ());
}
/* Function for v3push prologue. */
epilogue code fragment BUT 'ret' instruction. */
if (cfun->machine->naked_p)
{
- /* Generate return instruction by using
- unspec_volatile_func_return pattern.
- Make sure this instruction is after gen_blockage().
- NOTE that $lp will become 'live'
- after this instruction has been emitted. */
- emit_insn (gen_unspec_volatile_func_return ());
+ /* Generate return instruction by using 'return_internal' pattern.
+ Make sure this instruction is after gen_blockage(). */
+ emit_jump_insn (gen_return_internal ());
return;
}
emit_jump_insn (gen_pop25return ());
}
+/* Return nonzero if this function is known to have a null epilogue.
+ This allows the optimizer to omit jumps to jumps if no stack
+ was created. */
+int
+nds32_can_use_return_insn (void)
+{
+ /* Prior to reloading, we can't tell how many registers must be saved.
+ Thus we can not determine whether this function has null epilogue. */
+ if (!reload_completed)
+ return 0;
+
+ /* If no stack was created, two conditions must be satisfied:
+ 1. This is a naked function.
+ So there is no callee-saved, local size, or outgoing size.
+ 2. This is NOT a variadic function.
+ So there is no pushing arguement registers into the stack. */
+ return (cfun->machine->naked_p && (cfun->machine->va_args_size == 0));
+}
+
/* ------------------------------------------------------------------------ */
/* Function to test 333-form for load/store instructions.
;; ----------------------------------------------------------------------------
-;; unspec operation patterns
+;; Return operation patterns
;; ----------------------------------------------------------------------------
-;; In nds32 target, the 'ret5' instuction is actually 'jr5 $lp'.
-;; This pattern is designed to distinguish function return
-;; from general indirect_jump pattern so that we can directly
-;; generate 'ret5' for readability.
+;; Use this pattern to expand a return instruction
+;; with simple_return rtx if no epilogue is required.
+(define_expand "return"
+ [(simple_return)]
+ "nds32_can_use_return_insn ()"
+ ""
+)
-(define_insn "unspec_volatile_func_return"
- [(set (pc)
- (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_FUNC_RETURN))]
+;; This pattern is expanded only by the shrink-wrapping optimization
+;; on paths where the function prologue has not been executed.
+(define_expand "simple_return"
+ [(simple_return)]
+ ""
+ ""
+)
+
+(define_insn "return_internal"
+ [(simple_return)]
""
{
if (TARGET_16_BIT)
else
return "ret";
}
- [(set_attr "type" "misc")
+ [(set_attr "type" "branch")
(set_attr "enabled" "1")
(set (attr "length")
(if_then_else (match_test "TARGET_16_BIT")