我正试图理解SPIR规范,比如对循环的理解。在1.6修订版2规范的开头,下面的示例(只考虑到其中的一部分)
for (int i = 0; i < 4; ++i)
color *= multiplier;变成:
%49 = OpLabel
OpLoopMerge %51 %52 None ; structured loop
OpBranch %53
%53 = OpLabel
%54 = OpLoad %16 %48
%56 = OpSLessThan %25 %54 %55 ; i < 4 ?
OpBranchConditional %56 %50 %51 ; body or break
%50 = OpLabel ; body
%58 = OpLoad %7 %57
%59 = OpLoad %7 %31
%60 = OpFMul %7 %59 %58
OpStore %31 %60
OpBranch %52
%52 = OpLabel ; continue target
%61 = OpLoad %16 %48
%62 = OpIAdd %16 %61 %21 ; ++i
OpStore %48 %62
OpBranch %49 ; loop back
%51 = OpLabel ; loop merge point
OpReturn
OpFunctionEnd在规范中,它指定以标签开头的块,以任意分支终止指令结尾。这将上述情况转化为以下几点:
;Block 1
%49 = OpLabel
OpLoopMerge %51 %52 None ; structured loop
OpBranch %53
;Block 2
%53 = OpLabel
%54 = OpLoad %16 %48
%56 = OpSLessThan %25 %54 %55 ; i < 4 ?
OpBranchConditional %56 %50 %51 ; body or break
;Block 3
%50 = OpLabel ; body
%58 = OpLoad %7 %57
%59 = OpLoad %7 %31
%60 = OpFMul %7 %59 %58
OpStore %31 %60
OpBranch %52
;Block 4
%52 = OpLabel ; continue target
%61 = OpLoad %16 %48
%62 = OpIAdd %16 %61 %21 ; ++i
OpStore %48 %62
OpBranch %49 ; loop back
;Block 5
%51 = OpLabel ; loop merge point
OpReturn
OpFunctionEnd然后,规范规定:
头块:包含合并指令的块。循环头:合并指令为OpLoopMerge的头块
所以这里的循环头是块1,OpLoopMerge位于这里。
OpLoopMerge声称有三个参数,其中两个参数在这里很重要:
合并块是此结构化循环的合并块的标签。继续目标是用于处理循环“继续”的块的标签。
合并块
合并块:由合并指令的合并块操作数声明的块。
我的理解是,当“结构化循环/选择”结束时,在这个例子中,它就在函数的末尾,第5块,这对我来说是有意义的。
继续的目标对我来说还不清楚。这里的继续目标是块4,根据op循环合并指令。为什么继续目标不是块3?还是2号街区?是什么使第4块成为这里的继续目标?是因为它是最终决定退出或继续循环的块吗?这就是“处理循环”的意思吗?
发布于 2022-09-18 06:12:28
“继续目标”的存在是为了满足大多数语言中continue控制流指令的需要。在高级语言中,可以在循环中发出continue语句.这将跳转到循环中的下一次迭代。
“继续目标”是开始下一次迭代的循环代码的一部分。您可以直接从continue语句分支到这里,也可以从循环主体的末尾分支到这里。
如果源包含一个continue语句,那将是循环主体的一部分,在您的示例中是块3。因此没有理由将其作为继续目标;这将导致无限循环,因为从来没有检查过实际的终端条件,迭代表达式也没有被计算。
第二座也没什么意义。当您执行continue循环时,必须执行迭代表达式。重复终端条件不会有帮助,因为它显然已经通过了。这就是它开始进入循环体的原因。在计算迭代表达式之前,终端条件将继续传递。再一次,一个无限的循环会产生。
https://stackoverflow.com/questions/73760313
复制相似问题