Bug 65922 - Switch statement with __builtin_unreachable creates a wild branch
Summary: Switch statement with __builtin_unreachable creates a wild branch
Status: CLOSED DUPLICATE of bug 51513
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 6.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-04-29 01:28 UTC by Peter Bergner
Modified: 2015-04-29 02:21 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work: 4.7.0
Known to fail: 4.8.0, 4.9.0, 5.1.0, 6.0
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Peter Bergner 2015-04-29 01:28:41 UTC
The following test case compiled with -O2 creates a wild branch when it generates the branch to the switch's "default" leg.  On both POWER and x86_64 (maybe others), it generates a branch with a label just past the last instruction in the function.

POWER:

  .L.foo:
	cmplwi 7,4,6
	bgt 7,.L2
  [snip]
	blr
	.p2align 4,,15
  .L2:
	.long 0

X86_64:

  foo:
  .LFB0:
        .cfi_startproc
        cmpl    $6, %esi
        ja      .L2
  [snip]
        ret
        .p2align 4,,10
        .p2align 3
  .L2:
        .cfi_endproc
  .LFE0:
        .size   foo, .-foo

My guess is that since we've stated that the default leg is unreachable, we should probably just delete the branch altogether, rather than allowing it to branch into nowhere.  I'll note that I see the same behavior from GCC 4.8 thru trunk.  The code from GCC 4.7 and earlier looks ok.
Comment 1 Peter Bergner 2015-04-29 01:33:08 UTC
The last tree dump looks ok to me:

foo (unsigned char * ptr, unsigned int cond)
{
  unsigned char _5;
  unsigned char _6;
  unsigned char _8;
  unsigned char _9;

  <bb 2>:
  switch (cond_2(D)) <default: <L7>, case 0: <L9>, case 1 ... 4: <L1>, case 5: <L6>, case 6: <L1>>

<L1>:
  _5 = *ptr_4(D);
  _6 = _5 + 1;
  *ptr_4(D) = _6;
  goto <bb 6> (<L9>);

<L6>:
  _8 = *ptr_4(D);
  _9 = _8 + 2;
  *ptr_4(D) = _9;
  goto <bb 6> (<L9>);

<L7>:
  __builtin_unreachable ();

<L9>:
  return;

}

But the first rtl code after expand looks suspect to me.
Comment 2 Andrew Pinski 2015-04-29 01:46:21 UTC
Dup of bug 51513.

*** This bug has been marked as a duplicate of bug 51513 ***
Comment 3 Peter Bergner 2015-04-29 02:21:34 UTC
Closing as a DUP.  I forgot to include the test case, so for posterity, here is the test case reduced from PHP.

void
foo (unsigned char *ptr, unsigned int cond)
{
  switch (cond)
    {
    case 0:
      return;
    case 1:
    case 2:
    case 3:
    case 4:
    case 6:
      *ptr += 1;
      return;
    case 5:
      *ptr += 2;
      return;
    default:
      __builtin_unreachable ();
      break;
    }
}