[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