[Bug middle-end/86909] New: Missing common subexpression elimination for types other than int

antoshkka at gmail dot com gcc-bugzilla@gcc.gnu.org
Fri Aug 10 10:50:00 GMT 2018


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86909

            Bug ID: 86909
           Summary: Missing common subexpression elimination for types
                    other than int
           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 the std::variant visitation:

using size_t = unsigned long long;

struct A {};
static const size_t variant_npos = -1;

struct variant {
    A a;

    using __index_type = unsigned char; // !!!!
    __index_type _M_index;

    size_t index() const noexcept {
            return (_M_index == __index_type(variant_npos) ? variant_npos :
_M_index);
    }
};

template<size_t _Np>
static A* get_if(variant* __ptr) noexcept {
    return (__ptr->index() == _Np ? &__ptr->a : nullptr);
}

A* foo(variant& in) {
    int i = in.index();
    if (i==0) return get_if<0>(&in);
    if (i==1) return get_if<1>(&in);
    if (i==2) return get_if<2>(&in);
    if (i==3) return get_if<3>(&in);
    if (i==4) return get_if<4>(&in);
    if (i==5) return get_if<5>(&in);
    if (i==6) return get_if<6>(&in);

    return get_if<7>(&in);
}


GCC generates assembly with multiple comparisons:
foo(variant&):
<...>
        cmp     ecx, 1
        je      .L4
        cmp     ecx, 2
        je      .L4
        cmp     ecx, 3
        je      .L4
        cmp     ecx, 4
        je      .L4
        cmp     ecx, 5
        je      .L4
        cmp     ecx, 6
        je      .L4
        cmp     dl, 7
        je      .L4

Clang eliminates the subexpressions:
foo(variant&):                        # @foo(variant&)
        movzx   ecx, byte ptr [rdi + 1]
        cmp     cl, -1
        mov     edx, -1
        cmovne  edx, ecx
        cmp     edx, 7
        jb      .LBB0_2
        mov     dl, 7
.LBB0_2:
        xor     eax, eax
        cmp     cl, dl
        cmove   rax, rdi
        ret


Note that if we change `__index_type` to `int` then GCC generates great
assembly:
foo(variant&):
        mov     edx, DWORD PTR [rdi+4]
        xor     eax, eax
        cmp     edx, -1
        je      .L1
        cmp     edx, 7
        cmovbe  rax, rdi
.L1:
        ret


More information about the Gcc-bugs mailing list