[PATCH] Fix PR 40445: C++ ICE when using __builtin_unreachable() as only statement in a function.
David Daney
ddaney@caviumnetworks.com
Wed Jun 24 21:55:00 GMT 2009
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