Message ID | 20150306141531.GA27860@msticlxl57.ims.intel.com |
---|---|
State | New |
Headers | show |
Ping 2015-03-10 13:12 GMT+03:00 Ilya Enkovich <enkovich.gnu@gmail.com>: > Hi, > > Currentl we loose returned bounds when functions are merged. This patch fixes it by adding returne bounds support for cgraph_node::expand_thunk. Bootstrapped and tested on x86_64-unknown-linux-gnu. OK for trunk? > > Thanks, > Ilya > -- > gcc/ > > 2015-03-06 Ilya Enkovich <ilya.enkovich@intel.com> > > * cgraphunit.c (cgraph_node::expand_thunk): Build returned > bounds for instrumented functions. > > gcc/testsuite/ > > 2015-03-06 Ilya Enkovich <ilya.enkovich@intel.com> > > * gcc/testsuite/gcc.target/i386/thunk-retbnd.c: New. > > > diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c > index e640907..fc38e67 100644 > --- a/gcc/cgraphunit.c > +++ b/gcc/cgraphunit.c > @@ -1581,6 +1581,7 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk) > int i; > tree resdecl; > tree restmp = NULL; > + tree resbnd = NULL; > > gcall *call; > greturn *ret; > @@ -1697,6 +1698,21 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk) > gsi_insert_after (&bsi, call, GSI_NEW_STMT); > if (!alias_is_noreturn) > { > + if (instrumentation_clone > + && !DECL_BY_REFERENCE (resdecl) > + && restmp > + && BOUNDED_P (restmp)) > + { > + tree fn = targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDRET); > + gcall *retbnd = gimple_build_call (fn, 1, restmp); > + > + resbnd = create_tmp_reg (pointer_bounds_type_node, "retbnd"); > + gimple_call_set_lhs (retbnd, resbnd); > + > + gsi_insert_after (&bsi, retbnd, GSI_NEW_STMT); > + create_edge (get_create (fn), retbnd, callees->count, callees->frequency); > + } > + > if (restmp && !this_adjusting > && (fixed_offset || virtual_offset)) > { > @@ -1766,6 +1782,7 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk) > ret = gimple_build_return (restmp); > else > ret = gimple_build_return (resdecl); > + gimple_return_set_retbnd (ret, resbnd); > > gsi_insert_after (&bsi, ret, GSI_NEW_STMT); > } > diff --git a/gcc/testsuite/gcc.target/i386/thunk-retbnd.c b/gcc/testsuite/gcc.target/i386/thunk-retbnd.c > new file mode 100644 > index 0000000..d9bd031 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/thunk-retbnd.c > @@ -0,0 +1,19 @@ > +/* { dg-do compile } */ > +/* { dg-require-effective-target mpx } */ > +/* { dg-options "-O2 -fcheck-pointer-bounds -mmpx -fdump-tree-optimized" } */ > +/* { dg-final { scan-tree-dump-times "return &glob," 2 "optimized" } } */ > +/* { dg-final { cleanup-tree-dump "optimized" } } */ > + > +int glob; > + > +int * > +test1 (void) > +{ > + return &glob; > +} > + > +int * > +test2 (void) > +{ > + return test1 (); > +}
On 04/02/2015 08:49 AM, Ilya Enkovich wrote: > Ping > > 2015-03-10 13:12 GMT+03:00 Ilya Enkovich <enkovich.gnu@gmail.com>: >> Hi, >> >> Currentl we loose returned bounds when functions are merged. This patch fixes it by adding returne bounds support for cgraph_node::expand_thunk. Bootstrapped and tested on x86_64-unknown-linux-gnu. OK for trunk? >> >> Thanks, >> Ilya >> -- >> gcc/ >> >> 2015-03-06 Ilya Enkovich <ilya.enkovich@intel.com> >> >> * cgraphunit.c (cgraph_node::expand_thunk): Build returned >> bounds for instrumented functions. >> >> gcc/testsuite/ >> >> 2015-03-06 Ilya Enkovich <ilya.enkovich@intel.com> >> >> * gcc/testsuite/gcc.target/i386/thunk-retbnd.c: New. I really dislike the amount of gimple and bounded pointer knowledge in this code. It seems like a significant modularity violation and while you didn't introduce the gimple stuff, we probably shouldn't be making it worse. Is it possible to let this code build up the thunk, then pass it off as a whole to the chkp code to add the instrumentation, particularly for the return value? ALso, is this critical for stage4? It looks like this is strictly a QofI change, correct? jeff
> Ping > > 2015-03-10 13:12 GMT+03:00 Ilya Enkovich <enkovich.gnu@gmail.com>: > > Hi, > > > > Currentl we loose returned bounds when functions are merged. This patch fixes it by adding returne bounds support for cgraph_node::expand_thunk. Bootstrapped and tested on x86_64-unknown-linux-gnu. OK for trunk? > > 2015-03-06 Ilya Enkovich <ilya.enkovich@intel.com> > > > > * cgraphunit.c (cgraph_node::expand_thunk): Build returned > > bounds for instrumented functions. I think if the extra bultin call is needed here, the same andling needs to be added to ipa-split. We really ought to unify that code - it is surprisingly difficult to produce a wrapper call these days. > > + if (instrumentation_clone > > + && !DECL_BY_REFERENCE (resdecl) > > + && restmp > > + && BOUNDED_P (restmp)) > > + { > > + tree fn = targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDRET); > > + gcall *retbnd = gimple_build_call (fn, 1, restmp); > > + > > + resbnd = create_tmp_reg (pointer_bounds_type_node, "retbnd"); > > + gimple_call_set_lhs (retbnd, resbnd); > > + > > + gsi_insert_after (&bsi, retbnd, GSI_NEW_STMT); > > + create_edge (get_create (fn), retbnd, callees->count, callees->frequency); > > + } I am not sure why we need to check here: Originaly we have two bounded functions, A and B. We turn function B to a wrapper of function A. If callers of bounded functions need to call a builtin, I would expect all callers of B to do it already, so I would expect that wrapper is safe here? Or do we mix instrumented and non-instrumented versions somehow? Addding code handling return value is going to turn the call to non-tailcall, so you probably want to drop the tailcall flag, too. Honza
2015-04-02 22:42 GMT+03:00 Jeff Law <law@redhat.com>: > On 04/02/2015 08:49 AM, Ilya Enkovich wrote: >> >> Ping >> >> 2015-03-10 13:12 GMT+03:00 Ilya Enkovich <enkovich.gnu@gmail.com>: >>> >>> Hi, >>> >>> Currentl we loose returned bounds when functions are merged. This patch >>> fixes it by adding returne bounds support for cgraph_node::expand_thunk. >>> Bootstrapped and tested on x86_64-unknown-linux-gnu. OK for trunk? >>> >>> Thanks, >>> Ilya >>> -- >>> gcc/ >>> >>> 2015-03-06 Ilya Enkovich <ilya.enkovich@intel.com> >>> >>> * cgraphunit.c (cgraph_node::expand_thunk): Build returned >>> bounds for instrumented functions. >>> >>> gcc/testsuite/ >>> >>> 2015-03-06 Ilya Enkovich <ilya.enkovich@intel.com> >>> >>> * gcc/testsuite/gcc.target/i386/thunk-retbnd.c: New. > > I really dislike the amount of gimple and bounded pointer knowledge in this > code. > > It seems like a significant modularity violation and while you didn't > introduce the gimple stuff, we probably shouldn't be making it worse. > > Is it possible to let this code build up the thunk, then pass it off as a > whole to the chkp code to add the instrumentation, particularly for the > return value? OK, will rework the patch. > > ALso, is this critical for stage4? It looks like this is strictly a QofI > change, correct? Actually having just a tail call in a function we don't lose bounds and I don't expect it affects QofI. But we get instrumented function with no returned bounds for a pointer which triggers an assert somewhere (don't remember exact place). I'll revisit the original problem and will probably make a simpler stability fix for now, leaving thunk modification for stage 1. Thanks, Ilya > > jeff >
2015-04-02 23:55 GMT+03:00 Jan Hubicka <hubicka@ucw.cz>: >> Ping >> >> 2015-03-10 13:12 GMT+03:00 Ilya Enkovich <enkovich.gnu@gmail.com>: >> > Hi, >> > >> > Currentl we loose returned bounds when functions are merged. This patch fixes it by adding returne bounds support for cgraph_node::expand_thunk. Bootstrapped and tested on x86_64-unknown-linux-gnu. OK for trunk? >> > 2015-03-06 Ilya Enkovich <ilya.enkovich@intel.com> >> > >> > * cgraphunit.c (cgraph_node::expand_thunk): Build returned >> > bounds for instrumented functions. > > I think if the extra bultin call is needed here, the same andling needs to be > added to ipa-split. We really ought to unify that code - it is surprisingly > difficult to produce a wrapper call these days. Yep, there is such code in place. It is done by insert_bndret_call_after. You are right, I should use the same interface for both these cases. >> > + if (instrumentation_clone >> > + && !DECL_BY_REFERENCE (resdecl) >> > + && restmp >> > + && BOUNDED_P (restmp)) >> > + { >> > + tree fn = targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDRET); >> > + gcall *retbnd = gimple_build_call (fn, 1, restmp); >> > + >> > + resbnd = create_tmp_reg (pointer_bounds_type_node, "retbnd"); >> > + gimple_call_set_lhs (retbnd, resbnd); >> > + >> > + gsi_insert_after (&bsi, retbnd, GSI_NEW_STMT); >> > + create_edge (get_create (fn), retbnd, callees->count, callees->frequency); >> > + } > > I am not sure why we need to check here: Originaly we have two bounded functions, A and B. > We turn function B to a wrapper of function A. If callers of bounded functions need > to call a builtin, I would expect all callers of B to do it already, so I would expect > that wrapper is safe here? The problem with instrumented call is that instrumented function returns two values and call lhs gets only the first one. Thus we generate bndret call to get the second one to build own return with two values. > > Or do we mix instrumented and non-instrumented versions somehow? > > Addding code handling return value is going to turn the call to non-tailcall, so you probably > want to drop the tailcall flag, too. No, function still return what the last call return, thus may keep tailcall. Thanks, Ilya > > Honza
> > Yep, there is such code in place. It is done by > insert_bndret_call_after. You are right, I should use the same > interface for both these cases. That would be nice indeed. We should separate out and unify the code for porducing a wrapper call next stage1 (as Jeff mentions too). > > >> > + if (instrumentation_clone > >> > + && !DECL_BY_REFERENCE (resdecl) > >> > + && restmp > >> > + && BOUNDED_P (restmp)) > >> > + { > >> > + tree fn = targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDRET); > >> > + gcall *retbnd = gimple_build_call (fn, 1, restmp); > >> > + > >> > + resbnd = create_tmp_reg (pointer_bounds_type_node, "retbnd"); > >> > + gimple_call_set_lhs (retbnd, resbnd); > >> > + > >> > + gsi_insert_after (&bsi, retbnd, GSI_NEW_STMT); > >> > + create_edge (get_create (fn), retbnd, callees->count, callees->frequency); > >> > + } > > > > I am not sure why we need to check here: Originaly we have two bounded functions, A and B. > > We turn function B to a wrapper of function A. If callers of bounded functions need > > to call a builtin, I would expect all callers of B to do it already, so I would expect > > that wrapper is safe here? > > The problem with instrumented call is that instrumented function > returns two values and call lhs gets only the first one. Thus we > generate bndret call to get the second one to build own return with > two values. I see, patch is OK then (preferably merging as much as possible with ipa-split) Honza > > > > > Or do we mix instrumented and non-instrumented versions somehow? > > > > Addding code handling return value is going to turn the call to non-tailcall, so you probably > > want to drop the tailcall flag, too. > > No, function still return what the last call return, thus may keep tailcall. > > Thanks, > Ilya > > > > > Honza
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index e640907..fc38e67 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1581,6 +1581,7 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk) int i; tree resdecl; tree restmp = NULL; + tree resbnd = NULL; gcall *call; greturn *ret; @@ -1697,6 +1698,21 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk) gsi_insert_after (&bsi, call, GSI_NEW_STMT); if (!alias_is_noreturn) { + if (instrumentation_clone + && !DECL_BY_REFERENCE (resdecl) + && restmp + && BOUNDED_P (restmp)) + { + tree fn = targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDRET); + gcall *retbnd = gimple_build_call (fn, 1, restmp); + + resbnd = create_tmp_reg (pointer_bounds_type_node, "retbnd"); + gimple_call_set_lhs (retbnd, resbnd); + + gsi_insert_after (&bsi, retbnd, GSI_NEW_STMT); + create_edge (get_create (fn), retbnd, callees->count, callees->frequency); + } + if (restmp && !this_adjusting && (fixed_offset || virtual_offset)) { @@ -1766,6 +1782,7 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk) ret = gimple_build_return (restmp); else ret = gimple_build_return (resdecl); + gimple_return_set_retbnd (ret, resbnd); gsi_insert_after (&bsi, ret, GSI_NEW_STMT); } diff --git a/gcc/testsuite/gcc.target/i386/thunk-retbnd.c b/gcc/testsuite/gcc.target/i386/thunk-retbnd.c new file mode 100644 index 0000000..d9bd031 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/thunk-retbnd.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-O2 -fcheck-pointer-bounds -mmpx -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "return &glob," 2 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + +int glob; + +int * +test1 (void) +{ + return &glob; +} + +int * +test2 (void) +{ + return test1 (); +}