"Sean D'Epagnier" <geckosena...@gmail.com> writes: > I have a rule in machine descriptor: > > (define_insn "fract<FIXED2:mode><FIXED1:mode>2" > [(set (match_operand:FIXED1 0 "register_operand" "") > (fract_convert:FIXED1 (match_operand:FIXED2 1 > "register_operand" "")))] > "" > "* return fract_out (insn, operands, 1, NULL);" > [(set_attr "cc" "clobber")]) > > Basically it generates instructions for fixed point conversions, but I > found that in certain very unlikely cases, sometimes it calls > fract_out where one of the operands is in MEM and is not a register. > This caused my function to output incorrect assembly which could not > be assembled. > > I found that I can fix this problem by adding "=r" and "r" as follows: > > (define_insn "fract<FIXED2:mode><FIXED1:mode>2" > [(set (match_operand:FIXED1 0 "register_operand" "=r") > (fract_convert:FIXED1 (match_operand:FIXED2 1 > "register_operand" "r")))] > "" > "* return fract_out (insn, operands, 1, NULL);" > [(set_attr "cc" "clobber")]) > > > So I'm trying to understand this since I thought register_operand was > supposed to make things be in a register... I'm sure this is easy to > explain. Eventually I need to output instructions so one or the > other operands is allowed to be in MEM for efficiency reasons, but I > want to understand this first.
The predicates, like register_operand, are applied when an insn is recognized. An insn which does not meet those predicates is not recognized. However, before register allocation, the insn will be recognized with pseudo-registers. The register allocator may be unable to allocate the pseudo register to a real register. That will change the insn from using a REG to using a MEM. After the register allocator, the reload phase is responsible for making sure that all registers meet their constraints, like "r". If there are no constraints, the reload phase won't do anything, and the insn will continue to use a MEM. The reload phase uses constraints rather than predicates because the constraints are more specific, and because they tell reload what to do. If reload checked the predicate, and the predicate failed, reload would have no idea what to do. Constraints are associated with specific register classes, as well as general constraints like "m" or "g". When reload sees a constraint which is a register class and an operand which is not in a register, or is in a register in a class which does not match the constraint, then reload finds a register in that class, spilling if necessary, and introduces instructions to move the operand into an appropriate register. Ian