ZHCU881D May 2020 – May 2024
为了对循环形成软件流水线(从而提高性能),循环中唯一可能出现的分支是返回到循环顶部的分支。if-then 和 if-then-else 语句的分支或其他控制流构造的分支将阻止软件流水线。
为了摆脱这种限制,编译器进行了 if-conversion。通过预测指令以便根据“if”语句中的测试有条件地执行指令,if-conversion 尝试删除 if-then 和 if-then-else 语句相关联的分支。只要 if-then 或 if-then-else 语句中没有太多嵌套级、太多条件项或太多指令,if-conversion 通常会成功。
下述示例演示了 if-conversion。为了对此 C++ 代码中的“for”循环形成软件流水线,必须进行 if-conversion。pragma 用于防止编译器矢量化和生成对本例不重要的附加代码。
// if_conversion.cpp
// Compile with "cl7x -mv7100 --opt_level=3 --debug_software_pipeline
// --src_interlist --symdebug:none if_conversion.cpp"
void function_1(int * restrict a, int *restrict b, int *restrict out, int n)
{
#pragma UNROLL(1)
#pragma MUST_ITERATE(1024, ,32)
for (int i = 0; i < n; i++)
{
int result;
if (a[i] < b[i])
result = a[i] + b[i];
else
result = 0;
out [i] = result;
}
}
编译后,软件流水线信息注释块中循环的单次调度迭代如下所示:
;*----------------------------------------------------------------------------*
;* SINGLE SCHEDULED ITERATION
;*
;* ||$C$C65||:
;* 0 TICK ; [A_U]
;* 1 SLDW .D1 *D2++(4),A1 ; [A_D1] |17| ^
;* || SLDW .D2 *D1++(4),A2 ; [A_D2] |17| ^
;* 2 NOP 0x5 ; [A_B]
;* 7 CMPGEW .L1 A2,A1,A0 ; [A_L1] |17| ^
;* 8 [!A0] ADDW .D2 A1,A2,D3 ; [A_D2] |17| ^
;* 9 [ A0] MVKU32 .S1 0,D3 ; [A_S1] |17|
;* 10 STW .D1 D3,*D0++(4) ; [A_D1] |17|
;* || BNL .B1 ||$C$C65|| ; [A_B] |9|
;* 11 ; BRANCHCC OCCURS {||$C$C65||} ; [] |9|
;*----------------------------------------------------------------------------
指令 [!A0] ADDW.D2 A1,A2,D3
代表 if 语句的“then”部分。指令 [A0] MVK32.S1 0,D3
代表 if 语句的“else”部分。CMPGEW 指令计算 if-condition 并将结果放入谓词寄存器,用于有条件地执行 ADDW 和 MVKU32 指令。