https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119071

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |segher at gcc dot gnu.org

--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, I think the problematic combination is
Trying 13, 18, 17 -> 19:
   13: r97:SI=flags:CCZ!=0
   18: {r101:SI=-r97:SI;clobber flags:CC;}
      REG_UNUSED flags:CC
   17: r99:SI=flags:CCZ==0
      REG_DEAD flags:CCZ
   19: {r102:SI=r99:SI<<r101:SI#0;clobber flags:CC;}
      REG_DEAD r101:SI
      REG_DEAD r99:SI
      REG_UNUSED flags:CC
Failed to match this instruction:
(parallel [
        (set (reg:SI 102)
            (eq:SI (reg:CCZ 17 flags)
                (const_int 0 [0])))
        (clobber (reg:CC 17 flags))
        (set (reg:SI 97)
            (ne:SI (reg:CCZ 17 flags)
                (const_int 0 [0])))
    ])
Failed to match this instruction:
(parallel [
        (set (reg:SI 102)
            (eq:SI (reg:CCZ 17 flags)
                (const_int 0 [0])))
        (set (reg:SI 97)
            (ne:SI (reg:CCZ 17 flags)
                (const_int 0 [0])))
    ])
Successfully matched this instruction:
(set (reg:SI 97)
    (ne:SI (reg:CCZ 17 flags)
        (const_int 0 [0])))
Successfully matched this instruction:
(set (reg:SI 102)
    (eq:SI (reg:CCZ 17 flags)
        (const_int 0 [0])))
allowing combination of insns 13, 17, 18 and 19
original costs 4 + 4 + 4 + 4 = 16
replacement costs 4 + 4 = 8
deferring deletion of insn with uid = 17.
deferring deletion of insn with uid = 13.
modifying insn i2    18: r97:SI=flags:CCZ!=0
      REG_DEAD flags:CC
deferring rescan insn with uid = 18.
modifying insn i3    19: r102:SI=flags:CCZ==0
      REG_DEAD flags:CC
deferring rescan insn with uid = 19.

Note, the insn order is 13, 17, 18, 19, so before this change the IL is fine,
we have
   13: r97:SI=flags:CCZ!=0
   17: r99:SI=flags:CCZ==0
      REG_DEAD flags:CCZ
   18: {r101:SI=-r97:SI;clobber flags:CC;}
      REG_UNUSED flags:CC
   19: {r102:SI=r99:SI<<r101:SI#0;clobber flags:CC;}
      REG_DEAD r101:SI
      REG_DEAD r99:SI
      REG_UNUSED flags:CC
So, first there are 2 comparisons using flags, then subtraction which clobbers
flags and then left shift (which is UB if r97 is non-zero and <<0 otherwise).
But we turn it into just the two comparisons (so the left shift and negation
optimized away because of the UB), that is fine, but only if we only add
REG_DEAD on the last insn.  The code adds it on both though, which makes the
second comparison UB, reading a dead register.

Reply via email to