[PATCH] Fix PR 40445: C++ ICE when using __builtin_unreachable() as only statement in a function.

David Daney ddaney@caviumnetworks.com
Thu Jun 25 02:24:00 GMT 2009


I am testing a different patch.  It should be less hacky.

David Daney


David Daney wrote:
> Ian Lance Taylor wrote:
>> David Daney <ddaney@caviumnetworks.com> writes:
>>
>>> Ian Lance Taylor wrote:
>>>> David Daney <ddaney@caviumnetworks.com> writes:
>>>>
>>>>> Index: cfgcleanup.c
>>>>> ===================================================================
>>>>> --- cfgcleanup.c    (revision 148867)
>>>>> +++ cfgcleanup.c    (working copy)
>>>>> @@ -1903,7 +1903,8 @@ try_optimize_cfg (int mode)
>>>>>            /* Note that forwarder_block_p true ensures that
>>>>>               there is a successor for this block.  */
>>>>>            && (single_succ_edge (b)->flags & EDGE_FALLTHRU)
>>>>> -          && n_basic_blocks > NUM_FIXED_BLOCKS + 1)
>>>>> +          && n_basic_blocks > NUM_FIXED_BLOCKS + 1
>>>>> +          && single_pred_edge (b)->src != ENTRY_BLOCK_PTR)
>>>> I don't see why this test is sufficient for what you are trying to
>>>> prevent.  It seems to me that this empty block could be followed by a
>>>> number of other blocks.
>>>>
>>> Let me try to explain the patch a little better.
>>>
>>> There are several parts of the rtl optimizers that cannot handle a
>>> function that contains zero basic blocks.  They include, but are not
>>> limited to: record_effective_endpoints and
>>> rest_of_handle_df_initialize.
>>>
>>> One approach would be to fix all of the issues related to such empty
>>> functions.  I considered doing that, but the patch was getting large,
>>> so I did this patch (which is admittedly a bit of a hack) instead.
>>>
>>> If we can prevent the first block of the function from being deleted,
>>> there will never be functions with zero basic blocks, and none of the
>>> related problems will be exposed.
>>>
>>> Certainly the empty first block could be followed by other non-empty
>>> blocks and the patch would prevent it from being removed.  But it is
>>> empty so no code results and the compiler output is not (in theory)
>>> changed.
>>
>> I think I got all that, but why not simply also test whether the
>> successor block is the exit block?  If it isn't, then it should be fine
>> to go ahead and delete the block.  Shouldn't it?
>>
> No.
> 
> Consider this:
> 
> ;; Function const char* f() (_Z1fv)
> 
> 
> ;; Generating RTL for gimple basic block 2
> 
> 
> ;;
> ;; Full RTL generated for this function:
> ;;
> (note 1 0 3 NOTE_INSN_DELETED)
> 
> (note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
> 
> (note 2 3 4 2 NOTE_INSN_FUNCTION_BEG)
> 
> (note 4 2 5 3 [bb 3] NOTE_INSN_BASIC_BLOCK)
> 
> (barrier 5 4 11)
> 
> (note 11 5 8 4 [bb 4] NOTE_INSN_BASIC_BLOCK)
> 
> (insn 8 11 9 4 
> /home/daney/gccsvn/t1/gcc/testsuite/g++.dg/other/builtin-unreachable-1.C:11 
> (clobber (reg/i:SI 0 ax)) -1 (nil))
> 
> (insn 9 8 6 4 
> /home/daney/gccsvn/t1/gcc/testsuite/g++.dg/other/builtin-unreachable-1.C:11 
> (clobber (reg:SI 58 [ <result> ])) -1 (nil))
> 
> (code_label 6 9 12 5 1 "" [0 uses])
> 
> (note 12 6 7 5 [bb 5] NOTE_INSN_BASIC_BLOCK)
> 
> (insn 7 12 10 5 
> /home/daney/gccsvn/t1/gcc/testsuite/g++.dg/other/builtin-unreachable-1.C:11 
> (set (reg/i:SI 0 ax)
>         (reg:SI 58 [ <result> ])) -1 (nil))
> 
> (insn 10 7 0 5 
> /home/daney/gccsvn/t1/gcc/testsuite/g++.dg/other/builtin-unreachable-1.C:11 
> (use (reg/i:SI 0 ax)) -1 (nil))
> 
> 
> In the eh pass bb-2 is removed as it is empty and falls through to bb-3. 
>  Then bb-3 is removed as it is empty and has no successor edges.  This 
> leaves us with the ENTRY_BLOCK having no successors.  Blocks 4 and 5 are 
>  unreachable and are also deleted.
> 
> So after the eh pass we are left with a function with zero basic blocks 
> and no edges.
> 
> There are many RTL passes that assume that the ENTRY_BLOCK has 
> successors.  I have patched up dfinit and outof_cfglayout to handle 
> this, but this pushes the ICE into ira...
> 
> In the case of a C program (instead of c++), into_cfglayout is the first 
> time try_optimize_cfg is called.  In this case the mode is 
> CLEANUP_CFGLAYOUT.  This prevents bb-2 from being removed, and bb-3 is 
> removed first.  This causes the logic to change.  By removing bb-3, bb-2 
> no longer has a successor and cannot be removed by the 
> empty-with-fall-through rule.  If bb-2 is never removed, the ENTRY_BLOCK 
> will have an outgoing edge and all the RTL passes are happy.
> 



More information about the Gcc-patches mailing list