On 1/10/2026 9:11 AM, Stefan Schulze Frielinghaus wrote:
From: Stefan Schulze Frielinghaus <[email protected]>

This fixes

t.c:6:1: error: unable to find a register to spill
     6 | }
       | ^

for target avr.  In the PR we are given a patch which makes use of hard
register constraints in the machine description for divmodhi4.  Prior
combine we have for the test from the PR

(insn 7 6 8 2 (parallel [
             (set (reg:HI 46 [ _1 ])
                 (div:HI (reg/v:HI 44 [ k ])
                     (reg:HI 48)))
             (set (reg:HI 47)
                 (mod:HI (reg/v:HI 44 [ k ])
                     (reg:HI 48)))
             (clobber (scratch:HI))
             (clobber (scratch:QI))
         ]) "t.c":5:5 602 {divmodhi4}
      (expr_list:REG_DEAD (reg:HI 48)
         (expr_list:REG_DEAD (reg/v:HI 44 [ k ])
             (expr_list:REG_UNUSED (reg:HI 47)
                 (nil)))))
(insn 8 7 9 2 (set (reg:HI 22 r22)
         (symbol_ref/f:HI ("*.LC0") [flags 0x2]  <var_decl 0x3fff7950d10 *.LC0>)) 
"t.c":5:5 128 {*movhi_split}
      (nil))
(insn 9 8 10 2 (set (reg:HI 24 r24)
         (reg:HI 46 [ _1 ])) "t.c":5:5 128 {*movhi_split}
      (expr_list:REG_DEAD (reg:HI 46 [ _1 ])
         (nil)))

The patched instruction divmodhi4 constraints operand 2 (here pseudo
48) to hard register 22.  Combine merges insn 7 into 9 by crossing a
hard register assignment of register 22.

(note 7 6 8 2 NOTE_INSN_DELETED)
(insn 8 7 9 2 (set (reg:HI 22 r22)
         (symbol_ref/f:HI ("*.LC0") [flags 0x2]  <var_decl 0x3fff7950d10 *.LC0>)) 
"t.c":5:5 128 {*movhi_split}
      (nil))
(insn 9 8 10 2 (parallel [
             (set (reg:HI 24 r24)
                 (div:HI (reg:HI 49 [ k ])
                     (reg:HI 48)))
             (set (reg:HI 47)
                 (mod:HI (reg:HI 49 [ k ])
                     (reg:HI 48)))
             (clobber (scratch:HI))
             (clobber (scratch:QI))
         ]) "t.c":5:5 602 {divmodhi4}
      (expr_list:REG_DEAD (reg:HI 48)
         (expr_list:REG_DEAD (reg:HI 49 [ k ])
             (nil))))

This leaves us with a conflict for pseudo 48 in the updated insn 9 since
register 22 is live here.

Fixed by pulling the sledge hammer and skipping any logical link if a
single register constraint is possibly involved.  Ideally we would skip
based on the fact whether there is any usage of a hard register referred
by any single register constraint between INSN and USE_INSN during
combine.

gcc/ChangeLog:

        * combine.cc (has_single_register_constraint_p): New function.
        (create_log_links): Do not build LOG_LINKs between insns
        containing single register constraints.
Yea, this is a lot like the problems we have with return values and more generally classes with a single hard register.  I would suggest looking at can't combine_insn_p which has the likely_spilled checks in it.
Jeff

Reply via email to