https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116723
--- Comment #2 from Ye Xiong <bouncy12578 at gmail dot com> --- (In reply to Andrew Pinski from comment #1) > (p.f0 != (-18)) > > For uint16_t, this is always true and is an always infinite loop. While for > int16_t it is not and the loop is removed because you supplied -ffinite-loop. > > -ffinite-loop does NOT remove always infinite loops by design and is what is > required by the C++ standard even. > > So invalid by design. However, if swap the two types in the union (in case1.c) like: case3.c union U0 { int32_t f0; int16_t f1; } g; int func_1(union U0 p) { p.f1 = 0; for (p.f0 = 1; (p.f0 != (-18)); p.f0 = (int32_t) (3 - p.f0)); return 1; } Although p.f0 is a signed int, it will outputs "1" (with -O3 and -ffinite-loops). Even weirder, only change the type of p1 from int16_t to int32_t the basis of case3.c: case4.c union U0 { int32_t f0; int32_t f1; } g; int func_1(union U0 p) { p.f1 = 0; for (p.f0 = 1; (p.f0 != (-18)); p.f0 = (int32_t) (3 - p.f0)); return 1; } It will be seen as an infinite loop again.