aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-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
4 files changed, 62 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1d998d0..5d0313d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,17 @@
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.
* config/nds32/nds32.md (pop25return): New.
* config/nds32/nds32.c (nds32_expand_epilogue_v3pop): Emit
diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
index 328e061..91f8d9a 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 d38ea89..538495f 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 01faa68..1cf6202 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")