diff mbox

Fix libgo breakage (PR tree-optimization/67284)

Message ID 20150821105233.GJ2729@redhat.com
State New
Headers show

Commit Message

Marek Polacek Aug. 21, 2015, 10:52 a.m. UTC
This fixes the libgo breakage.  Seems I really should have removed the
edge after we split the block with null dereference after __builtin_trap 
statement so that it's unreachable.

Bootstrapped/regtested on x86_64-linux + ppc64-linux + bootstrapped on
aarch64-linux, ok for trunk?

2015-08-21  Marek Polacek  <polacek@redhat.com>

	PR tree-optimization/67284
	* gimple-ssa-isolate-paths.c (insert_trap): Remove the edge after
	we split a block.


	Marek

Comments

Richard Biener Aug. 21, 2015, 11:27 a.m. UTC | #1
On Fri, Aug 21, 2015 at 12:52 PM, Marek Polacek <polacek@redhat.com> wrote:
> This fixes the libgo breakage.  Seems I really should have removed the
> edge after we split the block with null dereference after __builtin_trap
> statement so that it's unreachable.
>
> Bootstrapped/regtested on x86_64-linux + ppc64-linux + bootstrapped on
> aarch64-linux, ok for trunk?

Hum.  I don't see why this is needed - CFG cleanup (which of course needs
to run!) should do this for you.  In fact stray unreachable blocks are usually
more of a problem.

Richard.

> 2015-08-21  Marek Polacek  <polacek@redhat.com>
>
>         PR tree-optimization/67284
>         * gimple-ssa-isolate-paths.c (insert_trap): Remove the edge after
>         we split a block.
>
> diff --git gcc/gimple-ssa-isolate-paths.c gcc/gimple-ssa-isolate-paths.c
> index ca2322d..5ac61d3 100644
> --- gcc/gimple-ssa-isolate-paths.c
> +++ gcc/gimple-ssa-isolate-paths.c
> @@ -115,7 +115,8 @@ insert_trap (gimple_stmt_iterator *si_p, tree op)
>    else
>      gsi_insert_before (si_p, seq, GSI_NEW_STMT);
>
> -  split_block (gimple_bb (new_stmt), new_stmt);
> +  edge e = split_block (gimple_bb (new_stmt), new_stmt);
> +  remove_edge (e);
>    *si_p = gsi_for_stmt (stmt);
>  }
>
>
>         Marek
Marek Polacek Aug. 21, 2015, 12:49 p.m. UTC | #2
On Fri, Aug 21, 2015 at 01:27:43PM +0200, Richard Biener wrote:
> On Fri, Aug 21, 2015 at 12:52 PM, Marek Polacek <polacek@redhat.com> wrote:
> > This fixes the libgo breakage.  Seems I really should have removed the
> > edge after we split the block with null dereference after __builtin_trap
> > statement so that it's unreachable.
> >
> > Bootstrapped/regtested on x86_64-linux + ppc64-linux + bootstrapped on
> > aarch64-linux, ok for trunk?
> 
> Hum.  I don't see why this is needed - CFG cleanup (which of course needs
> to run!) should do this for you.  In fact stray unreachable blocks are usually
> more of a problem.

Aha.  It seems cleanup does that if I change the code to generate
__builtin_unreachable instead of __builtin_trap.  A hint maybe? ;)

What's going on here is that we find a potential NULL dereference
(PHI argument has NULL), we call isolate_path, that duplicates a bb
and then cuts off the outgoing edges of this duplicated bb.  And in
some cases it leaves COND_EXPR at the end of the bb -> ICE.
The we insert __builtin_trap on this isolated path.

	Marek
Richard Biener Aug. 21, 2015, 1:37 p.m. UTC | #3
On Fri, Aug 21, 2015 at 2:49 PM, Marek Polacek <polacek@redhat.com> wrote:
> On Fri, Aug 21, 2015 at 01:27:43PM +0200, Richard Biener wrote:
>> On Fri, Aug 21, 2015 at 12:52 PM, Marek Polacek <polacek@redhat.com> wrote:
>> > This fixes the libgo breakage.  Seems I really should have removed the
>> > edge after we split the block with null dereference after __builtin_trap
>> > statement so that it's unreachable.
>> >
>> > Bootstrapped/regtested on x86_64-linux + ppc64-linux + bootstrapped on
>> > aarch64-linux, ok for trunk?
>>
>> Hum.  I don't see why this is needed - CFG cleanup (which of course needs
>> to run!) should do this for you.  In fact stray unreachable blocks are usually
>> more of a problem.
>
> Aha.  It seems cleanup does that if I change the code to generate
> __builtin_unreachable instead of __builtin_trap.  A hint maybe? ;)

