diff mbox

[CHKP] Support returned bounds in thunks expand

Message ID 20150306141531.GA27860@msticlxl57.ims.intel.com
State New
Headers show

Commit Message

Ilya Enkovich March 10, 2015, 10:12 a.m. UTC
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.

Comments

Ilya Enkovich April 2, 2015, 2:49 p.m. UTC | #1
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 ();
> +}
Jeff Law April 2, 2015, 7:42 p.m. UTC | #2
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
Jan Hubicka April 2, 2015, 8:55 p.m. UTC | #3
> 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
Ilya Enkovich April 3, 2015, 8:38 a.m. UTC | #4
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
>
Ilya Enkovich April 3, 2015, 8:45 a.m. UTC | #5
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
Jan Hubicka April 3, 2015, 5:05 p.m. UTC | #6
> 
> 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 mbox

Patch

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 ();
+}