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.

Reply via email to