[NDS32] Refine implementation of sibcall patterns.
authorChung-Ju Wu <jasonwucj@gmail.com>
Wed, 4 Apr 2018 00:56:16 +0000 (00:56 +0000)
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>
Wed, 4 Apr 2018 00:56:16 +0000 (00:56 +0000)
gcc/
* config/nds32/nds32-md-auxiliary.c (nds32_long_call_p): New function.
* config/nds32/nds32-protos.h (nds32_long_call_p): Declare.
* config/nds32/nds32.c (nds32_function_ok_for_sibcall): New function.
(TARGET_FUNCTION_OK_FOR_SIBCALL): Define.
* config/nds32/nds32.md (sibcall_internal): New.
(sibcall_register): Remove.
(sibcall_immediate): Remove.
(sibcall_value_internal): New.
(sibcall_value_register): Remove.
(sibcall_value_immediate): Remove.
* config/nds32/predicates.md (nds32_general_register_operand): New.
(nds32_call_address_operand): New.

Co-Authored-By: Kito Cheng <kito.cheng@gmail.com>
From-SVN: r259065

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

index cd64aa4..2b3369b 100644 (file)
@@ -1,3 +1,19 @@
+2018-04-04  Chung-Ju Wu  <jasonwucj@gmail.com>
+           Kito Cheng  <kito.cheng@gmail.com>
+
+       * config/nds32/nds32-md-auxiliary.c (nds32_long_call_p): New function.
+       * config/nds32/nds32-protos.h (nds32_long_call_p): Declare.
+       * config/nds32/nds32.c (nds32_function_ok_for_sibcall): New function.
+       (TARGET_FUNCTION_OK_FOR_SIBCALL): Define.
+       * config/nds32/nds32.md (sibcall_internal): New.
+       (sibcall_register): Remove.
+       (sibcall_immediate): Remove.
+       (sibcall_value_internal): New.
+       (sibcall_value_register): Remove.
+       (sibcall_value_immediate): Remove.
+       * config/nds32/predicates.md (nds32_general_register_operand): New.
+       (nds32_call_address_operand): New.
+
 2018-04-03  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/85167
index 755945f..5311b69 100644 (file)
@@ -1145,3 +1145,10 @@ nds32_expand_unaligned_store (rtx *operands, enum machine_mode mode)
        }
     }
 }
+
+/* Return true X is need use long call.  */
+bool
+nds32_long_call_p (rtx symbol)
+{
+  return TARGET_CMODEL_LARGE;
+}
index 1387cca..6a3281b 100644 (file)
@@ -116,6 +116,9 @@ extern bool nds32_symbol_load_store_p (rtx_insn *);
 extern const char *nds32_output_casesi_pc_relative (rtx *);
 extern const char *nds32_output_casesi (rtx *);
 
+/* Auxiliary functions to identify long-call symbol.  */
+extern bool nds32_long_call_p (rtx);
+
 /* Auxiliary functions to identify 16 bit addresing mode.  */
 
 extern enum nds32_16bit_address_type nds32_mem_format (rtx);
index 06a59be..829e097 100644 (file)
@@ -1762,6 +1762,26 @@ nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
 
 /* -- Permitting tail calls.  */
 
+/* Return true if it is ok to do sibling call optimization.  */
+static bool
+nds32_function_ok_for_sibcall (tree decl,
+                              tree exp ATTRIBUTE_UNUSED)
+{
+  /* The DECL is NULL if it is an indirect call.  */
+
+  /* 1. Do not apply sibling call if -mv3push is enabled,
+       because pop25 instruction also represents return behavior.
+     2. If this function is a variadic function, do not apply sibling call
+       because the stack layout may be a mess.
+     3. We don't want to apply sibling call optimization for indirect
+       sibcall because the pop behavior in epilogue may pollute the
+       content of caller-saved regsiter when the register is used for
+       indirect sibcall.  */
+  return (!TARGET_V3PUSH
+         && (cfun->machine->va_args_size == 0)
+         && decl);
+}
+
 /* Determine whether we need to enable warning for function return check.  */
 static bool
 nds32_warn_func_return (tree decl)
