aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorChung-Ju Wu <jasonwucj@gmail.com>2018-04-04 00:56:16 +0000
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>2018-04-04 00:56:16 +0000
commitcc48a87f9d1eae385269d87882517c183a06c383 (patch)
tree8c64481b3536726aae27b23b9257fb85095ed3d5 /gcc
parenta1b81a03200461827fcfd851af085ab4f7837190 (diff)
downloadgcc-cc48a87f9d1eae385269d87882517c183a06c383.zip
gcc-cc48a87f9d1eae385269d87882517c183a06c383.tar.gz
gcc-cc48a87f9d1eae385269d87882517c183a06c383.tar.bz2
[NDS32] Refine implementation of sibcall patterns.
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/config/nds32/nds32-md-auxiliary.c7
-rw-r--r--gcc/config/nds32/nds32-protos.h3
-rw-r--r--gcc/config/nds32/nds32.c23
-rw-r--r--gcc/config/nds32/nds32.md123
-rw-r--r--gcc/config/nds32/predicates.md15
6 files changed, 130 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cd64aa4..2b3369b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/nds32/nds32-md-auxiliary.c b/gcc/config/nds32/nds32-md-auxiliary.c
index 755945f..5311b69 100644
--- a/gcc/config/nds32/nds32-md-auxiliary.c
+++ b/gcc/config/nds32/nds32-md-auxiliary.c
@@ -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;
+}
diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
index 1387cca..6a3281b 100644
--- a/gcc/config/nds32/nds32-protos.h
+++ b/gcc/config/nds32/nds32-protos.h
@@ -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);
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index 06a59be..829e097 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -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
diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md
index e9bd791..0ececef 100644
--- a/gcc/config/nds32/nds32.md
+++ b/gcc/config/nds32/nds32.md
@@ -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))
+ ])]
+)
;; ----------------------------------------------------------------------------
diff --git a/gcc/config/nds32/predicates.md b/gcc/config/nds32/predicates.md
index bff37c7..ad04b51 100644
--- a/gcc/config/nds32/predicates.md
+++ b/gcc/config/nds32/predicates.md
@@ -57,6 +57,21 @@
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)")))