我试图最小化我编译的汇编代码中分支指令的数量,用于特定架构,由于处理器流水线的实现方式,分支指令的成本非常高。
我可以尝试实现自修改代码以减少在条件分支中必须测试条件的次数,但是我还有其他可以做的事情吗?
你不应该太在意编译代码中可见的分支指令的数量。您应该关心运行程序时在 CPU 上执行分支指令的次数。
减少执行分支数量的两种简单方法:
如果您的架构支持谓词指令,则if
可以使用谓词指令而不是分支生成小块。您可以要求您的编译器为您执行此操作。例如,如果您的编译器是 GCC,则使用 编译-O1, -O2, -O3 or -Os
或使用-fif-conversion2
标志应该这样做。
请记住:if
大块不会进行 if 转换,因为无论条件是否为真,谓词指令都会通过 CPU 流水线。这浪费了周期。
展开循环。循环意味着分支。如果展开它,您可以执行更少的分支(尽管在编译的代码中,您仍然“看到”相同数量的分支指令,对吧?)。
但请记住:这会增加代码大小。这可能意味着指令缓存上的未命中率增加。
例如:
for (i = 0; i < N; i++)
{
LOOP_BODY;
}
如果已知 N 是偶数,则手动展开两次很简单:
for (i = 0; i < N; i++)
{
LOOP_BODY;
i++;
LOOP_BODY;
}
当它执行时,执行的分支数量基本上减半。
同样,您的编译器也可能会自动执行此操作。例如,GCC 使用 . 展开一些循环-funroll-loops
。
编译器还可以为您做一些其他的技巧。例如,如果它是 GCC,那么您可能应该在此页面中搜索 'branch'。