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

--- Comment #15 from Richard Biener <rguenth at gcc dot gnu.org> ---
Thanks, it's still the same reason - we isolate a nullptr case and end up with

__atomic_or_fetch_4 (184B, 64, 0); [tail call]

The path we isolate is d->m_mutex == nullptr && !enable in

void QFutureInterfaceBase::setThrottled(bool enable)
{
    QMutexLocker lock(&d->m_mutex);
    if (enable) {
        switch_on(d->state, Throttled);
    } else {
        switch_off(d->state, Throttled);
        if (!(d->state.loadRelaxed() & suspendingOrSuspended))
            d->pausedWaitCondition.wakeAll();
    }
}

where for unknown reason QMutexLocker happily allows a nullptr mutex
(it's documented that way)

    inline explicit QMutexLocker(Mutex *mutex) noexcept
    {
        m = mutex;
        if (__builtin_expect(!!(mutex), true)) {
            mutex->lock();
            isLocked = true;
        }
    }

we predict the path to be unlikely but the adjustment to the threader
covered probably never executed paths (with probability zero).  The
threading opportunity arises because the DTOR calls

    inline void unlock() noexcept
    {   
        if (!isLocked)
            return;
        m->unlock();
        isLocked = false;
    }

and we know isLocked on the nullptr path.

I thought we could maybe enhance prediction to look for nullptr based
accesses but at the time we estimate probabilities the QMutexLocker
CTOR isn't yet inlined (the DTOR is partially inlined, exposing the
isLocked check).

Note the "impossible" path is actually in the sources - so there might
be a missing conditional somewhere.

Reply via email to