[NDS32] Have sibling calls optmization to be performed on nds32 target.
authorChung-Ju Wu <jasonwucj@gmail.com>
Fri, 16 Jan 2015 06:45:09 +0000 (06:45 +0000)
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>
Fri, 16 Jan 2015 06:45:09 +0000 (06:45 +0000)
gcc/
* 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.

From-SVN: r219712

gcc/ChangeLog
gcc/config/nds32/nds32-protos.h
gcc/config/nds32/nds32.c
gcc/config/nds32/nds32.md

index 5d0313dffdfd2bfc700445fbf00e618b328f718e..09a0c98643033b2b4fca943da7ad13e6a8f8ea13 100644 (file)
@@ -1,3 +1,20 @@
+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.
index 91f8d9ab0b26341e360b01e2149b474a15a0b0e0..620d897535a084b96392c7676f8c5bf3b15c5bde 100644 (file)
@@ -58,9 +58,9 @@ extern void nds32_init_cumulative_args (CUMULATIVE_ARGS *,
 /* -- Function Entry and Exit.  */
 
 extern void nds32_expand_prologue (void);
-extern void nds32_expand_epilogue (void);
+extern void nds32_expand_epilogue (bool);
 extern void nds32_expand_prologue_v3push (void);
-extern void nds32_expand_epilogue_v3pop (void);
+extern void nds32_expand_epilogue_v3pop (bool);
 
 /* ------------------------------------------------------------------------ */
 
index 538495fb298b5f362df0008773e331deadc06d1e..1845bc218122822dda3e53d93f5f16711f1648a1 100644 (file)
@@ -3044,7 +3044,7 @@ nds32_expand_prologue (void)
 
 /* Function for normal multiple pop epilogue.  */
 void
-nds32_expand_epilogue (void)
+nds32_expand_epilogue (bool sibcall_p)
 {
   int sp_adjust;
   int en4_const;
@@ -3089,7 +3089,8 @@ nds32_expand_epilogue (void)
 
       /* 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;
     }
 
@@ -3194,7 +3195,8 @@ nds32_expand_epilogue (void)
     }
 
   /* Generate return instruction.  */
-  emit_jump_insn (gen_return_internal ());
+  if (!sibcall_p)
+    emit_jump_insn (gen_return_internal ());
 }
 
 /* Function for v3push prologue.  */
@@ -3327,7 +3329,7 @@ nds32_expand_prologue_v3push (void)
 
 /* Function for v3pop epilogue.  */
 void
-nds32_expand_epilogue_v3pop (void)
+nds32_expand_epilogue_v3pop (bool sibcall_p)
 {
   int sp_adjust;
 
@@ -3348,7 +3350,8 @@ nds32_expand_epilogue_v3pop (void)
     {
       /* 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;
     }
 
index 1cf620288c780af10123642976223688ebbd4176..64823a13a47f307cb23f32f36b9996d4151f2e54 100644 (file)
@@ -1988,6 +1988,102 @@ create_template:
                      (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)]
@@ -2014,9 +2110,23 @@ create_template:
   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;
 })