On 11/26/13 14:41, Steven Bosscher wrote:

I suppose with "cruft" you mean the dead end in the CFG due to
builtin_unreachable, correct?
Yes.


If so, then I suppose you could also
just let cfgcleanup handle that cruft and not wait until
if-conversion.
But what does all this look like at the RTL level. A block resulting from __builtin_unreachable is just a block with no successors. So while we could clean it up in this case, I don't think we can in general.

ie, we might ahve:

   [ ... ]
   fubar ();
   __builtin_unreachable ();

Where the programmer is effectively asserting that fubar never returns.

So we have a block which calls fubar. The block would have no successors. And I think we're right back in the same situation. We're going to have a BARRIER after that block with no successors and ifcvt is going to muck things up tripping the checking failure.


Furthermore, ISTM, that while __builtin_unreachable is part of this instance of the problem, ultimately the core issue is that the ifcvt code doesn't properly handle cases where the converted blocks have no successors.




It still puzzles me what exactly the semantics __builtin_unreachable
are, but AFAIU, a basic block ending in __builtin_unreachable could go
anywhere (undefined behavior). So why do we emit a BARRIER after then
to begin with? Or why not even drop __builtin_unreachable completely
during expand? (It's caused me quite a lot of pain already:
__builtin_unreachable in the middle of a basic block confuses
find_many_sub_basic_blocks, there's a PR somewhere with my name on
it...).
I believe __builtin_unreachable is fundamentally broken, but I'm not really up for arguing with Jakub about it right now :(


Your understanding is basically correct. The barrier exists because __builtin_unreachable, when we convert to RTL is "emit_barrier()". Nothing more, nothing less. You can't directly see a __builtin_unreachable at the RTL level.

Arguably it could be dropped, as we expand, but then you drop useful information from the CFG. Namely that certain blocks of code never rejoin the main control flow. ie, once you're on that path, you're going to hang, abort/exit and the like. Thus you don't need edges from those paths back to the main stream.


Hacking BARRIERs by hand in a function that's supposed to know about
the CFG just seems wrong :-(
Open to other suggestions. The fundamental issue is BARRIERs live outside the CFG. So a pass that thinks it can manipulate the CFG and ignore the underlying RTL are going to have problems with things like this.

Jeff

Reply via email to