https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68730
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |vmakarov at gcc dot gnu.org --- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> --- As for the miscompilation, it looks like RA issue to me. Note, -m32 -O3 -march=x86-64 is needed on the testcase, and I've been actually looking at: int printf (const char *, ...); int b, d, e; unsigned long long c = 4100543410106915; void fn1 () { short f, g = 4 % c; int h = c; if (h) { int i = ~c; if (~c) i = 25662; f = g = i; h = c - g + ~-f; c = ~(c * h - f); } f = g; unsigned long long k = g || c; short l = c ^ g ^ k; if (g > 25662 || c == 74074520320 || !(g < 2)) { k = c; l = g; c = ~((k && c) + ~l); f = ~(f * (c ^ k) | l); if (c > k) printf ("X %d\n", f); } short m = -f; unsigned long long n = c; c = m * f | n % c; if (n) printf ("Y %d %d %d\n", f, g, l); while (f < -31807) ; c = ~(n | c) | f; if (n < c) printf ("Z %lld %d %d\n", (long long) f, h, l); for (; d;) for (; e;) for (;;) ; c = h; c = l % c; } int main () { for (; b < 2; b++) fn1 (); return 0; } testcase instead (following stuff is from that) with the same options (as makes it more clear what the bug is, for the code path taken in the first call to fn1, we end up with l being equal to f (i.e. -28479) instead of the right value, l being equal to g (i.e. 25662) as can be seen already at the Y printf. We have in *.ira: (code_label 294 125 127 16 24 "" [1 uses]) (note 127 294 128 16 [bb 16] NOTE_INSN_BASIC_BLOCK) (insn 128 127 13 16 (set (reg:SI 107 [ _52 ]) (sign_extend:SI (reg:HI 132 [ g.2_118 ]))) 147 {extendhisi2} (nil)) (insn 13 128 14 16 (set (reg:DI 130 [ c.0_114 ]) (reg:DI 100 [ _42 ])) pr68730-2.c:29 85 {*movdi_internal} (expr_list:REG_DEAD (reg:DI 100 [ _42 ]) (nil))) (insn 14 13 15 16 (set (reg/v:HI 88 [ l ]) (reg/v:HI 87 [ g ])) pr68730-2.c:29 88 {*movhi_internal} (expr_list:REG_DEAD (reg/v:HI 87 [ g ]) (nil))) (insn 15 14 348 16 (set (reg/v:HI 87 [ g ]) (reg:HI 132 [ g.2_118 ])) pr68730-2.c:28 88 {*movhi_internal} (nil)) (jump_insn 348 15 349 16 (set (pc) (label_ref 140)) 663 {jump} (nil) where (reg:HI 132 [ g.2_118 ]) is apparently the RTL for the partition including both g.2_118 and _50 at least: g.2_206 = (unsigned short) g_202; ... # g.2_118 = PHI <g.2_206(25), g.2_206(10), 0(7)> ... _39 = ~prephitmp_197; _40 = iftmp.3_7 + _39; _41 = ~_40; _42 = (long long unsigned int) _41; c = _42; _45 = (unsigned short) g_202; _46 = _42 ^ c.0_114; _47 = (unsigned short) _46; _48 = _45 * _47; _49 = _48 | g.2_118; _50 = ~_49; f_51 = (short int) _50; so while reg:HI 132 is initially equal to the current value of the g variable, it is reused for something else afterwards. This particular problematic RTL bb is likely coming just from PHIs: # f_1 = PHI <g_202(9), f_51(12), f_51(13), g_202(8)> # l_5 = PHI <l_203(9), g_202(12), g_202(13), l_110(8)> # prephitmp_222 = PHI <g.2_206(9), _219(12), _220(13), 0(8)> # prephitmp_224 = PHI <prephitmp_199(9), _42(12), pretmp_223(13), prephitmp_199(8)> # prephitmp_228 = PHI <prephitmp_197(9), _226(12), _52(13), prephitmp_197(8)> on certain edge. At this point reg:HI 132 should contain one value (the current value of f after f = ~(f * (c ^ k) | l);, and reg:HI 87 should contain the current value of g variable. But in *.reload dump this is already: (code_label 294 125 127 16 24 "" [1 uses]) (note 127 294 458 16 [bb 16] NOTE_INSN_BASIC_BLOCK) (insn 458 127 128 16 (set (reg:HI 0 ax [orig:132 g.2_118 ] [132]) (reg:HI 6 bp [orig:132 g.2_118 ] [132])) 88 {*movhi_internal} (nil)) (insn 128 458 419 16 (set (reg:SI 3 bx [orig:107 _52 ] [107]) (sign_extend:SI (reg:HI 0 ax [orig:132 g.2_118 ] [132]))) 147 {extendhisi2} (nil)) (insn 419 128 13 16 (set (mem/c:SI (plus:SI (reg/f:SI 7 sp) (const_int 16 [0x10])) [4 %sfp+-32 S4 A64]) (reg:SI 3 bx [orig:107 _52 ] [107])) 86 {*movsi_internal} (nil)) (insn 13 419 479 16 (set (reg:DI 2 cx [orig:130 c.0_114 ] [130]) (reg:DI 4 si [orig:100 _42 ] [100])) pr68730-2.c:29 85 {*movdi_internal} (nil)) (insn 479 13 474 16 (set (reg/v:HI 5 di [orig:87 g ] [87]) (reg:HI 6 bp [orig:132 g.2_118 ] [132])) pr68730-2.c:29 88 {*movhi_internal} (nil)) (note 474 479 14 16 NOTE_INSN_DELETED) (insn 14 474 15 16 (set (mem/c:HI (plus:SI (reg/f:SI 7 sp) (const_int 24 [0x18])) [4 %sfp+-24 S2 A32]) (reg/v:HI 5 di [orig:87 g ] [87])) pr68730-2.c:29 88 {*movhi_internal} (nil)) (insn 15 14 348 16 (set (mem/c:HI (plus:SI (reg/f:SI 7 sp) (const_int 10 [0xa])) [4 %sfp+-38 S2 A16]) (reg:HI 0 ax [orig:132 g.2_118 ] [132])) pr68730-2.c:28 88 {*movhi_internal} (nil)) which means that both l contains the g.2_118 value (aka f), instead of the desired one (g). Vlad, can you please have a look?