Bug 58774 - tree-switch-conversion doesn't optimize with content in default scase
Summary: tree-switch-conversion doesn't optimize with content in default scase
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.8.3
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2013-10-18 00:54 UTC by Ben Maurer
Modified: 2018-09-26 12:54 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work: 8.2.0, 9.0
Known to fail:
Last reconfirmed: 2013-10-18 00:00:00


Attachments
Example program (165 bytes, text/plain)
2013-10-18 00:54 UTC, Ben Maurer
Details
appers-fixed (675 bytes, text/plain)
2017-11-07 14:02 UTC, Shawn Landden
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ben Maurer 2013-10-18 00:54:34 UTC
Created attachment 31028 [details]
Example program

In cases where the default fallback path executes code, gcc does not appear to convert a switch statement into an array access. In the attached example, running gcc opt.c -O3 -fdump-tree-all, bug.c.032t.switchconv shows

;; Function switchwithprint...
Bailing out - bad case - a non-final BB not empty

;; Function switchwithnoprint...
Switch converted
Comment 1 Richard Biener 2013-10-18 08:18:38 UTC
Confirmed, but how do you expect the transform to look like in this case?
Comment 2 Ben Maurer 2013-10-18 17:18:35 UTC
I think there might be multiple appropriate transformations. In the switchwithnoprint example I attached, it is currently compiled as:

<switchwithnoprint>:
sub    $0x1,%edi
xor    %eax,%eax
cmp    $0x5,%edi
ja     RETURN
mov    0x400740(,%rdi,4),%eax
RETURN: repz retq

A good transformation for the switchwithprint function might be to make the RETURN label do the printf. On the other hand, the switch case with a non-trivial function might not be as clean as this. Eg, you could have:

switch(val) {
  case 1: return 1;
  case 2: return 2;
  case 3: printf("hello");
  case 4: return 4;
}

In this case you could do something like:

struct {
  bool is_code;
  union {int ret; void* jmp};
} actions[] = ...
if (val >= 1 && val <= 4) {
  auto action = actions[val];
  if (action.is_code) goto action.jmp;
  else return action.ret;
}

In theory, you might even be able to avoid having the is_code value if you knew that the ret and jmp values never overlapped (eg, if (action > MAX_POSSIBLE_RETURN_VALUE) goto (void*) action).
Comment 3 camille 2013-11-20 23:55:31 UTC
Facebook posted a $100 bounty on this issue via Bountysource:
https://www.bountysource.com/issues/1326594
Comment 4 Shawn Landden 2017-11-07 14:02:48 UTC
Created attachment 42556 [details]
appers-fixed
Comment 5 Shawn Landden 2017-11-07 14:03:04 UTC
Appears fixed
Comment 6 Martin Liška 2018-09-26 12:54:10 UTC
Fixed on trunk in r247538, which means Jakub Jelínek should be given $100.
Closing as fixed.