https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119841
Bug ID: 119841 Summary: [15 Regression] gcc.target/cris/pr93372-2.c Product: gcc Version: 14.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: hp at gcc dot gnu.org CC: rsandifo at gcc dot gnu.org Target Milestone: --- Target: cris-elf >From r15-9239-g4d7a634f6d4102 "combine: Allow 2->2 combinations, but with a tweak [PR116398]", there's a regression for cris-elf: Running /x/gcc/gcc/testsuite/gcc.target/cris/cris.exp ... FAIL: gcc.target/cris/pr93372-2.c scan-assembler-not \tcmp|\ttest FAIL: gcc.target/cris/pr93372-2.c scan-assembler-times \tmove 1 The testcase checks for elimination of redundant compare insns, from e.g. the cmpelim pass. Where gcc used to emit: _f: sub.d $r11,$r10 seq $r9 move.d $r9,[$r12] ret sge $r10 it now emits: _f: move.d $r10,$r9 sub.d $r11,$r9 cmp.d $r11,$r10 seq $r10 move.d $r10,[$r12] cmpq 0,$r9 ret sge $r10 So, not only is there an extra move, but also none of the compares are eliminated. It's all due to the combine. Where it used to back off, it helpfully "optimizes" these two insns (compact format): 8: {r30:SI=r32:SI-r33:SI;clobber ccr:CC;} 9: {r36:SI=r30:SI==0;clobber ccr:CC;} into: 8: {r30:SI=r40:SI-r41:SI;clobber ccr:CC;} 9: {r36:SI=r40:SI==r41:SI;clobber ccr:CC;} i.e. (in classic format) from (eq:SI (reg/v:SI 30 [ c ]) (const_int 0 [0])) to (eq:SI (reg:SI 40 [ a ]) (reg:SI 41 [ b ])) in insn 9. The costs are (currently) the same. Because the costs (hence also the total cost) are the same, that change may look benevolent to you. What is not seen in the compact format is that this extends the lifetime of two registers that died in insn 8. Zombie apocalypse ensues. Or at least pressure on the living: register 30 is born and must stay alive while at the same time both register 40 and 41 are still alive, where previously they were killed and either could be mapped to the same hard register as register 30. The consequences is for the test-case, one extra move insn and the rtl no longer matching what cmpelim looks for, so the compares aren't eliminated. For reference use the classic, detailed format. Incoming to combine: (gdb) p i2 $127 = (rtx_insn *) 0x7ffff7a94380 (gdb) pr (insn 8 5 9 2 (parallel [ (set (reg/v:SI 30 [ c ]) (minus:SI (reg:SI 40 [ a ]) (reg:SI 41 [ b ]))) (clobber (reg:CC 19 ccr)) ]) "/mnt/storage0/hp/tmpdir/250407_9238/gcc/gcc/testsuite/gcc.target/cris/pr93372-2.c":12:7 76 {*subsi3} (expr_list:REG_DEAD (reg:SI 41 [ b ]) (expr_list:REG_UNUSED (reg:CC 19 ccr) (expr_list:REG_DEAD (reg:SI 40 [ a ]) (nil))))) (gdb) p i3 $128 = (rtx_insn *) 0x7ffff7a943c0 (gdb) pr (insn 9 8 10 2 (parallel [ (set (reg:SI 36 [ _1 ]) (eq:SI (reg/v:SI 30 [ c ]) (const_int 0 [0]))) (clobber (reg:CC 19 ccr)) ]) "/mnt/storage0/hp/tmpdir/250407_9238/gcc/gcc/testsuite/gcc.target/cris/pr93372-2.c":15:11 355 {*cstoresieq4} (expr_list:REG_UNUSED (reg:CC 19 ccr) (nil))) On the way out from try_combine: (gdb) p i2 $91 = (rtx_insn *) 0x7ffff7a94380 (gdb) pr (insn 8 5 9 2 (parallel [ (set (reg/v:SI 30 [ c ]) (minus:SI (reg:SI 40 [ a ]) (reg:SI 41 [ b ]))) (clobber (reg:CC 19 ccr)) ]) "/mnt/storage0/hp/tmpdir/250407_9239/gcc/gcc/testsuite/gcc.target/cris/pr93372-2.c":12:7 76 {*subsi3} (expr_list:REG_UNUSED (reg:CC 19 ccr) (nil))) (gdb) p i3 $92 = (rtx_insn *) 0x7ffff7a943c0 (gdb) pr (insn 9 8 10 2 (parallel [ (set (reg:SI 36 [ _1 ]) (eq:SI (reg:SI 40 [ a ]) (reg:SI 41 [ b ]))) (clobber (reg:CC 19 ccr)) ]) "/mnt/storage0/hp/tmpdir/250407_9239/gcc/gcc/testsuite/gcc.target/cris/pr93372-2.c":15:11 355 {*cstoresieq4} (expr_list:REG_DEAD (reg:SI 40 [ a ]) (expr_list:REG_DEAD (reg:SI 41 [ b ]) (expr_list:REG_UNUSED (reg:CC 19 ccr) (nil))))) This has two (including) solutions: hack the target so that the cost of a comparison operator where the second operant isn't const0_rtx is higher, or fix combine so it breaks ties considering the higher register pressure. (I'm pursuing both.)