This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: putting operands in MEM even with register_operand predicate


"Sean D'Epagnier" <geckosenator@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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]