[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