https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98649
Bug ID: 98649
Summary: Trivial jump table not eliminated
Product: gcc
Version: 11.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: pdimov at gmail dot com
Target Milestone: ---
Trivial jump tables where all entries are the same are sometimes not
eliminated. E.g. the following example
```
struct Base { virtual void run( float f ) = 0; };
struct T0: Base { void run( float f ); };
struct T1: Base { void run( float f ); };
struct T2: Base { void run( float f ); };
struct T3: Base { void run( float f ); };
struct T4: Base { void run( float f ); };
template<int I> struct mp_int {};
struct variant
{
unsigned index_;
union
{
T0 t0_;
T1 t1_;
T2 t2_;
T3 t3_;
T4 t4_;
};
T0& get( mp_int<0> ) { return t0_; }
T1& get( mp_int<1> ) { return t1_; }
T2& get( mp_int<2> ) { return t2_; }
T3& get( mp_int<3> ) { return t3_; }
T4& get( mp_int<4> ) { return t4_; }
};
template<int I> decltype(auto) get( variant& v )
{
return v.get( mp_int<I>() );
}
void f1( variant& v, float f )
{
switch( v.index_ )
{
case 0: get<0>(v).run( f ); break;
case 1: get<1>(v).run( f ); break;
case 2: get<2>(v).run( f ); break;
case 3: get<3>(v).run( f ); break;
case 4: get<4>(v).run( f ); break;
default: __builtin_unreachable();
}
}
```
(https://godbolt.org/z/MxzGh8)
results in
```
f1(variant&, float):
mov eax, DWORD PTR [rdi]
lea r8, [rdi+8]
jmp [QWORD PTR .L4[0+rax*8]]
.L4:
.quad .L3
.quad .L3
.quad .L3
.quad .L3
.quad .L3
.L3:
mov rax, QWORD PTR [rdi+8]
mov rdi, r8
mov rax, QWORD PTR [rax]
jmp rax
```
This case may seem contrived, but it's not that rare in practice, because code
using std::variant or equivalent (such as Boost.Variant2, from which the
example has been reduced) is becoming more and more common nowadays.