aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>2015-08-04 10:17:13 +0000
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>2015-08-04 10:17:13 +0000
commit1fd8d40c7ff31933590e23be2a59c82889bcc6c1 (patch)
tree4295b4a44f7bfe4d4ba64773dfc09cd2770fd901
parent5a2c833115cc88f420f577e36ba46be6295cc23a (diff)
downloadgcc-1fd8d40c7ff31933590e23be2a59c82889bcc6c1.zip
gcc-1fd8d40c7ff31933590e23be2a59c82889bcc6c1.tar.gz
gcc-1fd8d40c7ff31933590e23be2a59c82889bcc6c1.tar.bz2
[AArch64][9/14] Implement TARGET_CAN_INLINE_P
* config/aarch64/aarch64.c (aarch64_tribools_ok_for_inlining_p): New function. (aarch64_can_inline_p): Likewise. (TARGET_CAN_INLINE_P): Define. From-SVN: r226561
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/aarch64/aarch64.c110
2 files changed, 117 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6344d85..28a55d5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2015-08-04 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ * config/aarch64/aarch64.c (aarch64_tribools_ok_for_inlining_p):
+ New function.
+ (aarch64_can_inline_p): Likewise.
+ (TARGET_CAN_INLINE_P): Define.
+
+2015-08-04 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
* common/config/aarch64/aarch64-common.c (aarch64_handle_option):
Remove static. Handle OPT_mgeneral_regs_only,
OPT_mfix_cortex_a53_835769, OPT_mstrict_align,
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 7a369fd..6b418a7 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -8459,6 +8459,113 @@ aarch64_option_valid_attribute_p (tree fndecl, tree, tree args, int)
return ret;
}
+/* Helper for aarch64_can_inline_p. In the case where CALLER and CALLEE are
+ tri-bool options (yes, no, don't care) and the default value is
+ DEF, determine whether to reject inlining. */
+
+static bool
+aarch64_tribools_ok_for_inlining_p (int caller, int callee,
+ int dont_care, int def)
+{
+ /* If the callee doesn't care, always allow inlining. */
+ if (callee == dont_care)
+ return true;
+
+ /* If the caller doesn't care, always allow inlining. */
+ if (caller == dont_care)
+ return true;
+
+ /* Otherwise, allow inlining if either the callee and caller values
+ agree, or if the callee is using the default value. */
+ return (callee == caller || callee == def);
+}
+
+/* Implement TARGET_CAN_INLINE_P. Decide whether it is valid
+ to inline CALLEE into CALLER based on target-specific info.
+ Make sure that the caller and callee have compatible architectural
+ features. Then go through the other possible target attributes
+ and see if they can block inlining. Try not to reject always_inline
+ callees unless they are incompatible architecturally. */
+
+static bool
+aarch64_can_inline_p (tree caller, tree callee)
+{
+ tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller);
+ tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee);
+
+ /* If callee has no option attributes, then it is ok to inline. */
+ if (!callee_tree)
+ return true;
+
+ struct cl_target_option *caller_opts
+ = TREE_TARGET_OPTION (caller_tree ? caller_tree
+ : target_option_default_node);
+
+ struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree);
+
+
+ /* Callee's ISA flags should be a subset of the caller's. */
+ if ((caller_opts->x_aarch64_isa_flags & callee_opts->x_aarch64_isa_flags)
+ != callee_opts->x_aarch64_isa_flags)
+ return false;
+
+ /* Allow non-strict aligned functions inlining into strict
+ aligned ones. */
+ if ((TARGET_STRICT_ALIGN_P (caller_opts->x_target_flags)
+ != TARGET_STRICT_ALIGN_P (callee_opts->x_target_flags))
+ && !(!TARGET_STRICT_ALIGN_P (callee_opts->x_target_flags)
+ && TARGET_STRICT_ALIGN_P (caller_opts->x_target_flags)))
+ return false;
+
+ bool always_inline = lookup_attribute ("always_inline",
+ DECL_ATTRIBUTES (callee));
+
+ /* If the architectural features match up and the callee is always_inline
+ then the other attributes don't matter. */
+ if (always_inline)
+ return true;
+
+ if (caller_opts->x_aarch64_cmodel_var
+ != callee_opts->x_aarch64_cmodel_var)
+ return false;
+
+ if (caller_opts->x_aarch64_tls_dialect
+ != callee_opts->x_aarch64_tls_dialect)
+ return false;
+
+ /* Honour explicit requests to workaround errata. */
+ if (!aarch64_tribools_ok_for_inlining_p (
+ caller_opts->x_aarch64_fix_a53_err835769,
+ callee_opts->x_aarch64_fix_a53_err835769,
+ 2, TARGET_FIX_ERR_A53_835769_DEFAULT))
+ return false;
+
+ /* If the user explicitly specified -momit-leaf-frame-pointer for the
+ caller and calle and they don't match up, reject inlining. */
+ if (!aarch64_tribools_ok_for_inlining_p (
+ caller_opts->x_flag_omit_leaf_frame_pointer,
+ callee_opts->x_flag_omit_leaf_frame_pointer,
+ 2, 1))
+ return false;
+
+ /* If the callee has specific tuning overrides, respect them. */
+ if (callee_opts->x_aarch64_override_tune_string != NULL
+ && caller_opts->x_aarch64_override_tune_string == NULL)
+ return false;
+
+ /* If the user specified tuning override strings for the
+ caller and callee and they don't match up, reject inlining.
+ We just do a string compare here, we don't analyze the meaning
+ of the string, as it would be too costly for little gain. */
+ if (callee_opts->x_aarch64_override_tune_string
+ && caller_opts->x_aarch64_override_tune_string
+ && (strcmp (callee_opts->x_aarch64_override_tune_string,
+ caller_opts->x_aarch64_override_tune_string) != 0))
+ return false;
+
+ return true;
+}
+
/* Return true if SYMBOL_REF X binds locally. */
static bool
@@ -12863,6 +12970,9 @@ aarch64_promoted_type (const_tree t)
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE aarch64_can_eliminate
+#undef TARGET_CAN_INLINE_P
+#define TARGET_CAN_INLINE_P aarch64_can_inline_p
+
#undef TARGET_CANNOT_FORCE_CONST_MEM
#define TARGET_CANNOT_FORCE_CONST_MEM aarch64_cannot_force_const_mem