SCF Dialect
在 MLIR 的世界中高层级的方言如tosa、linalg负责处理宏观的业务逻辑或数学运算但它们最终都必须脚踏实地逐步“降级”Lowering到贴近甚至等价于机器指令的底层方言。首先为你介绍最基础、也是所有底层控制流的核心SCF DialectStructured Control Flow结构化控制流方言。1. SCF Dialect结构化控制流在传统的中间表示比如经典的 LLVM IR中控制流是通过显式的条件跳转指令类似于goto在不同的基本块Blocks之间切来切去实现的。这种扁平、破碎的控制流对机器很友好但对编译器优化特别是循环优化来说简直是噩梦。编译器不得不通过复杂的算法去分析哪些块组成了一个循环。SCF Dialect 的核心思想是保留高级语言中的高层控制流结构如if-else条件、for循环不急着把它们打碎。核心操作OperationsSCF 主要包含以下三个核心 Opscf.for表示带有显式步长的循环。它直接定义了循环变量induction variable、下界、上界和步长。scf.if表示条件分支。它包含一个then区域和一个可选的else区域。scf.while表示基于条件的循环通常用于处理无法在编译期确定迭代次数的复杂循环。语法示例scf.for看看一个标准的scf.for在 MLIR 中长什么样scf.for %i %lb to %ub step %step { // 循环体Region 内部的 Block %val dialect.some_op(%i) : (index) - f32 }%i是循环的索引变量。%lb(Lower Bound)、%ub(Upper Bound) 和%step控制了循环的执行范围。循环体被包裹在一个Region区域内部这意味着整个循环在空间结构上依然是一个完整的整体没有被拆散成无数个带标签的跳转块。为什么 SCF 至关重要让循环优化变得极其简单因为循环结构是显式保留的编译器做循环展开Loop Unrolling、循环重组Loop Tiling或循环交换Loop Interchange时不需要写复杂的图分析算法直接操作scf.for这个 Op 及其属性即可。支持 SSA 值的显式传递scf.for和scf.if还可以返回值通过scf.yield。这意味着你可以在循环迭代之间、或者条件分支之间以严格符合静态单赋值SSA规范的方式传递和更新数据而不需要依赖内存读写Alloca/Load/Store这极大地拉高了编译器的并行优化上限。当 SCF 完成了它在循环和条件分支上的优化使命后它会被进一步降级到更底层的方言如cf方言将结构化的循环真正打碎成带有跳转引脚Branch的扁平基本块。