From: Kyrylo Tkachov Date: Tue, 4 Aug 2015 10:17:13 +0000 (+0000) Subject: [AArch64][9/14] Implement TARGET_CAN_INLINE_P X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1fd8d40c7ff31933590e23be2a59c82889bcc6c1;p=gcc.git [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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6344d8571ae..28a55d5529e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2015-08-04 Kyrylo Tkachov + + * 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 * common/config/aarch64/aarch64-common.c (aarch64_handle_option): diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 7a369fd4734..6b418a7a129 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