https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125518

            Bug ID: 125518
           Summary: [RA]: lunable to find a register to spill: internal
                    compiler error: in lra_split_hard_reg_for, at
                    lra-assigns.cc:1885
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gjl at gcc dot gnu.org
  Target Milestone: ---

Created attachment 64595
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=64595&action=edit
spill1-rtl.c: C-RTL test case (spill fail)

The attached spill1-rtl.c runs into a spill fail:

$ avr-gcc spill1-rtl.c -S -Os
spill1-rtl.c: In function 'foo':
spill1-rtl.c:58:1: error: unable to find a register to spill
   58 | }
      | ^
spill1-rtl.c:58:1: error: this is the insn:
(insn 7 23 19 2 (parallel [
            (set (reg:HI 53 [orig:47 _1 ] [47])
                (div:HI (reg/v:HI 45 [ var ])
                    (reg:HI 54 [49])))
            (set (reg:HI 55 [48])
                (mod:HI (reg/v:HI 45 [ var ])
                    (reg:HI 54 [49])))
            (clobber (reg:HI 56 [50]))
            (clobber (reg:QI 57 [51]))
        ]) 600 {divmodhi4}
     (expr_list:REG_UNUSED (reg:QI 57 [51])
        (expr_list:REG_UNUSED (reg:HI 56 [50])
            (expr_list:REG_UNUSED (reg:HI 55 [48])
                (expr_list:REG_DEAD (reg:HI 54 [49])
                    (expr_list:REG_DEAD (reg/v:HI 45 [ var ])
                        (nil)))))))
during RTL pass: reload
spill1-rtl.c:58:1: internal compiler error: in lra_split_hard_reg_for, at
lra-assigns.cc:1885

The equivalent C code is:

int bar (int, int);
int foo (int var)
{
    return bar (var / 5, 0);
}

What the CRTL does is basically, that in preparation for the call, it
1) Sets the 2nd argument: reg22:HI=0 ; cinsn 8
2) Calculates the 1st argument using divmodhi4:
   reg<6>:HI=5 ; cinsn 6
   parallel (reg<4>:HI=div:HI (reg<2>:HI, reg<6>:HI) ; cinsn 7
             reg<5>:HI=mod:HI (reg<2>:HI, reg<6>:HI)
             clobber:HI
             clobber:QI)
   reg24:HI=reg<4>:HI ; cinsn 9

This is completely valid non-strict RTL, see for example this discussion:
https://gcc.gnu.org/pipermail/gcc/2026-May/248268.html

The challenge is that since r17-891, avr.md::divmodhi4 is using hard-reg
constraints:

(define_insn_and_split "divmodhi4"
  [(set (match_operand:HI 0 "register_operand"        "={r22}")
        (div:HI (match_operand:HI 1 "register_operand" "{r24}")
                (match_operand:HI 2 "register_operand" "{r22}")))
   (set (match_operand:HI 3 "register_operand"        "={r24}")
        (mod:HI (match_dup 1)
                (match_dup 2)))
   (clobber (match_scratch:HI 4                       "={r26}"))
   (clobber (match_scratch:QI 5                       "={r21}"))]

and hence it sets R22:HI as a side effect.  RA should spill R22 prior to cinsn
7, or it should rematerialize R22:HI=0 after cinsn 7.

Currently, the testcase is not reachable from C since insn combine is rejecting
any combination that involves hard-reg constraints as of r17-438.  This means
fixing the current PR is needed so insns with hard-reg constraints can be
insn-combined.

Reply via email to