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
Confirmed, but how do you expect the transform to look like in this case?
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).
Facebook posted a $100 bounty on this issue via Bountysource: https://www.bountysource.com/issues/1326594
Created attachment 42556 [details] appers-fixed
Appears fixed
Fixed on trunk in r247538, which means Jakub Jelínek should be given $100. Closing as fixed.