Ping
2015-05-19 12:39 GMT+03:00 Ilya Enkovich <enkovich....@gmail.com>: > Ping > > 2015-05-05 11:05 GMT+03:00 Ilya Enkovich <enkovich....@gmail.com>: >> Ping >> >> 2015-04-14 17:35 GMT+03:00 Ilya Enkovich <enkovich....@gmail.com>: >>> On 10 Apr 03:27, Jan Hubicka wrote: >>>> > >>>> > + /* We might propagate instrumented function pointer into >>>> > + not instrumented function and vice versa. In such a >>>> > + case we need to either fix function declaration or >>>> > + remove bounds from call statement. */ >>>> > + if (flag_check_pointer_bounds && callee) >>>> > + skip_bounds = chkp_redirect_edge (e); >>>> >>>> I think this gets wrong the case where the edge is speculative and the new >>>> direct call needs adjustement. You probably need to do the right think in >>>> the if (e->speculative) branch so direct call is updated by indirect is not >>>> or at least give an explanation why this is not needed :) >>>> >>>> The speculative edge handling works in a way that the runtime conditoinal >>>> is >>>> built and then the edge is updated to the direct path, so perhaps >>>> you can just move all this after the ocnditoinal? >>> >>> I think you are right, it should be OK to move it after apeculative call >>> processing. >>> >>>> >>>> > diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c >>>> > index 404cb68..ffb6ad7 100644 >>>> > --- a/gcc/lto-wrapper.c >>>> > +++ b/gcc/lto-wrapper.c >>>> > @@ -273,6 +273,7 @@ merge_and_complain (struct cl_decoded_option >>>> > **decoded_options, >>>> > case OPT_fwrapv: >>>> > case OPT_fopenmp: >>>> > case OPT_fopenacc: >>>> > + case OPT_fcheck_pointer_bounds: >>>> > /* For selected options we can merge conservatively. */ >>>> > for (j = 0; j < *decoded_options_count; ++j) >>>> > if ((*decoded_options)[j].opt_index == foption->opt_index) >>>> > @@ -503,6 +504,7 @@ append_compiler_options (obstack *argv_obstack, >>>> > struct cl_decoded_option *opts, >>>> > case OPT_Ofast: >>>> > case OPT_Og: >>>> > case OPT_Os: >>>> > + case OPT_fcheck_pointer_bounds: >>>> >>>> Hmm, will this make mixed units contaiing some check bounds and some >>>> non-check bounds to work? >>>> Perhaps these should be function specific? Does things like inlining >>>> bounds checked function into >>>> non-checked function work? >>> >>> This actually should make it work better because solves a possible problem >>> with uninitialized static bounds data (chkp static constructors are >>> generated only when OPT_fcheck_pointer_bounds is passed). >>> >>> Inlining of instrumentation thunks is not supported (similar to all other >>> thunks). But we may have a not instrumented call in an instrumented >>> function and do inlining for it. >>> >>>> >>>> Otherwise the patch seems resonable. >>>> Honza >>> >>> >>> Here is a fixed version with chkp redirection moved. Bootstrap and testing >>> passed. Is it OK for trunk and later for GCC 5? >>> >>> Thanks, >>> Ilya >>> -- >>> gcc/ >>> >>> 2015-04-14 Ilya Enkovich <ilya.enkov...@intel.com> >>> >>> PR target/65527 >>> * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Add >>> redirection for instrumented calls. >>> * lto-wrapper.c (merge_and_complain): Merge -fcheck-pointer-bounds. >>> (append_compiler_options): Append -fcheck-pointer-bounds. >>> * tree-chkp.h (chkp_copy_call_skip_bounds): New. >>> (chkp_redirect_edge): New. >>> * tree-chkp.c (chkp_copy_call_skip_bounds): New. >>> (chkp_redirect_edge): New. >>> >>> gcc/testsuite/ >>> >>> 2015-04-14 Ilya Enkovich <ilya.enkov...@intel.com> >>> >>> PR target/65527 >>> * gcc.target/i386/mpx/chkp-fix-calls-1.c: New. >>> * gcc.target/i386/mpx/chkp-fix-calls-2.c: New. >>> * gcc.target/i386/mpx/chkp-fix-calls-3.c: New. >>> * gcc.target/i386/mpx/chkp-fix-calls-4.c: New. >>> >>> >>> diff --git a/gcc/cgraph.c b/gcc/cgraph.c >>> index 85531c8..38e71fc 100644 >>> --- a/gcc/cgraph.c >>> +++ b/gcc/cgraph.c >>> @@ -1281,6 +1281,7 @@ cgraph_edge::redirect_call_stmt_to_callee (void) >>> tree lhs = gimple_call_lhs (e->call_stmt); >>> gcall *new_stmt; >>> gimple_stmt_iterator gsi; >>> + bool skip_bounds = false; >>> #ifdef ENABLE_CHECKING >>> cgraph_node *node; >>> #endif >>> @@ -1389,8 +1390,16 @@ cgraph_edge::redirect_call_stmt_to_callee (void) >>> } >>> } >>> >>> + /* We might propagate instrumented function pointer into >>> + not instrumented function and vice versa. In such a >>> + case we need to either fix function declaration or >>> + remove bounds from call statement. */ >>> + if (flag_check_pointer_bounds && e->callee) >>> + skip_bounds = chkp_redirect_edge (e); >>> + >>> if (e->indirect_unknown_callee >>> - || decl == e->callee->decl) >>> + || (decl == e->callee->decl >>> + && !skip_bounds)) >>> return e->call_stmt; >>> >>> #ifdef ENABLE_CHECKING >>> @@ -1415,13 +1424,19 @@ cgraph_edge::redirect_call_stmt_to_callee (void) >>> } >>> } >>> >>> - if (e->callee->clone.combined_args_to_skip) >>> + if (e->callee->clone.combined_args_to_skip >>> + || skip_bounds) >>> { >>> int lp_nr; >>> >>> - new_stmt >>> - = gimple_call_copy_skip_args (e->call_stmt, >>> - >>> e->callee->clone.combined_args_to_skip); >>> + new_stmt = e->call_stmt; >>> + if (e->callee->clone.combined_args_to_skip) >>> + new_stmt >>> + = gimple_call_copy_skip_args (new_stmt, >>> + >>> e->callee->clone.combined_args_to_skip); >>> + if (skip_bounds) >>> + new_stmt = chkp_copy_call_skip_bounds (new_stmt); >>> + >>> gimple_call_set_fndecl (new_stmt, e->callee->decl); >>> gimple_call_set_fntype (new_stmt, gimple_call_fntype (e->call_stmt)); >>> >>> diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c >>> index 404cb68..ffb6ad7 100644 >>> --- a/gcc/lto-wrapper.c >>> +++ b/gcc/lto-wrapper.c >>> @@ -273,6 +273,7 @@ merge_and_complain (struct cl_decoded_option >>> **decoded_options, >>> case OPT_fwrapv: >>> case OPT_fopenmp: >>> case OPT_fopenacc: >>> + case OPT_fcheck_pointer_bounds: >>> /* For selected options we can merge conservatively. */ >>> for (j = 0; j < *decoded_options_count; ++j) >>> if ((*decoded_options)[j].opt_index == foption->opt_index) >>> @@ -503,6 +504,7 @@ append_compiler_options (obstack *argv_obstack, struct >>> cl_decoded_option *opts, >>> case OPT_Ofast: >>> case OPT_Og: >>> case OPT_Os: >>> + case OPT_fcheck_pointer_bounds: >>> break; >>> >>> default: >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-1.c >>> b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-1.c >>> new file mode 100644 >>> index 0000000..cb4d229 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-1.c >>> @@ -0,0 +1,16 @@ >>> +/* { dg-do compile } */ >>> +/* { dg-options "-O2 -fcheck-pointer-bounds -mmpx" } */ >>> + >>> +#include "math.h" >>> + >>> +double >>> +test1 (double x, double y, double (*fn)(double, double)) >>> +{ >>> + return fn (x, y); >>> +} >>> + >>> +double >>> +test2 (double x, double y) >>> +{ >>> + return test1 (x, y, copysign); >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-2.c >>> b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-2.c >>> new file mode 100644 >>> index 0000000..951e7de >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-2.c >>> @@ -0,0 +1,16 @@ >>> +/* { dg-do compile } */ >>> +/* { dg-options "-O3 -fcheck-pointer-bounds -mmpx -fno-inline" } */ >>> + >>> +#include "math.h" >>> + >>> +double >>> +test1 (double x, double y, double (*fn)(double, double)) >>> +{ >>> + return fn (x, y); >>> +} >>> + >>> +double >>> +test2 (double x, double y) >>> +{ >>> + return test1 (x, y, copysign); >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-3.c >>> b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-3.c >>> new file mode 100755 >>> index 0000000..439f631 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-3.c >>> @@ -0,0 +1,33 @@ >>> +/* { dg-do compile } */ >>> +/* { dg-options "-O2 -fexceptions -fcheck-pointer-bounds -mmpx" } */ >>> + >>> +extern int f2 (const char*, int, ...); >>> +extern long int f3 (int *); >>> +extern void err (void) __attribute__((__error__("error"))); >>> + >>> +extern __inline __attribute__ ((__always_inline__)) int >>> +f1 (int i, ...) >>> +{ >>> + if (__builtin_constant_p (i)) >>> + { >>> + if (i) >>> + err (); >>> + return f2 ("", i); >>> + } >>> + >>> + return f2 ("", i); >>> +} >>> + >>> +int >>> +test () >>> +{ >>> + int i; >>> + >>> + if (f1 (0)) >>> + if (f3 (&i)) >>> + i = 0; >>> + >>> + return i; >>> +} >>> + >>> + >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-4.c >>> b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-4.c >>> new file mode 100644 >>> index 0000000..1b7d703 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-4.c >>> @@ -0,0 +1,17 @@ >>> +/* { dg-do compile } */ >>> +/* { dg-options "-Os -fcheck-pointer-bounds -mmpx" } */ >>> + >>> +typedef void (func) (int *); >>> + >>> +static inline void >>> +bar (func f) >>> +{ >>> + int i; >>> + f (&i); >>> +} >>> + >>> +void >>> +foo () >>> +{ >>> + bar (0); >>> +} >>> diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c >>> index 8c5a628..c2d9e94 100644 >>> --- a/gcc/tree-chkp.c >>> +++ b/gcc/tree-chkp.c >>> @@ -529,6 +529,71 @@ chkp_insert_retbnd_call (tree bndval, tree retval, >>> return bndval; >>> } >>> >>> +/* Build a GIMPLE_CALL identical to CALL but skipping bounds >>> + arguments. */ >>> + >>> +gcall * >>> +chkp_copy_call_skip_bounds (gcall *call) >>> +{ >>> + bitmap bounds; >>> + unsigned i; >>> + >>> + bitmap_obstack_initialize (NULL); >>> + bounds = BITMAP_ALLOC (NULL); >>> + >>> + for (i = 0; i < gimple_call_num_args (call); i++) >>> + if (POINTER_BOUNDS_P (gimple_call_arg (call, i))) >>> + bitmap_set_bit (bounds, i); >>> + >>> + if (!bitmap_empty_p (bounds)) >>> + call = gimple_call_copy_skip_args (call, bounds); >>> + gimple_call_set_with_bounds (call, false); >>> + >>> + BITMAP_FREE (bounds); >>> + bitmap_obstack_release (NULL); >>> + >>> + return call; >>> +} >>> + >>> +/* Redirect edge E to the correct node according to call_stmt. >>> + Return 1 if bounds removal from call_stmt should be done >>> + instead of redirection. */ >>> + >>> +bool >>> +chkp_redirect_edge (cgraph_edge *e) >>> +{ >>> + bool instrumented = false; >>> + tree decl = e->callee->decl; >>> + >>> + if (e->callee->instrumentation_clone >>> + || chkp_function_instrumented_p (decl)) >>> + instrumented = true; >>> + >>> + if (instrumented >>> + && !gimple_call_with_bounds_p (e->call_stmt)) >>> + e->redirect_callee (cgraph_node::get_create (e->callee->orig_decl)); >>> + else if (!instrumented >>> + && gimple_call_with_bounds_p (e->call_stmt) >>> + && !chkp_gimple_call_builtin_p (e->call_stmt, >>> BUILT_IN_CHKP_BNDCL) >>> + && !chkp_gimple_call_builtin_p (e->call_stmt, >>> BUILT_IN_CHKP_BNDCU) >>> + && !chkp_gimple_call_builtin_p (e->call_stmt, >>> BUILT_IN_CHKP_BNDSTX)) >>> + { >>> + if (e->callee->instrumented_version) >>> + e->redirect_callee (e->callee->instrumented_version); >>> + else >>> + { >>> + tree args = TYPE_ARG_TYPES (TREE_TYPE (decl)); >>> + /* Avoid bounds removal if all args will be removed. */ >>> + if (!args || TREE_VALUE (args) != void_type_node) >>> + return true; >>> + else >>> + gimple_call_set_with_bounds (e->call_stmt, false); >>> + } >>> + } >>> + >>> + return false; >>> +} >>> + >>> /* Mark statement S to not be instrumented. */ >>> static void >>> chkp_mark_stmt (gimple s) >>> diff --git a/gcc/tree-chkp.h b/gcc/tree-chkp.h >>> index 1bafe99..b5ab562 100644 >>> --- a/gcc/tree-chkp.h >>> +++ b/gcc/tree-chkp.h >>> @@ -56,5 +56,7 @@ extern bool chkp_gimple_call_builtin_p (gimple call, >>> extern void chkp_expand_bounds_reset_for_mem (tree mem, tree ptr); >>> extern tree chkp_insert_retbnd_call (tree bndval, tree retval, >>> gimple_stmt_iterator *gsi); >>> +extern gcall *chkp_copy_call_skip_bounds (gcall *call); >>> +extern bool chkp_redirect_edge (cgraph_edge *e); >>> >>> #endif /* GCC_TREE_CHKP_H */