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

Reply via email to