https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114729
--- Comment #13 from Vineet Gupta <vineetg at gcc dot gnu.org> --- So after many months on and off on the issue, I think I understand what's going on. There are 3 insns involved in the issue which sched1 current generates in following order: insn 46(1) srliw a0,a5,16 insn 55(3) srli a1,a5,32 insn 54(2) sh a0,%lo(_Z1sv+2)(a3) We want them in order 1,2,3 to avoid allocating a1, which ends up getting spilled. When insn 54 is ready, we see this ;; GR_REGS:28(1) FP_REGS:1(-31) ;; dependencies resolved: insn 54 ;; tick updated: insn 54 into ready ;; +------------------------------------------------------ ;; | Pressure costs for ready queue ;; | pressure points GR_REGS:[28->28 at 0:94] FP_REGS:[1->1 at 0:94] ^^^^^^^ insn 54 is clearly a sink insn and it is going to reduce register pressure, no matter what. But it seems in the complex maze of pressure calculations this crucial bit is getting lost and model_excess_cost concludes pressure stays at 28 (from 28). schedule_block ready_sort_real model_set_excess_costs (first = ready_lastpos (ready) which is insn 54) model_excess_cost(insn 54) model_excess_cost (insn=0x7ffff75c8fc0, print_p=true) at ../../gcc-scratch/gcc/haifa-sched.cc:2428 2428 { (gdb) 2433 calculate_reg_deaths (insn, insn_death); (gdb) 2436 cost = 0; (gdb) 2446 delta = insn_reg_pressure[pci].set_increase - insn_death[cl]; (gdb) (gdb) p delta $5 = -1 2447 this_cost = model_excess_group_cost (&model_before_pressure, point, pci, delta = -1) (gdb) 2449 cost += this_cost; (gdb) p this_cost $12 = 0 model_excess_group_costs -> model_spill_cost do takes delta -1 into account but there's a bunch of MAX values (all of which I don't quite understand) which ends up computing this_cost to 0 which is inaccurate for this insn. As a hack to understand this, I initialize the cost above to NOT 0, but the first delta which causes the -1 to get factored into cost returned by model_excess_cost. @@ -2444,6 +2444,8 @@ model_excess_cost (rtx_insn *insn, bool print_p) { cl = ira_pressure_classes[pci]; delta = insn_reg_pressure[pci].set_increase - insn_death[cl]; + if (pci == 0) + cost = delta; this_cost = model_excess_group_cost (&model_before_pressure, point, pci, delta); This causes the test to NOT spill. This doesn't feel like a production ready fix but seems like progress.