https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86912
Bug ID: 86912 Summary: Function pointer imposes an optimization barrier Product: gcc Version: 9.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: antoshkka at gmail dot com Target Milestone: --- Consider the following minimized example of std::variant visitation: struct A {}; struct B : A {}; struct C : A {}; struct D : A {}; struct E : A {}; struct X : A {}; template <class T> struct helper { static A& call(void* value) { return *static_cast<T*>(value); } }; A& get_base(int index, void* value) { using f_ptr = A&(*)(void*); constexpr f_ptr visitors[] = { helper<A>::call, helper<B>::call, helper<C>::call, helper<D>::call, helper<E>::call, helper<X>::call, }; return visitors[index](value); } For the above code GCC generates very suboptimal assembly that fills an array with pointers and does the jmp: <...> get_base(int, void*): mov QWORD PTR [rsp-56], OFFSET FLAT:(anonymous namespace)::helper<A>::call(void*) movsx rax, edi mov rdi, rsi mov QWORD PTR [rsp-48], OFFSET FLAT:(anonymous namespace)::helper<B>::call(void*) mov QWORD PTR [rsp-40], OFFSET FLAT:(anonymous namespace)::helper<C>::call(void*) mov QWORD PTR [rsp-32], OFFSET FLAT:(anonymous namespace)::helper<D>::call(void*) mov QWORD PTR [rsp-24], OFFSET FLAT:(anonymous namespace)::helper<E>::call(void*) mov QWORD PTR [rsp-16], OFFSET FLAT:(anonymous namespace)::helper<X>::call(void*) mov rax, QWORD PTR [rsp-56+rax*8] jmp rax Optimal assembly should be the following: get_base(int, void*): mov rax, rsi ret If we rewrite `get_base` to avoid calls by function pointer, the assembly becomes optimal: A& get_base(int index, void* value) { if (index == 0) return helper<A>::call(value); if (index == 1) return helper<B>::call(value); if (index == 2) return helper<C>::call(value); if (index == 3) return helper<D>::call(value); if (index == 4) return helper<E>::call(value); if (index == 5) return helper<X>::call(value); }