Next: Output Template, Previous: Example, Up: Machine Desc
RTL模板用来定义哪些insn匹配特定的模式,以及如何找到它们的操作数。对于命名的模 式,RTL模板还说明了如何根据特定的操作数来构建一个insn。
构建insn涉及到替换指定操作数到模板。匹配insn涉及到测定被匹配insn的操作数值。这 些匹配和替换操作数的行为都是由专门的表达式类型来控制。
(match_operand:
m n predicate constraint)
每个指令模式中的操作数编号必须从0开始连续的选择。在指令模式中,可以对每个操作数
编号只是用一个 match_operand
表达式。 通常操作数按照在
match_operand
表达式中出现的顺序被编号。对于 define_expand
,任何
使用的操作数编号,只有在 match_dup
表达式中才会具有比其它操作数编号更高
的值。
predicate 为一个字符串,为一个函数的名字,其接受两个参数,一个表达式和一个 机器模式。参见Predicates。在匹配过程中,函数将会被调用,使用假定的操作数作为 表达式并且 m 作为机器模式参数(如果 m 没有被指定,则使用 VOIDmode
,这通常会使得 predicate 可以接受任何机器模式)。如果其返 回0,则该指令模式匹配失败。predicate 可以为一个空字符串;这意味着不对操作 数作测试,这样出现在该位置的任何都是有效的。
大多时候,predicate 将会拒绝 m 之外的机器模式——但并不总是这样。例 如,predicate address_operand
使用 m 作为内存引用的机器模式。许多predicate 接受 const_int
节点,即使它们的机器模式为 VOIDmode
。
constraint 控制重载以及针对一个值选择最好的寄存器类别来使用,将在后面解释 (参见Constraints)。如果constraint为空字符串,则可以忽略掉。
人们经常弄不清楚constraint和predicate的区别。predicate帮助决定一个给定的insn是否匹配指令模式。constraint在该决定中不发挥作用;替代的,其控制已经匹配的insn的各种决定。
(match_scratch:
m n constraint)
scratch
或者 reg
表达式。
当在匹配指令模式时,其相当于
(match_operand:m n "scratch_operand" pred)
但是,当在生成RTL时,其产生一个(scratch
:m)表达式。
如果在一个 parallel
中的最后几个表达式为 clobber
表达式,其操作数
为一个硬寄存器或者 match_scratch
,则组合器可以在需要的时候增加或删除它
们。参见Side Effects。
(match_dup
n)
在构建过程中,match_dup
的作用就跟 match_operand
一样。操作数被
替换到正在被构建的insn中。但是在匹配时,match_dup
的行为就有所不同了。
其假设操作数编号 n 已经由在识别模板中之前出现的 match_operand
确
定了,其只匹配相同的表达式。
注意 match_dup
不要用来告诉编译器特定寄存器被用于两个操作数(例如:
add
将一个寄存器加到另一个之上;第二个寄存器即为输入操作数,同样也为输
出操作数)。可以为此使用匹配constraint(参见Simple Constraints)。match_dup
是用于一个操作数在模板中的两个地方被使用的情况,例如一条指令同时计算商和余数,
其中操作码接受两个输入操作数,但是RTL模板不得不引用它们两次;一次用于求商指令
模式,一次用于求余数指令模式。
(match_operator:
m n predicate [
operands...])
当构造一个insn时,其代表RTL表达式,其表达式代码取自操作数 n,并且其操作 数从指令模式 operands 中构造。
当匹配一个表达式时,其匹配一个表达式,如果函数 predicate 对于该表达式返 回非零,并且 指令模式 operands 匹配表达式的操作数。
假设函数 commutative_operator
被如下定义,来匹配任何表达式,其操作符为
RTL中可交换的算术操作符,并且其机器模式为 mode:
int commutative_integer_operator (x, mode) rtx x; enum machine_mode mode; { enum rtx_code code = GET_CODE (x); if (GET_MODE (x) != mode) return 0; return (GET_RTX_CLASS (code) == RTX_COMM_ARITH || code == EQ || code == NE); }
那么下列指令模式将匹配任何RTL表达式,其由一个可交换操作符和两个通用操作数组成:
(match_operator:SI 3 "commutative_operator" [(match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")])
这里的向量 [
operands...]
包含了两个指令模式,因为要匹配的表达
式都是包含两个操作数。
当该指令模式确实匹配时,可交换操作符的两个操作数被记录为insn的操作数1和2。(这
由 match_operand
的两个实例完成)。insn的操作数3将为整个可交换表达式:使
用 GET_CODE (operands[3])
来查看使用了哪个可交换操作符。
match_operator
的机器模式 m 的作用与 match_operand
的类似:
其被作为第二个参数传递给predicate函数,并且函数专门负责决定被匹配的表达式是否具有那
个机器模式。
当构造insn时,gen-function 的参数3将会指定要构造的表达式的操作(即,表达式代 码)。其应该为一个RTL表达式,其表达式代码被复制到一个新的表达式中,新表达式的 操作数为 gen-function的参数1和2。参数3的子表达式不被使用;只与它的表达式代码 有关。
当 match_operator
被用于指令模式中来匹配insn时,通常最好让
match_operator
的操作数编号高于insn的实际操作数。这将提高寄存器分配,
因为寄存器分配者通常查看insn的操作数1和2,来看是否它可以做寄存器绑定
(register tying)。
无法指定在 match_operator
中的constraint。对应于 match_operator
的
insn的操作数,不具有任何constraint,因为它从来不作为一个整体被重载。但是,如果它
的 operands 的一部分被 match_operand
指令模式匹配,那些部分可
以具有它们自己的constraint。
(match_op_dup:
m n[
operands...])
match_dup
,除了其应用于操作符而不是操作数。当构造insn时,操作数
编号 n 将在这一点被替代。但是在匹配时,match_op_dup
的行为有所
不同。其假设操作数编号 n 已经被在识别模板中先前出现的
match_operator
所确定,并且其只匹配identical-looking的表达式。
(match_parallel
n predicate [
subpat...])
parallel
表达式组成。该表达式应该只在insn指令模式的顶层出现。
当构造insn时,操作数编号 n 将在该处被替换。当匹配一个insn时,其当insn
的主体为一个 parallel
表达式,其具有至少跟向量 subpat 表达式同
样多数目元素,并且函数 predicate 返回非零时才匹配。predicate负责判定在
match_parallel
中的 parallel
的元素是否有效。
match_parallel
的一个典型用法是,匹配加载和存储多个表达式,其可以在
parallel
中包含一个可变数目的元素。例如,
(define_insn "" [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 1 "gpc_reg_operand" "=r") (match_operand:SI 2 "memory_operand" "m")) (use (reg:SI 179)) (clobber (reg:SI 179))])] "" "loadm 0,0,%1,%2")
这个例子来自 a29k.md。函数 load_multiple_operation
在
a29k.c 中定义,其检查在 parallel
中的序列元素,是否与在
指令模式中的 set
相同,除非它们在引用后续的寄存器和内存位置。
匹配该指令模式的insn可能看起来像:
(parallel [(set (reg:SI 20) (mem:SI (reg:SI 100))) (use (reg:SI 179)) (clobber (reg:SI 179)) (set (reg:SI 21) (mem:SI (plus:SI (reg:SI 100) (const_int 4)))) (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 100) (const_int 8))))])
(match_par_dup
n [
subpat...])
match_op_dup
类似,但是针对于 match_parallel
,而不是
match_operator
。