On 14 Nov 23:58, Jeff Law wrote: > On 11/14/14 01:06, Ilya Enkovich wrote: > > >>>- /* Avoid instrumented builtin functions for now. Due to IPA > >>>- it also means we have to avoid instrumentation of indirect > >>>- calls. */ > >>>- if (fndecl && DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN) > >>>- return; > >>>+ /* We instrument only some subset of builtins. We also instrument > >>>+ builtin calls to be inlined. */ > >>>+ if (fndecl > >>>+ && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL > >>>+ && !chkp_instrument_normal_builtin (fndecl)) > >>>+ { > >>>+ struct cgraph_node *clone = chkp_maybe_create_clone (fndecl); > >>>+ if (!clone > >>>+ || !gimple_has_body_p (clone->decl) > >>>+ || !lookup_attribute ("always_inline", DECL_ATTRIBUTES > >>>(fndecl))) > >>>+ return; > >>>+ } > >> > >>Is that outer conditional right? If we have a fndecl and it's a normal > >>builtin, but it's _not_ one of hte builtins we're instrumenting, then call > >>chkp_maybe_create_clone? > > > >Some builtin functions (especially their *_chk version) are defined as > >always_inline functions in headers. In this case we handle them as > >regular functions (clone and instrument) because they will be inlined > >anyway. Seems gimple_has_body_p should be applied to fndecl and moved > >into outer if-statement along with attribute check. Thus unneeded > >clones would be avoided. > So the outer condition is, essentially checking for a _chk builtin > and if we find it, try to create a clone for instrumentation > purposes. > > I think the always_inline attribute lookup can move to the outer-if. > Less sure about the gimple_has_body check though. Presumably > clone->decl is going to refer to fndecl? If so, then that can move > to the outer if as well. As you say, that may cut down on the > number of clones that get created. > > OK as-is, or with those two conditions moved out of level as long as > all prerequisites are approved and it passes a bootstrap & > regression test. > > JEff
I moved always_inline check up. Here is a final version. Thanks, Ilya -- diff --git a/gcc/ipa-chkp.c b/gcc/ipa-chkp.c index 3e343d4..46b2139 100644 --- a/gcc/ipa-chkp.c +++ b/gcc/ipa-chkp.c @@ -581,8 +581,9 @@ chkp_versioning (void) && (!flag_chkp_instrument_marked_only || lookup_attribute ("bnd_instrument", DECL_ATTRIBUTES (node->decl))) - /* No builtins instrumentation for now. */ - && DECL_BUILT_IN_CLASS (node->decl) == NOT_BUILT_IN) + && (!DECL_BUILT_IN (node->decl) + || (DECL_BUILT_IN_CLASS (node->decl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (node->decl) < BEGIN_CHKP_BUILTINS))) chkp_maybe_create_clone (node->decl); } diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c index df7d425..0fb78cc 100644 --- a/gcc/tree-chkp.c +++ b/gcc/tree-chkp.c @@ -1586,6 +1586,50 @@ chkp_find_bound_slots (const_tree type, bitmap res) chkp_find_bound_slots_1 (type, res, 0); } +/* Return 1 if call to FNDECL should be instrumented + and 0 otherwise. */ + +static bool +chkp_instrument_normal_builtin (tree fndecl) +{ + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_STRLEN: + case BUILT_IN_STRCPY: + case BUILT_IN_STRNCPY: + case BUILT_IN_STPCPY: + case BUILT_IN_STPNCPY: + case BUILT_IN_STRCAT: + case BUILT_IN_STRNCAT: + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMPCPY: + case BUILT_IN_MEMSET: + case BUILT_IN_MEMMOVE: + case BUILT_IN_BZERO: + case BUILT_IN_STRCMP: + case BUILT_IN_STRNCMP: + case BUILT_IN_BCMP: + case BUILT_IN_MEMCMP: + case BUILT_IN_MEMCPY_CHK: + case BUILT_IN_MEMPCPY_CHK: + case BUILT_IN_MEMMOVE_CHK: + case BUILT_IN_MEMSET_CHK: + case BUILT_IN_STRCPY_CHK: + case BUILT_IN_STRNCPY_CHK: + case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STPNCPY_CHK: + case BUILT_IN_STRCAT_CHK: + case BUILT_IN_STRNCAT_CHK: + case BUILT_IN_MALLOC: + case BUILT_IN_CALLOC: + case BUILT_IN_REALLOC: + return 1; + + default: + return 0; + } +} + /* Add bound arguments to call statement pointed by GSI. Also performs a replacement of user checker builtins calls with internal ones. */ @@ -1619,7 +1663,7 @@ chkp_add_bounds_to_call_stmt (gimple_stmt_iterator *gsi) && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_OBJECT_SIZE) return; - /* Donothing for calls to legacy functions. */ + /* Do nothing for calls to legacy functions. */ if (fndecl && lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl))) return; @@ -1686,11 +1730,20 @@ chkp_add_bounds_to_call_stmt (gimple_stmt_iterator *gsi) if (!flag_chkp_instrument_calls) return; - /* Avoid instrumented builtin functions for now. Due to IPA - it also means we have to avoid instrumentation of indirect - calls. */ - if (fndecl && DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN) - return; + /* We instrument only some subset of builtins. We also instrument + builtin calls to be inlined. */ + if (fndecl + && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL + && !chkp_instrument_normal_builtin (fndecl)) + { + if (!lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl))) + return; + + struct cgraph_node *clone = chkp_maybe_create_clone (fndecl); + if (!clone + || !gimple_has_body_p (clone->decl)) + return; + } /* If function decl is available then use it for formal arguments list. Otherwise use function type. */ @@ -1764,14 +1817,6 @@ chkp_add_bounds_to_call_stmt (gimple_stmt_iterator *gsi) } new_args.release (); - /* If we call built-in function and pass no bounds then - we do not need to change anything. */ - if (new_call == call - && fndecl - && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL - && fndecl == builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl))) - return; - /* For direct calls fndecl is replaced with instrumented version. */ if (fndecl) { @@ -3905,15 +3950,21 @@ chkp_replace_function_pointer (tree *op, int *walk_subtrees, { if (TREE_CODE (*op) == FUNCTION_DECL && !lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (*op)) - /* Do not replace builtins for now. */ - && DECL_BUILT_IN_CLASS (*op) == NOT_BUILT_IN) + && (DECL_BUILT_IN_CLASS (*op) == NOT_BUILT_IN + /* For builtins we replace pointers only for selected + function and functions having definitions. */ + || (DECL_BUILT_IN_CLASS (*op) == BUILT_IN_NORMAL + && (chkp_instrument_normal_builtin (*op) + || gimple_has_body_p (*op))))) { struct cgraph_node *node = cgraph_node::get_create (*op); + struct cgraph_node *clone = NULL; if (!node->instrumentation_clone) - chkp_maybe_create_clone (*op); + clone = chkp_maybe_create_clone (*op); - *op = node->instrumented_version->decl; + if (clone) + *op = clone->decl; *walk_subtrees = 0; }