https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116799
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |krebbel at gcc dot gnu.org --- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> --- So, I think this is caused by stale REG_DEAD note. In *.optimized the code I'm talking about is: _32 = x_13(D) + _25; if (_26 == 42) goto <bb 4>; [94.50%] else goto <bb 5>; [5.50%] <bb 3> [local count: 958878295]: x_15 = x_27 + 1; _2 = MEM[(const char *)x_15]; if (_2 == 42) goto <bb 4>; [94.50%] else goto <bb 5>; [5.50%] <bb 4> [local count: 1014686025]: # x_27 = PHI <x_15(3), x_13(D)(2)> if (x_27 < _32) goto <bb 3>; [94.50%] else goto <bb 11>; [5.50%] ... <bb 11> [local count: 55807731]: if (x_27 <= _32) goto <bb 10>; [5.66%] else goto <bb 9>; [94.34%] where in the testcase the flow is _26 == 42 is true, x_27 < _32 is true, x is incremented by 1 and dereferenced, _2 == 42 is true, x_27 < _32 is not, so goto bb 11 and there x_27 <= _32 is true, so goto bb 10. Before unrolling, that is similarly we do ... and the increment and dereference, and (insn 32 31 33 3 (set (reg:CCZ 33 %cc) (compare:CCZ (reg:SI 77) (const_int 42 [0x2a]))) "pr116799.c":15:22 1448 {*cmpsi_cct} (expr_list:REG_DEAD (reg:SI 77) (nil))) is equal, so we do (insn 37 35 38 5 (set (reg:CCU 33 %cc) (compare:CCU (reg/v/f:DI 68 [ x ]) (reg/v/f:DI 65 [ y ]))) "pr116799.c":15:22 discrim 1 1460 {*cmpdi_ccu} (nil)) (jump_insn 38 37 42 5 (set (pc) (if_then_else (ltu (reg:CCU 33 %cc) (const_int 0 [0])) (label_ref 36) (pc))) "pr116799.c":15:22 discrim 1 2173 {*cjump_64} (int_list:REG_BR_PROB 1014686028 (nil)) -> 36) where x == y now, so ltu is false, so we continue with (note 84 81 86 16 [bb 16] NOTE_INSN_BASIC_BLOCK) (jump_insn 86 84 0 16 (set (pc) (if_then_else (leu (reg:CCU 33 %cc) (const_int 0 [0])) (label_ref:DI 99) (pc))) "pr116799.c":20:6 2173 {*cjump_64} (expr_list:REG_DEAD (reg:CCU 33 %cc) (int_list:REG_BR_PROB 60774356 (nil))) using the same %cc and leu is true. Now, loop2_unroll unrolls the loop in there, so after bb 2 we have (insn 400 402 401 94 (parallel [ (set (reg:DI 89) (minus:DI (reg/v/f:DI 65 [ y ]) (reg/v/f:DI 68 [ x ]))) (clobber (reg:CC 33 %cc)) ]) -1 (nil)) (insn 401 400 536 94 (parallel [ (set (reg:DI 90) (and:DI (reg:DI 89) (const_int 7 [0x7]))) (clobber (reg:CC 33 %cc)) ]) -1 (nil)) (where in the testcase y - x is 1), followed by (insn 534 536 535 130 (set (reg:CCZ 33 %cc) (compare:CCZ (reg:DI 90) (const_int 0 [0]))) -1 (nil)) (jump_insn 535 534 36 130 (set (pc) (if_then_else (eq (reg:CCZ 33 %cc) (const_int 0 [0])) (label_ref 533) (pc))) -1 pseudo 90 is 1, so eq is false, fallthrough correctly to the x = x + 1 and dereference. Then (insn 32 31 33 3 (set (reg:CCZ 33 %cc) (compare:CCZ (reg:SI 77) (const_int 42 [0x2a]))) "pr116799.c":15:22 1448 {*cmpsi_cct} (expr_list:REG_DEAD (reg:SI 77) (nil))) (jump_insn 33 32 102 3 (set (pc) (if_then_else (ne (reg:CCZ 33 %cc) (const_int 0 [0])) (label_ref 42) (pc))) "pr116799.c":15:22 2173 {*cjump_64} (expr_list:REG_DEAD (reg:CCZ 33 %cc) (int_list:REG_BR_PROB 59055804 (nil))) ne is false, then (insn 37 35 38 5 (set (reg:CCU 33 %cc) (compare:CCU (reg/v/f:DI 68 [ x ]) (reg/v/f:DI 65 [ y ]))) "pr116799.c":15:22 discrim 1 1460 {*cmpdi_ccu} (expr_list:REG_DEAD (reg/v/f:DI 65 [ y ]) (nil))) (jump_insn 38 37 42 5 (set (pc) (if_then_else (ltu (reg:CCU 33 %cc) (const_int 0 [0])) (label_ref 36) (pc))) "pr116799.c":15:22 discrim 1 2173 {*cjump_64} (expr_list:REG_DEAD (reg:CCU 33 %cc) (int_list:REG_BR_PROB 1014686028 (nil))) ltu is false, and go again to (note 84 81 86 16 [bb 16] NOTE_INSN_BASIC_BLOCK) (jump_insn 86 84 117 16 (set (pc) (if_then_else (leu (reg:CCU 33 %cc) (const_int 0 [0])) (label_ref:DI 99) (pc))) "pr116799.c":20:6 2173 {*cjump_64} (expr_list:REG_DEAD (reg:CCU 33 %cc) (int_list:REG_BR_PROB 60774356 (nil))) All fine except the REG_DEAD note on insn 38. That might not be a bug (though wonder what adds it there), REG_DEAD notes generally can be stale and one needs to recompute them when using them. But then comes loop2_doloop and changes -(jump_insn 38 37 42 5 (set (pc) - (if_then_else (ltu (reg:CCU 33 %cc) - (const_int 0 [0])) - (label_ref 36) - (pc))) "pr116799.c":15:22 discrim 1 2173 {*cjump_64} - (expr_list:REG_DEAD (reg:CCU 33 %cc) - (int_list:REG_BR_PROB 1014686028 (nil))) +(jump_insn 652 37 42 5 (parallel [ + (set (pc) + (if_then_else (ne (reg:DI 93) + (const_int 1 [0x1])) + (label_ref 36) + (pc))) + (set (reg:DI 93) + (plus:DI (reg:DI 93) + (const_int -1 [0xffffffffffffffff]))) + (clobber (scratch:DI)) + (clobber (reg:CC 33 %cc)) + ]) "pr116799.c":15:22 discrim 1 -1 + (int_list:REG_BR_PROB 1014686028 (nil)) but that clobbers %cc between the setter in insn 37 and use in insn 86.