https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88033
--- Comment #3 from Peter Bergner <bergner at gcc dot gnu.org> ---
So this is a problem when we have a simple copy from a reg to itself, like so:
(insn (set (reg:DI XXX) (reg:DI XXX)))
By definition, a register does not conflict with itself, but a copy of this
type is confusing the code that is handling non conflicting copies and we're
adding extra program points when we shouldn't. Since a register cannot
conflict with itself, it's easier to just bail on these types of copies in
non_conflicting_reg_copy_p() rather than trying to fix up the code to handle
them. I'm regtesting the following patch that fixes the ICE for me.
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c (revision 266207)
+++ gcc/ira-lives.c (working copy)
@@ -1083,11 +1083,17 @@ non_conflicting_reg_copy_p (rtx_insn *insn)
int src_regno = REGNO (SET_SRC (set));
machine_mode mode = GET_MODE (SET_DEST (set));
+ /* By definition, a register does not conflict with itself, therefore we
+ do not have to handle it specially. Returning NULL_RTX now, helps
+ simplify the callers of this function. */
+ if (dst_regno == src_regno)
+ return NULL_RTX;
+
/* Computing conflicts for register pairs is difficult to get right, so
for now, disallow it. */
- if ((dst_regno < FIRST_PSEUDO_REGISTER
+ if ((HARD_REGISTER_NUM_P (dst_regno)
&& hard_regno_nregs (dst_regno, mode) != 1)
- || (src_regno < FIRST_PSEUDO_REGISTER
+ || (HARD_REGISTER_NUM_P (src_regno)
&& hard_regno_nregs (src_regno, mode) != 1))
return NULL_RTX;