diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
index c456c40..c6b7884 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 e24d0dc..0cd3550 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -3099,12 +3099,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;
     }
 
@@ -3208,9 +3205,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.  */
@@ -3362,12 +3358,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;
     }
 
@@ -3466,6 +3459,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 a09650f..c9f5995 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")
-- 
1.9.0

