[Bug tree-optimization/79472] New: x86-64: Switch table generation fails if default case has different code
yuriks at yuriks dot net
gcc-bugzilla@gcc.gnu.org
Sun Feb 12 02:40:00 GMT 2017
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79472
Bug ID: 79472
Summary: x86-64: Switch table generation fails if default case
has different code
Product: gcc
Version: 7.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: yuriks at yuriks dot net
Target Milestone: ---
Consider the following code, compiled at -O2: (Compiler explorer link:
https://godbolt.org/g/GljuJt)
#include <cstdint>
#include <cstdio>
#include <cstdlib>
void frobulate(uint32_t v) {
const char* s;
switch (v) {
case 0:
s = "foo";
break;
case 1:
s = "bar";
break;
case 2:
s = "spam";
break;
default:
abort();
break;
}
printf("%s\n", s);
}
void frobulate_for_gcc(uint32_t v) {
const char* s;
switch (v) {
case 0:
s = "foo";
break;
case 1:
s = "bar";
break;
case 2:
s = "spam";
break;
default:
s = nullptr;
break;
}
if (s == nullptr) {
abort();
}
printf("%s\n", s);
}
------------------------------------------------------------------------------
gcc 6.3 produces the following code. It fails to generate a data table in
"frobulate", even though it it doing a branch beforehand that could be used to
insert the abort into. If I add the indirection of checking for the null
pointer instead then the check is actually hoisted up into the range check for
the table:
frobulate(unsigned int):
cmp edi, 1
je .L3
jb .L4
cmp edi, 2
jne .L12
mov edi, OFFSET FLAT:.LC2
jmp puts
.L12:
sub rsp, 8
call abort
.L4:
mov edi, OFFSET FLAT:.LC0
jmp puts
.L3:
mov edi, OFFSET FLAT:.LC1
jmp puts
frobulate_for_gcc(unsigned int):
cmp edi, 2
jbe .L18
.L14:
sub rsp, 8
call abort
.L18:
mov edi, edi
mov rdi, QWORD PTR CSWTCH.2[0+rdi*8]
test rdi, rdi
je .L14
jmp puts
CSWTCH.2:
.quad .LC0
.quad .LC1
.quad .LC2
------------------------------------------------------------------------------
gcc 7 (20170211) appears to regress further, it fails to generate a table in
both cases:
frobulate(unsigned int):
cmp edi, 1
je .L3
jb .L4
cmp edi, 2
jne .L12
mov edi, OFFSET FLAT:.LC2
jmp puts
.L4:
mov edi, OFFSET FLAT:.LC0
jmp puts
.L3:
mov edi, OFFSET FLAT:.LC1
jmp puts
.L12:
sub rsp, 8
call abort
------------------------------------------------------------------------------
For comparison, clang 3.9.1 generates optimal code in both instances:
frobulate(unsigned int): # @frobulate(unsigned int)
cmp edi, 3
jae .LBB0_1
movsxd rax, edi
mov rdi, qword ptr [8*rax + .Lswitch.table.4]
jmp puts # TAILCALL
.LBB0_1:
push rax
call abort
frobulate_for_gcc(unsigned int): # @frobulate_for_gcc(unsigned
int)
cmp edi, 3
jae .LBB1_1
movsxd rax, edi
mov rdi, qword ptr [8*rax + .Lswitch.table.4]
jmp puts # TAILCALL
.LBB1_1:
push rax
call abort
More information about the Gcc-bugs
mailing list