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

            Bug ID: 93940
           Summary: crazy codegen bug on Og with builtin_constant_p,
                    coverage, and pthread
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: barry.revzin at gmail dot com
  Target Milestone: ---

This holds for gcc 8.x, 9.x, and trunk. The following program (thanks,
creduce):

using uint16_t = unsigned short;

struct a {
    uint16_t b = 0;
};
struct c {
    short d;
};
class e {
public:
    void f();
    void init_session(c);
};

#ifdef ADD_CONSTEXPR
#define CONSTEXPR constexpr
#else
#define CONSTEXPR
#endif

auto htons = [](uint16_t s) {
    if CONSTEXPR (__builtin_constant_p(s)) {
        return uint16_t(uint16_t(s >> 8) | uint16_t(s << 8));
    } else {
        return uint16_t(uint16_t(s >> 8) | uint16_t(s << 8));
    }
};

struct g {
    e h;
    void i(a k) {
        h.f();
        auto j = c();
        j.d = htons(k.b);
        h.init_session(j);
    }
};

void test() {
    g().i({});
}

The htons lambda is mimicking the htons macro, which leads with the
__builtin_constant_p check before doing either a different builtin or direct
asm. In this case, the __builtin_constant_p appears to be significant but the
rest not so much.

When compiling the above with -std=c++17 -Og -pthread --coverage, the generated
asm for test() is:

test():
        sub     rsp, 24
        lock add        QWORD PTR __gcov0.test()[rip], 1
        lock add        QWORD PTR __gcov0._ZN1g1iE1a[rip], 1
        lea     rdi, [rsp+15]
        call    e::f()

That's it. It only calls f(), there is no call to init_session(). 

On the other hand, when compiling the above with -std=c++17 -Og -pthread
--coverage -DADD_CONSTEXPR, the generated asm for test() is:

test():
        sub     rsp, 24
        lock add        QWORD PTR __gcov0.test()[rip], 1
        lock add        QWORD PTR __gcov0._ZN1g1iE1a[rip], 1
        lea     rdi, [rsp+15]
        call    e::f()
        lock add        QWORD PTR __gcov0._ZN1g1iE1a[rip+8], 1
        mov     esi, 0
        lea     rdi, [rsp+15]
        call    e::init_session(c)
        lock add        QWORD PTR __gcov0._ZN1g1iE1a[rip+16], 1
        lock add        QWORD PTR __gcov0.test()[rip+8], 1
        add     rsp, 24
        ret

It seems that this whole combination of flags (-Og, pthread, coverage) is
significant, as is the fact that htons is a lambda and not a function, as are
all sorts of other things. I have no idea. 

Link to compiler explorer: https://godbolt.org/z/6pgLF_

Reply via email to