https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108892
Jeffrey A. Law <law at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Assignee|unassigned at gcc dot gnu.org |law at gcc dot gnu.org --- Comment #3 from Jeffrey A. Law <law at gcc dot gnu.org> --- This looks like a long-standing latent bug in combine. About 20 years ago support was added to combine to allow it to utilize a REG_EQUAL note to help simplifications. The code looks like this: /* Temporarily replace the set's source with the contents of the REG_EQUAL note. The insn will be deleted or recognized by try_combine. */ rtx orig_src = SET_SRC (set); rtx orig_dest = SET_DEST (set); if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT) SET_DEST (set) = XEXP (SET_DEST (set), 0); SET_SRC (set) = note; i2mod = temp; i2mod_old_rhs = copy_rtx (orig_src); i2mod_new_rhs = copy_rtx (note); next = try_combine (insn, i2mod, NULL, NULL, &new_direct_jump_p, last_combined_insn); i2mod = NULL; if (next) { statistics_counter_event (cfun, "insn-with-note combine", 1); goto retry; } SET_SRC (set) = orig_src; SET_DEST (set) = orig_dest; So assume that temp (from which SET in the above code was extracted) looks like this: (insn 122 117 127 2 (set (reg:DI 157 [ _46 ]) (ior:DI (reg:DI 200) (reg:DI 251))) "j.c":14:5 -1 (expr_list:REG_EQUAL (const_int 25769803782 [0x600000006]) (nil))) Basically the constant isn't one we can load with a single insn, so we construct the constant using several insns and attach a REG_EQUAL note for the final result. Totally normal. We replace the SET_SRC with the contents of the note. This results in the following insn that gets passed down to try_combine as I2MOD: (insn 122 117 127 2 (set (reg:DI 157 [ _46 ]) (const_int 25769803782 [0x600000006])) "j.c":14:5 -1 (expr_list:REG_EQUAL (const_int 25769803782 [0x600000006]) (nil))) Exactly what I would expect. try_combine will actually try to recognize that insn and gets a match on the mvconst_internal. So when try_combine returns the insn looks like this: (insn 122 117 127 2 (set (reg:DI 157 [ _46 ]) (const_int 25769803782 [0x600000006])) "j.c":14:5 177 {*mvconst_internal} (expr_list:REG_EQUAL (const_int 25769803782 [0x600000006]) (nil))) Again, totally normal. Nothing wrong at this point. But note how we restore the SET_SRC/SET_DEST objects after returning from try_combine. After restoration we have: (insn 122 117 127 2 (set (reg:DI 157 [ _46 ]) (ior:DI (reg:DI 200) (reg:DI 251))) "j.c":14:5 177 {*mvconst_internal} (expr_list:REG_EQUAL (const_int 25769803782 [0x600000006]) (nil))) And that's where things have gone off the rails. When we restore the SET_SRC/SET_DEST we need to either re-recognize or at least clear the INSN_CODE. This has *absolutely nothing* to do with multiple matching patterns. It's just a latent bug in the combiner.