https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108832
--- Comment #4 from Uroš Bizjak <ubizjak at gmail dot com> --- (In reply to Jakub Jelinek from comment #1) > and so ICEs if we see the same REGNO as from in a different mode. > I think we actually don't need most of what replace_rtx is doing, we don't > need to simplify anything etc. because we are just changing one register to > another and can do it in place. > So, I think we need a different function for what the backend wants. > It can avoid all the simplify stuff because replace_rtx was destructive, so > could be implemented say using FOR_EACH_SUBRTX_PTR. When seeing *loc == > from, it obviously > should set *loc = to, if it sees REG_P (*loc) && REGNO (*loc) == REGNO > (from), then > if the mode is the same, it can also just *loc = to, but if it is a > different mode, > I'd say for narrower mode it should *loc = gen_rtx_REG (GET_MODE (*loc), > REGNO (to)); > and for wider mode (especially if say a multi-register reg) punt. > Not sure if such a case can occur though, but the punting would be hard if > we have made some changes already... There are no multi-registers in flags-setting integer instructions, we only have instructions with implicit ZERO_EXTEND from SI to DImode in case of x86_64 target. So, a FOR_EACH_RTX loop that blindly changes REGNOs of the RTX should do the trick. Perhaps do it on a copied RTX, to avoid nasty surprises.