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.

Reply via email to