如何让 llvm 使用 'OR' 指令进行加速
How to get llvm to use the 'OR' instruction for speedup
我有一些 C 代码基本上可以归结为:
*p_Bool3 = *p_Bool1 || *p_Bool2;
其中 p_Bool1、p_Bool2 和 p_Bool3 为“bool *”。
clang++ 为我提供了使用 O2 的 X86 程序集(O3 没有区别,我只是使用 O2,因为那是实际项目中使用的):
mov eax, dword ptr [esp + 12]
mov edx, dword ptr [esp + 4]
mov cl, 1
cmp byte ptr [edx], 0
je LBB1_1
mov byte ptr [eax], cl
ret
LBB1_1:
mov ecx, dword ptr [esp + 8]
mov cl, byte ptr [ecx]
mov byte ptr [eax], cl
ret
实际程序有点复杂,有一堆 ob get 和 set 函数以及一些重载运算符,但它基本上是使用 O2 的相同汇编代码:
001de515 mov al, 0x01
001de517 mov ecx, dword ptr ds:[edi+0x00000628]
001de51d cmp byte ptr ds:[ecx], 0x00000000
001de520 jne 0x001DE52E
001de522 mov eax, dword ptr ds:[edi+0x0000065C]
001de528 cmp byte ptr ds:[eax], 0x00000000
001de52b setne al
001de52e mov ecx, dword ptr ds:[edi+0x000005EC]
001de534 mov byte ptr ds:[ecx], al
现在我有一些参考代码在相同的 hardware/system 上运行速度提高了 75%,如下所示:
0100121e lea ebx, dword ptr ds:[esi+0x10280005]
01001224 mov al, byte ptr ds:[ebx]
01001226 lea ebx, dword ptr ds:[esi+0x10280006]
0100122c or al, byte ptr ds:[ebx]
0100122e lea ebx, dword ptr ds:[esi+0x10280004]
01001234 mov byte ptr ds:[ebx], al
如何让 clang 仅使用 'or' 指令并更快?
您是否尝试过使用 *p_Bool3 = *p_Bool1 | *p_Bool2
中的 OR 运算符?编译器无法自行生成它,因为如果 p_Bool1
为真,则不允许取消引用 p_Bool2
。
如果您不能在此处使用 |
运算符,也应该首先手动解引用指针,告诉编译器允许这样做:
bool tmp1 = *p_Bool1, tmp2 = *p_Bool2;
*p_Bool3 = tmp1 || tmp2;
与 ||
运算符一起使用的 left/right 表达式被 延迟计算 。由于间接会导致副作用(例如页面错误、硬件影响),编译器需要使用条件来防止副作用在不应该发生的时候发生。
要避免此问题,您可以使用 |
运算符。 Here 是一个例子。
我有一些 C 代码基本上可以归结为:
*p_Bool3 = *p_Bool1 || *p_Bool2;
其中 p_Bool1、p_Bool2 和 p_Bool3 为“bool *”。
clang++ 为我提供了使用 O2 的 X86 程序集(O3 没有区别,我只是使用 O2,因为那是实际项目中使用的):
mov eax, dword ptr [esp + 12]
mov edx, dword ptr [esp + 4]
mov cl, 1
cmp byte ptr [edx], 0
je LBB1_1
mov byte ptr [eax], cl
ret
LBB1_1:
mov ecx, dword ptr [esp + 8]
mov cl, byte ptr [ecx]
mov byte ptr [eax], cl
ret
实际程序有点复杂,有一堆 ob get 和 set 函数以及一些重载运算符,但它基本上是使用 O2 的相同汇编代码:
001de515 mov al, 0x01
001de517 mov ecx, dword ptr ds:[edi+0x00000628]
001de51d cmp byte ptr ds:[ecx], 0x00000000
001de520 jne 0x001DE52E
001de522 mov eax, dword ptr ds:[edi+0x0000065C]
001de528 cmp byte ptr ds:[eax], 0x00000000
001de52b setne al
001de52e mov ecx, dword ptr ds:[edi+0x000005EC]
001de534 mov byte ptr ds:[ecx], al
现在我有一些参考代码在相同的 hardware/system 上运行速度提高了 75%,如下所示:
0100121e lea ebx, dword ptr ds:[esi+0x10280005]
01001224 mov al, byte ptr ds:[ebx]
01001226 lea ebx, dword ptr ds:[esi+0x10280006]
0100122c or al, byte ptr ds:[ebx]
0100122e lea ebx, dword ptr ds:[esi+0x10280004]
01001234 mov byte ptr ds:[ebx], al
如何让 clang 仅使用 'or' 指令并更快?
您是否尝试过使用 *p_Bool3 = *p_Bool1 | *p_Bool2
中的 OR 运算符?编译器无法自行生成它,因为如果 p_Bool1
为真,则不允许取消引用 p_Bool2
。
如果您不能在此处使用 |
运算符,也应该首先手动解引用指针,告诉编译器允许这样做:
bool tmp1 = *p_Bool1, tmp2 = *p_Bool2;
*p_Bool3 = tmp1 || tmp2;
与 ||
运算符一起使用的 left/right 表达式被 延迟计算 。由于间接会导致副作用(例如页面错误、硬件影响),编译器需要使用条件来防止副作用在不应该发生的时候发生。
要避免此问题,您可以使用 |
运算符。 Here 是一个例子。