I'm working with a CPU having a restricted set of registers that can do three address maths wheres ALL registers can do two address maths.

If I define

(define_insn "addsi3"
  [     (set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_operand:SI 1 "register_operand" "0,0") (match_operand:SI 2 "rhs_operand" "r,i")))

So that all adds are done using 2 address instructions then all is fine. If however I change addsi3 to

(where the constraint 'R' is the smaller set of three address registers)

(define_insn "addsi3"
  [     (set (match_operand:SI 0 "register_operand" "=R,r,r")
(plus:SI (match_operand:SI 1 "register_operand" "R,0,0") (match_operand:SI 2 "rhs_operand" "R,r,i")))


to take advantage of the three address instructions then the three address instructions are used successfully on many occassions.

However when register pressure on the 'R' class is high the allocater never falls back to using the entire register set by employing the two address instructions.

Resulting in ...

error: unable to find a register to spill in class ‘GP_REGS’

enabling lra and inspecting the rtl dump indicates that both alternatives (R and r) seem to be equally appealing to the allocater so it chooses 'R' and fails.

GCC internals document indicates that the '0' alternates should be placed at the end of the alternatives list, so I'm guessing 'R' will always be chosen.

Using constraint disparaging (?R) eradicates the errors, but of course that causes the 'R' three address alternative to never be used.

Suggestions ?

Reply via email to