It is not trivial to decide when a write of a register pair terminates or starts a new chain. For example, prior regrename we have
(insn 91 38 36 5 (set (reg:FPRX2 16 %f0 [orig:76 x ] [76]) (const_double:FPRX2 0.0 [0x0.0p+0])) "float-cast-overflow-7-reduced.c":5:55 discrim 2 1507 {*movfprx2_64} (expr_list:REG_EQUAL (const_double:FPRX2 0.0 [0x0.0p+0]) (nil))) (insn 36 91 37 5 (set (subreg:DF (reg:FPRX2 16 %f0 [orig:76 x ] [76]) 0) (mem/c:DF (plus:DI (reg/f:DI 15 %r15) (const_int 160 [0xa0])) [7 %sfp+-32 S8 A64])) "float-cast-overflow-7-reduced.c":5:55 discrim 2 1512 {*movdf_64dfp} (nil)) (insn 37 36 43 5 (set (subreg:DF (reg:FPRX2 16 %f0 [orig:76 x ] [76]) 8) (mem/c:DF (plus:DI (reg/f:DI 15 %r15) (const_int 168 [0xa8])) [7 %sfp+-24 S8 A64])) "float-cast-overflow-7-reduced.c":5:55 discrim 2 1512 {*movdf_64dfp} (nil)) where insn 91 writes both registers of a register pair and it is clear that an existing chain must be terminated and a new started. Insn 36 and 37 write only into one register of a corresponding register pair. For each write on its own it is not obvious when to terminate an existing chain and to start a new one. In other words, once insn 36 materializes and 37 didn't we are kind of in a limbo state. Tracking this correctly is inherently hard and I'm not entirely sure whether optimizations could even lead to more complicated cases where it is even less clear when a chain terminates and a new has to be started. Therefore, skip renaming of register pairs. Bootstrapped and regtested on x86_64, aarch64, powerpc64le, and s390. Ok for mainline? This fixes on s390: FAIL: g++.dg/cpp23/ext-floating14.C -std=gnu++23 execution test FAIL: g++.dg/cpp23/ext-floating14.C -std=gnu++26 execution test FAIL: c-c++-common/ubsan/float-cast-overflow-7.c -O2 execution test FAIL: c-c++-common/ubsan/float-cast-overflow-7.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test FAIL: c-c++-common/ubsan/float-cast-overflow-7.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test FAIL: gcc.dg/torture/fp-int-convert-float128-ieee-timode.c -O0 execution test FAIL: gcc.dg/torture/fp-int-convert-float128-ieee-timode.c -O1 execution test FAIL: gcc.dg/torture/fp-int-convert-float128-ieee-timode.c -O2 execution test FAIL: gcc.dg/torture/fp-int-convert-float128-ieee-timode.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test FAIL: gcc.dg/torture/fp-int-convert-float128-ieee-timode.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test FAIL: gcc.dg/torture/fp-int-convert-float128-ieee-timode.c -O3 -g execution test FAIL: gcc.dg/torture/fp-int-convert-float128-ieee-timode.c -Os execution test FAIL: gcc.dg/torture/fp-int-convert-float64x-timode.c -O0 execution test FAIL: gcc.dg/torture/fp-int-convert-float64x-timode.c -O1 execution test FAIL: gcc.dg/torture/fp-int-convert-float64x-timode.c -O2 execution test FAIL: gcc.dg/torture/fp-int-convert-float64x-timode.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test FAIL: gcc.dg/torture/fp-int-convert-float64x-timode.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test FAIL: gcc.dg/torture/fp-int-convert-float64x-timode.c -O3 -g execution test FAIL: gcc.dg/torture/fp-int-convert-float64x-timode.c -Os execution test FAIL: gcc.dg/torture/fp-int-convert-timode.c -O0 execution test FAIL: gcc.dg/torture/fp-int-convert-timode.c -O1 execution test FAIL: gcc.dg/torture/fp-int-convert-timode.c -O2 execution test FAIL: gcc.dg/torture/fp-int-convert-timode.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test FAIL: gcc.dg/torture/fp-int-convert-timode.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test FAIL: gcc.dg/torture/fp-int-convert-timode.c -O3 -g execution test FAIL: gcc.dg/torture/fp-int-convert-timode.c -Os execution test FAIL: gfortran.dg/pr96711.f90 -O0 execution test FAIL: TestSignalForwardingExternal FAIL: go test misc/cgo/testcarchive FAIL: libffi.closures/nested_struct5.c -W -Wall -Wno-psabi -O2 output pattern test FAIL: libphobos.phobos/std/algorithm/mutation.d execution test FAIL: libphobos.phobos/std/conv.d execution test FAIL: libphobos.phobos/std/internal/math/errorfunction.d execution test FAIL: libphobos.phobos/std/variant.d execution test FAIL: libphobos.phobos_shared/std/algorithm/mutation.d execution test FAIL: libphobos.phobos_shared/std/conv.d execution test FAIL: libphobos.phobos_shared/std/internal/math/errorfunction.d execution test FAIL: libphobos.phobos_shared/std/variant.d execution test gcc/ChangeLog: PR rtl-optimiztion/115860 * regrename.cc (scan_rtx_reg): Do not try to rename register pairs. --- gcc/regrename.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gcc/regrename.cc b/gcc/regrename.cc index 054e601740b..6ae5a2309d0 100644 --- a/gcc/regrename.cc +++ b/gcc/regrename.cc @@ -1113,6 +1113,10 @@ scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions act c = create_new_chain (this_regno, this_nregs, loc, insn, cl); + /* Give up early in case of register pairs. */ + if (this_nregs != 1) + c->cannot_rename = 1; + /* We try to tie chains in a move instruction for a single output. */ if (recog_data.n_operands == 2 -- 2.45.2