On 01/03/2013 12:01 PM, Steven Bosscher wrote:
Hello,
Consider the following test case:
void bar (void);
int foo (int b, int c, int d)
{
int r = 0;
if (b)
res = b * 2 + 4;
if (c)
{
if (d)
r = res;
else
__builtin_unreachable ();
}
return r;
}
This is typical for code in GCC itself in places where
gcc_unreachable() is used.
The corresponding CFG looks like this:
+-----+
| bb0 |
+-----+
|
|
v
+-----+
| bb2 | -+
+-----+ |
| |
| |
v |
+-----+ |
| bb3 | |
+-----+ |
| |
| |
v |
+-----+ +-----+ |
| bb8 | <-- | bb4 | <+
+-----+ +-----+
| |
| |
| v
| +-----+ +-----+
| | bb5 | --> | bb7 |
| +-----+ +-----+
| |
| |
| v
| +-----+
| | bb6 |
| +-----+
| |
| |
| v
| +-----+
+-------> | bb9 |
+-----+
|
|
v
+-----+
| bb1 |
+-----+
Presumably BB7 was created in response to the builtin_unreachable? One
could argue that an empty dead-end basic block should just be removed
and the CFG appropriately simplified.
You might want to look at a discussion from Oct/Nov 2011 "New pass to
delete unexecutable paths in the CFG" which touches on some of this
stuff. It's not 100% the same, but the concept of eliminating edges
from the CFG which we can never traverse in a conforming program applies
to both your example and the stuff I was playing with.
jeff