#### 17.8.4 Constraint Modifier Characters

Here are constraint modifier characters.

‘`=`’

  Means that this operand is written to by this instruction: the previous value is discarded and replaced by new data.

‘`+`’

  Means that this operand is both read and written by the instruction.

  When the compiler fixes up the operands to satisfy the constraints, it needs to know which operands are read by the instruction and which are written by it. ‘`=`’ identifies an operand which is only written; ‘`+`’ identifies an operand that is both read and written; all other operands are assumed to only be read.

  If you specify ‘`=`’ or ‘`+`’ in a constraint, you put it in the first character of the constraint string.

‘`&`’

  Means (in a particular alternative) that this operand is an earlyclobber operand, which is written before the instruction is finished using the input operands. Therefore, this operand may not lie in a register that is read by the instruction or as part of any memory address.

  ‘`&`’ applies only to the alternative in which it is written. In constraints with multiple alternatives, sometimes one alternative requires ‘`&`’ while others do not. See, for example, the ‘`movdf`’ insn of the 68000.

  A operand which is read by the instruction can be tied to an earlyclobber operand if its only use as an input occurs before the early result is written. Adding alternatives of this form often allows GCC to produce better code when only some of the read operands can be affected by the earlyclobber. See, for example, the ‘`mulsi3`’ insn of the ARM.

  Furthermore, if the earlyclobber operand is also a read/write operand, then that operand is written only after it’s used.

  ‘`&`’ does not obviate the need to write ‘`=`’ or ‘`+`’. As earlyclobber operands are always written, a read-only earlyclobber operand is ill-formed and will be rejected by the compiler.

‘`%`’

  Declares the instruction to be commutative for this operand and the following operand. This means that the compiler may interchange the two operands if that is the cheapest way to make all operands fit the constraints. ‘`%`’ applies to all alternatives and must appear as the first character in the constraint. Only read-only operands can use ‘`%`’.

  This is often used in patterns for addition instructions that really have only two operands: the result must go in one of the arguments. Here for example, is how the 68000 halfword-add instruction is defined:

      (define_insn "addhi3"
        [(set (match_operand:HI 0 "general_operand" "=m,r")
           (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
                    (match_operand:HI 2 "general_operand" "di,g")))]
        …)

  GCC can only handle one commutative pair in an asm; if you use more, the compiler may fail. Note that you need not use the modifier if the two alternatives are strictly identical; this would only waste time in the reload pass. The modifier is not operational after register allocation, so the result of `define_peephole2` and `define_split`s performed after reload cannot rely on ‘`%`’ to make the intended insn match.

‘`#`’

  Says that all following characters, up to the next comma, are to be ignored as a constraint. They are significant only for choosing register preferences.

‘`*`’

  Says that the following character should be ignored when choosing register preferences. ‘`*`’ has no effect on the meaning of the constraint as a constraint, and no effect on reloading. For LRA ‘`*`’ additionally disparages slightly the alternative if the following character matches the operand.

  Here is an example: the 68000 has an instruction to sign-extend a halfword in a data register, and can also sign-extend a value by copying it into an address register. While either kind of register is acceptable, the constraints on an address-register destination are less strict, so it is best if register allocation makes an address register its goal. Therefore, ‘`*`’ is used so that the ‘`d`’ constraint letter (for data register) is ignored when computing register preferences.

      (define_insn "extendhisi2"
        [(set (match_operand:SI 0 "general_operand" "=*d,a")
              (sign_extend:SI
               (match_operand:HI 1 "general_operand" "0,g")))]
        …)