summaryrefslogtreecommitdiff
path: root/gcc/config/nds32
diff options
context:
space:
mode:
authorjasonwucj <jasonwucj@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-16 06:20:22 +0000
committerjasonwucj <jasonwucj@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-16 06:20:22 +0000
commitc29277862679d425598253f5d9c1edfb4ec577f3 (patch)
treef85dd78875ae4f283fa1ab54e809870a6a7ec11a /gcc/config/nds32
parent405249c13a86eb86b3be3b0b3d87df863d239a4e (diff)
downloadgcc-c29277862679d425598253f5d9c1edfb4ec577f3.tar.gz
[NDS32] Have shirnk-wrapping optimization to be performed on nds32 target.
gcc/ * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219711 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.c42
-rw-r--r--gcc/config/nds32/nds32.md28
3 files changed, 50 insertions, 24 deletions
diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
index 328e0619ead..91f8d9ab0b2 100644
--- a/gcc/config/nds32/nds32-protos.h
+++ b/gcc/config/nds32/nds32-protos.h
@@ -120,6 +120,10 @@ extern const char *nds32_output_32bit_load_s (rtx *, int);
extern const char *nds32_output_stack_push (rtx);
extern const char *nds32_output_stack_pop (rtx);
+/* Auxiliary functions to check using return with null epilogue. */
+
+extern int nds32_can_use_return_insn (void);
+
/* Auxiliary functions to decide output alignment or not. */
extern int nds32_target_alignment (rtx);
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index d38ea896d79..538495fb298 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -3087,12 +3087,9 @@ nds32_expand_epilogue (void)
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;
}
@@ -3196,9 +3193,8 @@ nds32_expand_epilogue (void)
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. */
@@ -3350,12 +3346,9 @@ nds32_expand_epilogue_v3pop (void)
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;
}
@@ -3454,6 +3447,25 @@ nds32_expand_epilogue_v3pop (void)
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.
diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md
index 01faa681cad..1cf620288c7 100644
--- a/gcc/config/nds32/nds32.md
+++ b/gcc/config/nds32/nds32.md
@@ -2090,17 +2090,27 @@ create_template:
;; ----------------------------------------------------------------------------
-;; 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)
@@ -2108,7 +2118,7 @@ create_template:
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")