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

Drea Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
   Last reconfirmed|                            |2026-08-01
           Keywords|                            |ice-on-valid-code
             Status|UNCONFIRMED                 |NEW
   Target Milestone|---                         |15.4

--- Comment #1 from Drea Pinski <pinskia at gcc dot gnu.org> ---
      /* Replacing the operand of a SUBREG or a ZERO_EXTEND with a
         CONST_INT is not valid, because after the replacement, the
         original mode would be gone.  Unfortunately, we can't tell
         when do_SUBST is called to replace the operand thereof, so we
         perform this test on oldval instead, checking whether an
         invalid replacement took place before we got here.  */
      gcc_assert (!(GET_CODE (oldval) == SUBREG
                    && CONST_INT_P (SUBREG_REG (oldval))));
      gcc_assert (!(GET_CODE (oldval) == ZERO_EXTEND
                    && CONST_INT_P (XEXP (oldval, 0))));


(gdb) p debug_rtx(oldval)
(zero_extend:DI (const_int 0 [0]))


ext_dce goes from:
(insn 34 33 5 2 (set (reg/v:SI 104 [ bb8 ])
        (const_int 0 [0])) :17:10 -1
     (nil))
...
(insn 6 5 7 2 (set (subreg:DI (reg:QI 108) 0)
        (zero_extract:DI (subreg:DI (reg/v:SI 104 [ bb8 ]) 0)
            (const_int 8 [0x8])
            (const_int 24 [0x18]))) 817 {*extzvdi}
     (expr_list:REG_DEAD (reg/v:SI 104 [ bb8 ])
        (nil)))
(insn 7 6 10 2 (set (reg:SI 105 [ _6 ])
        (subreg:SI (reg:QI 108) 0)) 69 {*movsi_aarch64}
     (nil))
(insn 10 7 11 2 (set (reg:SI 110 [ _6 ])
        (sign_extend:SI (reg:QI 108))) :19:21 110 {*extendqisi2_aarch64}
     (expr_list:REG_DEAD (reg:QI 108)
        (nil)))

to:
(insn 34 33 5 2 (set (reg/v:SI 104 [ bb8 ])
        (const_int 0 [0])) :17:10 -1
     (nil))
...
(insn 6 5 7 2 (set (subreg:DI (reg:QI 108) 0)
        (zero_extract:DI (subreg:DI (reg/v:SI 104 [ bb8 ]) 0)
            (const_int 8 [0x8])
            (const_int 24 [0x18]))) 817 {*extzvdi}
     (expr_list:REG_DEAD (reg/v:SI 104 [ bb8 ])
        (nil)))
(insn 7 6 10 2 (set (reg:SI 105 [ _6 ])
        (zero_extend:SI (reg:QI 108))) 114 {*zero_extendqisi2_aarch64}
     (nil))
(insn 10 7 11 2 (set (reg:SI 110 [ _6 ])
        (sign_extend:SI (reg:QI 108))) :19:21 110 {*extendqisi2_aarch64}
     (expr_list:REG_DEAD (reg:QI 108)
        (nil)))

Which seems like a very much valid thing to do but combine does not like it.

combine is doing:

Trying 10 -> 11:
   10: r110:SI=0
   11: cc:CC=cmp(r110:SI,0)
      REG_DEAD r110:SI

which actually combines in insn 12 because cc here:
(insn 12 11 14 2 (set (reg:SI 111 [ _2 ])
        (gt:SI (reg:CC 66 cc)
            (const_int 0 [0]))) :19:21 443 {aarch64_cstoresi}
     (expr_list:REG_DEAD (reg:CC 66 cc)
        (nil)))


And combine produces:
(insn 12 11 14 2 (set (reg:DI 111 [ _2 ])
        (zero_extend:DI (const_int 0 [0]))) :19:21 449 {*cstoresi_insn_uxtw}
     (expr_list:REG_DEAD (reg:CC 66 cc)
        (nil)))

Reply via email to