Next: Insn Canonicalizations, Previous: Jump Patterns, Up: Machine Desc
一些机器具有特定的跳转指令,可以使循环更为有效。 常见的例子为68000的‘dbra’指令,其执行一个寄存器的递减, 并且如果结果大于0,则进行一个分支。其它机器,特别是数字信号处理器(DSP), 具有特定的块重复指令,以提供低成本的循环支持。 例如TI TMS320C3x/C4x DSP具有一个块重复指令, 其加载特定的寄存器来标记一个循环的顶部和底部,并计算循环迭代的次数。 这就避免了对‘dbra’这样的指令的取指和执行的需要, 并避免了和跳转相关的流水线阻塞。
GCC具有三个特定的命名指令模式,来支持低开销循环。
它们为‘decrement_and_branch_until_zero’, ‘doloop_begin’和‘doloop_end’。
第一个指令模式‘decrement_and_branch_until_zero’,在RTL生成过程中没有被产生,
但可以在指令合并阶段被产生。这需要循环优化器的帮助,
使用在strength reduction过程中所搜集的信息,来将一个循环转换为向下计数到0。
一些target还要求循环优化器增加一个REG_NONNEG
注解,来指示迭代计数总是为正的。
这在target执行一个有符号循环终止测试的时候被需要。例如,
68000为它的dbra
指令使用了下面类似的指令模式:
(define_insn "decrement_and_branch_until_zero" [(set (pc) (if_then_else (ge (plus:SI (match_operand:SI 0 "general_operand" "+d*am") (const_int -1)) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] "find_reg_note (insn, REG_NONNEG, 0)" "...")
注意,由于该insn为jump insn并且具有一个输出,所以其必须处理自己的重载, 因此要使用`m' constraint。还要注意,由于该insn是在指令组合过程中, 通过将两个连序insn组合成一个隐式并行的insn而生成的,所以迭代计数器需要。 注意下面类似的指令模式将不会被编译器匹配。
(define_insn "decrement_and_branch_until_zero" [(set (pc) (if_then_else (ge (match_operand:SI 0 "general_operand" "+d*am") (const_int 1)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] "find_reg_note (insn, REG_NONNEG, 0)" "...")
另外两个特定的循环指令模式‘doloop_begin’和‘doloop_end’, 由循环优化器为一些具有有限循环迭代, 使用强度消减所搜集的信息的良好行为的循环所生成的。
‘doloop_end’指令模式描述了实际的循环指令(或者隐式的循环操作), ‘doloop_begin’指令模式为一个可选的配套指令模式, 可以用于一些低开销循环指令的初始化需要。
注意有些机器需要在循环顶部生成实际的循环指令(例如TMS320C3x/C4x DSP)。 在循环顶部生成真正的RTL循环指令,会对流分析造成问题。所以,替换的, 一个假‘doloop’ insn在循环的结尾处被生成。 机器相关的reorg过程会检查该‘doloop’ insn的存在, 然后向后搜寻插入了真正循环insn(假设在循环中没有会造成问题的指令)的循环顶部。 任何额外的标号都可以在该点被生成。另外, 如果所需要的特定迭代技术器寄存器没有被分配, 则该机器相关的reorg过程能够生成一个传统的比较跳转指令对。
指令模式‘decrement_and_branch_until_zero’和‘doloop_end’的本质区别为, 循环优化器会为后者分配一个额外的伪寄存器作为迭代计数器。 该伪寄存器不能用在循环中(即,通用的规约变量不能由此生成),但是, 许多情况下循环规约变量可能变成冗余的并且被后续的过程移除掉。