Not really...

static bool
cleanup_control_flow_bb (basic_block bb)
{
...
  /* Check for indirect calls that have been turned into
     noreturn calls.  */
  else if (is_gimple_call (stmt)
           && gimple_call_noreturn_p (stmt)
           && remove_fallthru_edge (bb->succs))
    retval = true;

and __builtin_trap is NORETURN.  But there is the hint where to debug.

Richard.

> What's going on here is that we find a potential NULL dereference
> (PHI argument has NULL), we call isolate_path, that duplicates a bb
> and then cuts off the outgoing edges of this duplicated bb.  And in
> some cases it leaves COND_EXPR at the end of the bb -> ICE.
> The we insert __builtin_trap on this isolated path.
>
>         Marek
Marek Polacek Aug. 21, 2015, 2:41 p.m. UTC | #4
On Fri, Aug 21, 2015 at 03:37:38PM +0200, Richard Biener wrote:
> On Fri, Aug 21, 2015 at 2:49 PM, Marek Polacek <polacek@redhat.com> wrote:
> > On Fri, Aug 21, 2015 at 01:27:43PM +0200, Richard Biener wrote:
> >> On Fri, Aug 21, 2015 at 12:52 PM, Marek Polacek <polacek@redhat.com> wrote:
> >> > This fixes the libgo breakage.  Seems I really should have removed the
> >> > edge after we split the block with null dereference after __builtin_trap
> >> > statement so that it's unreachable.
> >> >
> >> > Bootstrapped/regtested on x86_64-linux + ppc64-linux + bootstrapped on
> >> > aarch64-linux, ok for trunk?
> >>
> >> Hum.  I don't see why this is needed - CFG cleanup (which of course needs
> >> to run!) should do this for you.  In fact stray unreachable blocks are usually
> >> more of a problem.
> >
> > Aha.  It seems cleanup does that if I change the code to generate
> > __builtin_unreachable instead of __builtin_trap.  A hint maybe? ;)
> 
> Not really...
> 
> static bool
> cleanup_control_flow_bb (basic_block bb)
> {
> ...
>   /* Check for indirect calls that have been turned into
>      noreturn calls.  */
>   else if (is_gimple_call (stmt)
>            && gimple_call_noreturn_p (stmt)
>            && remove_fallthru_edge (bb->succs))
>     retval = true;
> 
> and __builtin_trap is NORETURN.  But there is the hint where to debug.

Yes, but gimple_call_noreturn_p is false on __builtin_trap.  That's quite
confusing... but flags_from_decl_or_type really returns 0 for __builtin_trap.

So can't we use __builtin_unreachable in isolate-path code?

	Marek
Jeff Law Aug. 21, 2015, 2:42 p.m. UTC | #5
On 08/21/2015 08:41 AM, Marek Polacek wrote:
> On Fri, Aug 21, 2015 at 03:37:38PM +0200, Richard Biener wrote:
>> On Fri, Aug 21, 2015 at 2:49 PM, Marek Polacek <polacek@redhat.com> wrote:
>>> On Fri, Aug 21, 2015 at 01:27:43PM +0200, Richard Biener wrote:
>>>> On Fri, Aug 21, 2015 at 12:52 PM, Marek Polacek <polacek@redhat.com> wrote:
>>>>> This fixes the libgo breakage.  Seems I really should have removed the
>>>>> edge after we split the block with null dereference after __builtin_trap
>>>>> statement so that it's unreachable.
>>>>>
>>>>> Bootstrapped/regtested on x86_64-linux + ppc64-linux + bootstrapped on
>>>>> aarch64-linux, ok for trunk?
>>>>
>>>> Hum.  I don't see why this is needed - CFG cleanup (which of course needs
>>>> to run!) should do this for you.  In fact stray unreachable blocks are usually
>>>> more of a problem.
>>>
>>> Aha.  It seems cleanup does that if I change the code to generate
>>> __builtin_unreachable instead of __builtin_trap.  A hint maybe? ;)
>>
>> Not really...
>>
>> static bool
>> cleanup_control_flow_bb (basic_block bb)
>> {
>> ...
>>    /* Check for indirect calls that have been turned into
>>       noreturn calls.  */
>>    else if (is_gimple_call (stmt)
>>             && gimple_call_noreturn_p (stmt)
>>             && remove_fallthru_edge (bb->succs))
>>      retval = true;
>>
>> and __builtin_trap is NORETURN.  But there is the hint where to debug.
>
> Yes, but gimple_call_noreturn_p is false on __builtin_trap.  That's quite
> confusing... but flags_from_decl_or_type really returns 0 for __builtin_trap.
>
> So can't we use __builtin_unreachable in isolate-path code?
No, we really want the trap to halt execution rather than executing 
whatever code is following in the instruction stream.  The latter is a 
significant security problem.



jeff
Jeff Law Aug. 21, 2015, 3:09 p.m. UTC | #6
On 08/21/2015 08:41 AM, Marek Polacek wrote:
> On Fri, Aug 21, 2015 at 03:37:38PM +0200, Richard Biener wrote:
>> On Fri, Aug 21, 2015 at 2:49 PM, Marek Polacek <polacek@redhat.com> wrote:
>>> On Fri, Aug 21, 2015 at 01:27:43PM +0200, Richard Biener wrote:
>>>> On Fri, Aug 21, 2015 at 12:52 PM, Marek Polacek <polacek@redhat.com> wrote:
>>>>> This fixes the libgo breakage.  Seems I really should have removed the
>>>>> edge after we split the block with null dereference after __builtin_trap
>>>>> statement so that it's unreachable.
>>>>>
>>>>> Bootstrapped/regtested on x86_64-linux + ppc64-linux + bootstrapped on
>>>>> aarch64-linux, ok for trunk?
>>>>
>>>> Hum.  I don't see why this is needed - CFG cleanup (which of course needs
>>>> to run!) should do this for you.  In fact stray unreachable blocks are usually
>>>> more of a problem.
>>>
>>> Aha.  It seems cleanup does that if I change the code to generate
>>> __builtin_unreachable instead of __builtin_trap.  A hint maybe? ;)
>>
>> Not really...
>>
>> static bool
>> cleanup_control_flow_bb (basic_block bb)
>> {
>> ...
>>    /* Check for indirect calls that have been turned into
>>       noreturn calls.  */
>>    else if (is_gimple_call (stmt)
>>             && gimple_call_noreturn_p (stmt)
>>             && remove_fallthru_edge (bb->succs))
>>      retval = true;
>>
>> and __builtin_trap is NORETURN.  But there is the hint where to debug.
>
> Yes, but gimple_call_noreturn_p is false on __builtin_trap.  That's quite
> confusing... but flags_from_decl_or_type really returns 0 for __builtin_trap.
Well, if that's intentional (and offhand I have no idea if it is), then 
you could emit a __builtin_trap followed by a __builtin_unreachable.

jeff
Richard Biener Aug. 21, 2015, 4:21 p.m. UTC | #7
On August 21, 2015 5:09:46 PM GMT+02:00, Jeff Law <law@redhat.com> wrote:
>On 08/21/2015 08:41 AM, Marek Polacek wrote:
>> On Fri, Aug 21, 2015 at 03:37:38PM +0200, Richard Biener wrote:
>>> On Fri, Aug 21, 2015 at 2:49 PM, Marek Polacek <polacek@redhat.com>
>wrote:
>>>> On Fri, Aug 21, 2015 at 01:27:43PM +0200, Richard Biener wrote:
>>>>> On Fri, Aug 21, 2015 at 12:52 PM, Marek Polacek
><polacek@redhat.com> wrote:
>>>>>> This fixes the libgo breakage.  Seems I really should have
>removed the
>>>>>> edge after we split the block with null dereference after
>__builtin_trap
>>>>>> statement so that it's unreachable.
>>>>>>
>>>>>> Bootstrapped/regtested on x86_64-linux + ppc64-linux +
>bootstrapped on
>>>>>> aarch64-linux, ok for trunk?
>>>>>
>>>>> Hum.  I don't see why this is needed - CFG cleanup (which of
>course needs
>>>>> to run!) should do this for you.  In fact stray unreachable blocks
>are usually
>>>>> more of a problem.
>>>>
>>>> Aha.  It seems cleanup does that if I change the code to generate
>>>> __builtin_unreachable instead of __builtin_trap.  A hint maybe? ;)
>>>
>>> Not really...
>>>
>>> static bool
>>> cleanup_control_flow_bb (basic_block bb)
>>> {
>>> ...
>>>    /* Check for indirect calls that have been turned into
>>>       noreturn calls.  */
>>>    else if (is_gimple_call (stmt)
>>>             && gimple_call_noreturn_p (stmt)
>>>             && remove_fallthru_edge (bb->succs))
>>>      retval = true;
>>>
>>> and __builtin_trap is NORETURN.  But there is the hint where to
>debug.
>>
>> Yes, but gimple_call_noreturn_p is false on __builtin_trap.  That's
>quite
>> confusing... but flags_from_decl_or_type really returns 0 for
>__builtin_trap.
>Well, if that's intentional (and offhand I have no idea if it is), then
>
>you could emit a __builtin_trap followed by a __builtin_unreachable.

Looking at builtins.def I'd say it should be no return.

Richard.

>jeff
Richard Biener Aug. 21, 2015, 4:23 p.m. UTC | #8
On August 21, 2015 5:09:46 PM GMT+02:00, Jeff Law <law@redhat.com> wrote:
>On 08/21/2015 08:41 AM, Marek Polacek wrote:
>> On Fri, Aug 21, 2015 at 03:37:38PM +0200, Richard Biener wrote:
>>> On Fri, Aug 21, 2015 at 2:49 PM, Marek Polacek <polacek@redhat.com>
>wrote:
>>>> On Fri, Aug 21, 2015 at 01:27:43PM +0200, Richard Biener wrote:
>>>>> On Fri, Aug 21, 2015 at 12:52 PM, Marek Polacek
><polacek@redhat.com> wrote:
>>>>>> This fixes the libgo breakage.  Seems I really should have
>removed the
>>>>>> edge after we split the block with null dereference after
>__builtin_trap
>>>>>> statement so that it's unreachable.
>>>>>>
>>>>>> Bootstrapped/regtested on x86_64-linux + ppc64-linux +
>bootstrapped on
>>>>>> aarch64-linux, ok for trunk?
>>>>>
>>>>> Hum.  I don't see why this is needed - CFG cleanup (which of
>course needs
>>>>> to run!) should do this for you.  In fact stray unreachable blocks
>are usually
>>>>> more of a problem.
>>>>
>>>> Aha.  It seems cleanup does that if I change the code to generate
>>>> __builtin_unreachable instead of __builtin_trap.  A hint maybe? ;)
>>>
>>> Not really...
>>>
>>> static bool
>>> cleanup_control_flow_bb (basic_block bb)
>>> {
>>> ...
>>>    /* Check for indirect calls that have been turned into
>>>       noreturn calls.  */
>>>    else if (is_gimple_call (stmt)
>>>             && gimple_call_noreturn_p (stmt)
>>>             && remove_fallthru_edge (bb->succs))
>>>      retval = true;
>>>
>>> and __builtin_trap is NORETURN.  But there is the hint where to
>debug.
>>
>> Yes, but gimple_call_noreturn_p is false on __builtin_trap.  That's
>quite
>> confusing... but flags_from_decl_or_type really returns 0 for
>__builtin_trap.
>Well, if that's intentional (and offhand I have no idea if it is), then
>
>you could emit a __builtin_trap followed by a __builtin_unreachable.

But maybe go is non-call-exceptions  and that makes a difference?

>jeff
diff mbox

Patch

diff --git gcc/gimple-ssa-isolate-paths.c gcc/gimple-ssa-isolate-paths.c
index ca2322d..5ac61d3 100644
--- gcc/gimple-ssa-isolate-paths.c
+++ gcc/gimple-ssa-isolate-paths.c
@@ -115,7 +115,8 @@  insert_trap (gimple_stmt_iterator *si_p, tree op)
   else
     gsi_insert_before (si_p, seq, GSI_NEW_STMT);
 
-  split_block (gimple_bb (new_stmt), new_stmt);
+  edge e = split_block (gimple_bb (new_stmt), new_stmt);
+  remove_edge (e);
   *si_p = gsi_for_stmt (stmt);
 }