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

            Bug ID: 107785
           Summary: Integer comparison result compile with -O3
           Product: gcc
           Version: 12.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mugglewei at gmail dot com
  Target Milestone: ---

I have a ring buffer, in a loop put integer value and get position in the ring. 
-------------------------------------------------
#include <stdio.h>
#include <assert.h>
#include <unistd.h>

#define IDX_IN_POW_OF_2_RING(idx, capacity) ((idx) & ((capacity) - 1))

// #define pos_t unsigned int  // it's ok
#define pos_t int

int main()
{
        pos_t capacity = 1 << 10;
        pos_t k = 16;
        // pos_t pos = 0x7fff0fff;  // it's ok
        pos_t pos = 0x7fffdfff;

        fprintf(stderr, "capacity = 0x%08x, pos = 0x%08x\n", capacity, pos);
        pos_t idx_in_ring = IDX_IN_POW_OF_2_RING(pos, capacity);
        pos_t last_idx_in_ring = idx_in_ring;
        pos_t loop_cnt = capacity * k;
        for (pos_t i = 0; i < loop_cnt; ++i)
        {
                idx_in_ring = IDX_IN_POW_OF_2_RING(++pos, capacity);
                assert(idx_in_ring >= 0);
                assert(idx_in_ring < capacity);
                if (last_idx_in_ring == capacity - 1)
                {
                        assert(idx_in_ring == 0);
                }
                else
                {
                        assert(idx_in_ring == last_idx_in_ring + 1);
                }
                last_idx_in_ring = idx_in_ring;

                if (i % capacity == 0)
                {
                        fprintf(stderr, "%d < %d is %s, pos = 0x%08x\n",
                                (int)i, (int)(loop_cnt),
                                (int)i < (int)(loop_cnt) ? "true" : "false",
                                pos);
                        usleep(100 * 1000);
                }
        }
        fprintf(stderr, "bye\n");

        return 0;
}
-------------------------------------------------

Under normal circumstances, like compile with -O0, it will print like:
###########################
capacity = 0x00000400, pos = 0x7fffdfff
0 < 16384 is true, pos = 0x7fffe000
1024 < 16384 is true, pos = 0x7fffe400
2048 < 16384 is true, pos = 0x7fffe800
3072 < 16384 is true, pos = 0x7fffec00
4096 < 16384 is true, pos = 0x7ffff000
5120 < 16384 is true, pos = 0x7ffff400
6144 < 16384 is true, pos = 0x7ffff800
7168 < 16384 is true, pos = 0x7ffffc00
8192 < 16384 is true, pos = 0x80000000
9216 < 16384 is true, pos = 0x80000400
10240 < 16384 is true, pos = 0x80000800
11264 < 16384 is true, pos = 0x80000c00
12288 < 16384 is true, pos = 0x80001000
13312 < 16384 is true, pos = 0x80001400
14336 < 16384 is true, pos = 0x80001800
15360 < 16384 is true, pos = 0x80001c00
bye

But when compile with -O3, incorrect integer comparison result in loop, i <
loop_cnt always return true, and will print infinitely. 
I found when I use `#define pos_t unsigned int` replace `#define pos_t int`, Or
ensure pos always positive integer, the comparison result is correct. But why
the type of pos will effect integer comparison?

Reply via email to