@@ -3764,6 +3784,9 @@ nds32_target_alignment (rtx_insn *label)
 
 /* -- Permitting tail calls.  */
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL nds32_function_ok_for_sibcall
+
 #undef TARGET_WARN_FUNC_RETURN
 #define TARGET_WARN_FUNC_RETURN nds32_warn_func_return
 
index e9bd791..0ececef 100644 (file)
@@ -1996,50 +1996,55 @@ create_template:
 ;; The sibcall patterns.
 
 ;; sibcall
-;; sibcall_register
-;; sibcall_immediate
+;; sibcall_internal
 
 (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"))
+(define_insn "sibcall_internal"
+  [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i"))
                    (match_operand 1))
              (clobber (reg:SI TA_REGNUM))
              (return)])]
   ""
 {
-  if (TARGET_CMODEL_LARGE)
-    return "b\t%0";
-  else
-    return "j\t%0";
+  switch (which_alternative)
+    {
+    case 0:
+      if (TARGET_16_BIT)
+       return "jr5\t%0";
+      else
+       return "jr\t%0";
+    case 1:
+      if (nds32_long_call_p (operands[0]))
+       return "b\t%0";
+      else
+       return "j\t%0";
+    default:
+      gcc_unreachable ();
+    }
 }
-  [(set_attr "type"   "branch")
-   (set (attr "length")
-       (if_then_else (match_test "TARGET_CMODEL_LARGE")
-                     (const_int 12)
-                     (const_int 4)))])
+  [(set_attr "enabled" "1")
+   (set_attr "type" "branch")
+   (set_attr_alternative "length"
+     [
+       ;; Alternative 0
+       (if_then_else (match_test "TARGET_16_BIT")
+                    (const_int 2)
+                    (const_int 4))
+       ;; Alternative 1
+       (if_then_else (match_test "nds32_long_call_p (operands[0])")
+                    (const_int 12)
+                    (const_int 4))
+     ])]
+)
 
 ;; sibcall_value
-;; sibcall_value_register
+;; sibcall_value_internal
 ;; sibcall_value_immediate
 
 (define_expand "sibcall_value"
@@ -2048,42 +2053,46 @@ create_template:
                         (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"
+(define_insn "sibcall_value_internal"
   [(parallel [(set (match_operand 0)
-                  (call (mem (match_operand:SI 1 "immediate_operand" "i"))
+                  (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i"))
                         (match_operand 2)))
              (clobber (reg:SI TA_REGNUM))
              (return)])]
   ""
 {
-  if (TARGET_CMODEL_LARGE)
-    return "b\t%1";
-  else
-    return "j\t%1";
+  switch (which_alternative)
+    {
+    case 0:
+      if (TARGET_16_BIT)
+       return "jr5\t%1";
+      else
+       return "jr\t%1";
+    case 1:
+      if (nds32_long_call_p (operands[1]))
+       return "b\t%1";
+      else
+       return "j\t%1";
+    default:
+      gcc_unreachable ();
+    }
 }
-  [(set_attr "type"   "branch")
-   (set (attr "length")
-       (if_then_else (match_test "TARGET_CMODEL_LARGE")
-                     (const_int 12)
-                     (const_int 4)))])
-
+  [(set_attr "enabled" "1")
+   (set_attr "type" "branch")
+   (set_attr_alternative "length"
+     [
+       ;; Alternative 0
+       (if_then_else (match_test "TARGET_16_BIT")
+                    (const_int 2)
+                    (const_int 4))
+       ;; Alternative 1
+       (if_then_else (match_test "nds32_long_call_p (operands[1])")
+                    (const_int 12)
+                    (const_int 4))
+     ])]
+)
 
 ;; ----------------------------------------------------------------------------
 
index bff37c7..ad04b51 100644 (file)
   return true;
 })
 
+(define_predicate "nds32_general_register_operand"
+  (match_code "reg,subreg")
+{
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  return (REG_P (op)
+         && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+             || REGNO (op) <= NDS32_LAST_GPR_REGNUM));
+})
+
+(define_predicate "nds32_call_address_operand"
+  (ior (match_operand 0 "nds32_symbolic_operand")
+       (match_operand 0 "nds32_general_register_operand")))
+
 (define_predicate "nds32_lmw_smw_base_operand"
   (and (match_code "mem")
        (match_test "nds32_valid_smw_lwm_base_p (op)")))