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

            Bug ID: 127693
           Summary: [13/14/15/16/17] Miscompilation: __builtin_constant_p
                    branch removed then still apparently used
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ipa
          Assignee: unassigned at gcc dot gnu.org
          Reporter: thiago at kde dot org
  Target Milestone: ---

Reference: https://qt-project.atlassian.net/browse/QTBUG-151050

Note: I used an AI to help me narrow down the QtCore crash to the reproducers
below, which I have reviewed for validity. 

The following I am sure of:

Qt reproducer:
#include <QtCore/qstringview.h>
#include <cstdio>

// Reduced from NumericPattern::Scanner in
qtbase/src/corelib/time/qtimezoneprivate.cpp
struct Scanner
{
    QStringView given;

    int scanForToken(QStringView sought)
    {
        const qsizetype n = sought.size();
        qsizetype idx = -n;
        int tokensMatched = 0;
        while ((idx = given.indexOf(sought, idx + n)) >= 0)
            ++tokensMatched;
        return tokensMatched;
    }

    Q_NEVER_INLINE int scanForSigns()
    {
        return scanForToken(u"\u2212"); // Canonical minus sign
    }
};

int main()
{
    Scanner scanner{ u"1\u22122\u22123" };
    std::printf("%d\n", scanner.scanForSigns());   // expected: 2
}

C-only reproducer:

struct SV { long m_size; };
long findString(long from, struct SV needle);
long findChar(long from);

static long indexOf(struct SV s, long from)
{
    if (__builtin_constant_p(s.m_size) && s.m_size == 1)
        return findChar(from);
    return findString(from, s);
}

static int scan(struct SV sought)
{
    long n = sought.m_size;
    long idx = -n;
    int matched = 0;
    while ((idx = indexOf(sought, idx + n)) >= 0)
        ++matched;
    return matched;
}

int f(void) { return scan((struct SV){1}); }

The Qt reproducer appears to work with GCC 13 and 14. The C-only reproducer
fails with all these versions:
* 13.5.0
* 14.4.0
* 15.3.0
* 16.2.0
* 17 as of today, Git commit 3b60e2204e225ea643fe54a999848f99d49a6659

The program has no UB: f() should loop calling findChar() or findString() 
(either is ok but the intent is that one is selected at compile time) until it
returns a negative value. Clang 23 compiled f() to a function calling
findChar(), as expected.

Instead, under -O2 (and only -O2), this C reproducer appears to replace the
entire function with a __builtin_unreachable(). GCC 13-15 then just emit
nothing (no ret), so a call ends up at whatever is next in the executable. GCC
16 and 17 emit an ud2 on x86-64.

This was made worse by Qt recently adding a few [[assume]] calls. Now the Qt
reproducer fails with -O3 too.

It *looks* like -ftree-vrp is the culprit: without it (with -fno-tree-vrp), the
generated code is calling findChar() as expected.

Reply via email to