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?