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
#include
#include
#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 = 0x0400, 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 = 0x7000
5120 < 16384 is true, pos = 0x7400
6144 < 16384 is true, pos = 0x7800
7168 < 16384 is true, pos = 0x7c00
8192 < 16384 is true, pos = 0x8000
9216 < 16384 is true, pos = 0x8400
10240 < 16384 is true, pos = 0x8800
11264 < 16384 is true, pos = 0x8c00
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?