Next: , Previous: Class Preferences, Up: Constraints


16.8.4 constraint修饰符

这里是约束修饰符。

=
意味着该指令的该操作数为只写的:先前的值将被丢弃并且由输出数据替换。


+
意味着该操作数可以由指令读和写。

当编译器修订操作数来满足约束时, 它需要知道哪些操作数为指令的输入以及哪些为它的输出。‘=’表示一个输出; ‘+’表示一个操作数同时为输入和输出;所有其它操作数将被认为只是输入。

如果你指定了‘=’或者‘+’,你要将它作为约束字符串的第一个字符。


&
意味着(在一个特别的可选项中)该操作数为一个earlyclobber操作数, 其在指令完成使用输入操作数之前就被修改了。 因此该操作数可能不在被用作输入操作数或者用作任何内存地址的一部分的寄存器中。

&’只应用于其所在的可选项。在具有多个可选项的约束中, 有时一个可选项需要‘&’,而其它的不需要。例如,参见68000的‘movdf’ insn。

一个输入操作数可以被限定为一个earlyclobber操作数, 如果它唯一的作为输入的使用发生在早期结果被写出之前。 增加这种形式的可选项经常可以允许GCC来产生更好的代码, 当只有一些输出可以被earlyclobber影响时。例如,参见ARM的‘mulsi3’ insn。

&’不排除对‘=’的需要。


%
声明指令对于该操作数和随后的操作数是可交换的。这意味着编译器可以交换两操作数, 如果有更廉价的方式来使得所有操作数都适合约束。 这经常被用于实际上只有两个操作数的加法指令中:结果必须放在一个参数中。 这里有个例子,是68000半字加指令如何被定义的:
          (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只能处理在asm中的一个可交换对;如果你有更多的,编译器将会失败。 注意如果两个可选项严格相同,则不需要使用该修饰符;这只会在重载过程浪费时间。 该修饰符在寄存器分配之后,是不可操作的, 所以在重载之后执行的define_peephole2define_split的结果不能依赖 ‘%’来进行insn匹配。


#
表示所有后续的字符,直到下一个逗号,作为约束都被忽略掉。 它们只对选择寄存器优先时有意义。


*
表示后续字符在选择寄存器优先时应该被忽略掉。‘*’对于重载没有影响。

这里有一个例子:68000有一条指令,用于在数据寄存器中符号扩展一个半字, 并且还可以通过将其复制到一个地址寄存器中来符号扩展一个值。 当每种寄存器都可以被接受时,对于地址寄存器的约束相对不是很严格, 所以最好是寄存器分配将地址寄存器作为其目标。 因此,‘*’被使用,以至于‘d’约束字母(数据寄存器)被忽略, 当计算寄存器优先时。

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