public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "christoph at muppetnet dot net" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c++/113665] New: Regular for Loop results in Endless Loop with -O2
Date: Mon, 29 Jan 2024 23:11:17 +0000	[thread overview]
Message-ID: <bug-113665-4@http.gcc.gnu.org/bugzilla/> (raw)

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

            Bug ID: 113665
           Summary: Regular for Loop results in Endless Loop with -O2
           Product: gcc
           Version: 11.4.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: christoph at muppetnet dot net
  Target Milestone: ---

Compiling the example code below with GCC 11.4.0 (I actually encountered this
bug in all versions >= 11 which I tried but not in older ones) and -O2 (other
optimization levels seem to work) results in an endless loop and finally a
segmentation fault due to an out-of-bounds access.

We can clearly argue about issues in the implementation of the bitfield class
(it is based on a real implementation of such a class I encountered in existing
codebase) but the main problem here is that the simple for loop in bug() is
generated into an endless loop. I think regardless of how the test method is
implemented, this loop should always terminate correctly.

#include <cstdint>
#include <cstddef>
#include <array>
#include <climits>

template<size_t S>
class bitfield
{
private:
    using Element = uint8_t;

    static constexpr uint32_t C = (S - 1u) / 8u;

private:
    std::array<Element, C + 1> m_Array;

public:
    bool test(size_t i) const
    {   
        if (i >= S){
            return false;
        }

        const size_t index = static_cast<uint32_t>(i) / 8u;
        const Element bitmask = 1u << (i % 8u);
        return (m_Array[index] & bitmask) != 0u;
    }
};

void bug2(const bitfield<0x120u> &b)
{
    if (!b.test(1u))
    {
        volatile int test = 1;
    }
}

void bug(const bitfield<0x250u> &b)
{
    for (uint16_t i = 0u; i < 0x250u; i++)
    {
        // this loop seems to not properly terminate
        if (!b.test(i))
        {
            volatile int test = i;
        }
    }
}

int main()
{
    bitfield<0x250u> b;
    bug(b);
    return 0;
}

Looking at the generated assembler code (in this example ARM64 generated in
godbolt.org, the same issue is also present on my x86-64 machine) we can see,
that the check for i < 0x250 is completely lost. Actually, at .L9 we do the
increment of the loop variable and then unconditionally jump back to .L10 for
the next iteration.

bug(bitfield<592ul> const&):
        sub     sp, sp, #16
        mov     w2, 0
        mov     w4, 1
.L10:
        lsr     w3, w2, 3
        and     w1, w2, 7
        lsl     w1, w4, w1
        ldrb    w3, [x0, w3, uxtw]
        and     w1, w1, w3
        tst     w1, 255
        bne     .L9
        str     w2, [sp, 12]
.L9:
        add     w2, w2, 1
        b       .L10

During testing of different variants of the code I encountered that there seem
to be different (but totally unexpected) ways to solve the issue:

- adding -fno-tree-vrp or -fno-guess-branch-probability
- deleting method bug2
- changing the type of i to size_t

             reply	other threads:[~2024-01-29 23:11 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-29 23:11 christoph at muppetnet dot net [this message]
2024-01-29 23:14 ` [Bug c++/113665] " christoph at muppetnet dot net
2024-01-30  0:25 ` [Bug ipa/113665] " pinskia at gcc dot gnu.org
2024-01-30  6:01 ` [Bug ipa/113665] [11/12/13/14 regression] " sjames at gcc dot gnu.org
2024-01-30  6:04 ` pinskia at gcc dot gnu.org
2024-01-30  8:11 ` rguenth at gcc dot gnu.org
2024-01-30  8:16 ` rguenth at gcc dot gnu.org
2024-01-30  9:12 ` [Bug ipa/113665] [11/12/13/14 regression] Regular for Loop results in Endless Loop with -O2 since r11-4987-g602c6cfc79ce4a sjames at gcc dot gnu.org
2024-01-30 17:21 ` hubicka at ucw dot cz
2024-01-31  7:35 ` rguenth at gcc dot gnu.org
2024-03-09 17:10 ` law at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-113665-4@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).