【发布时间】:2020-06-24 14:33:17
【问题描述】:
我花了几个小时试图将以下代码转换为内联汇编 (GCC),但没有成功:
int new_low = mid + 1;
int new_high = mid - 1;
if (middle < key) {
low = new_low;
}
if (!(middle < key)) {
high = new_high;
}
我希望编译器优化掉那些 if,而使用条件移动。不幸的是,编译器不断产生跳转。我尝试编写内联汇编,但我不擅长它,而且寄存器破坏存在一些问题,我无法正确处理。我做错了什么?
__asm__ (
"cmp %[array_middle], %[key];"
"cmovb %[new_low], %[low];"
"cmovae %[new_high], %[high];"
: [low] "=&r"(low), [high] "=&r"(high)
: [new_low] "r"(new_low), [new_high] "r"(new_high), [array_middle] "r"(middle), [key] "r"(key)
: "cc"
);
【问题讨论】:
-
你是如何调用 GCC 的?
-
"寄存器损坏有一些问题,我无法正确处理。" 这不是问题描述。您看到的具体问题是什么?
-
你试过像
low = (middle < key) ? new_low : low;这样的三元运算符吗?您是否尝试过配置文件引导优化,因此 GCC 可以看到该分支实际上不是很可预测? (gcc optimization flag -O3 makes code slower than -O2 表明 if 转换为无分支通常仅在-O3处完成,至少在某些情况下)。另外,请记住,无分支会创建数据依赖关系,这对于二分搜索可能会更糟;推测执行有效地为您提供内存并行/预取,而不是序列化加载。 -
使用使用
low加上size而不是low和high的二分搜索。这意味着您只需要一个条件(如果针在高半部分,则更新基数),并且可以无条件更新大小(减半)。这通常会导致cmov。
标签: gcc x86 inline-assembly conditional-move