为什么 C99 编译器不针对布尔值将“!a && b”优化为 "a < b"?
Why doesn't the C99 compiler optimize "!a && b" as "a < b" for booleans?
我看到了this really interesting tweet:
resisting my code golf instinct to turn if(!bool1 && bool2)
into if(bool1<bool2)
我以前从未见过,所以我想看看编译器是否也会使用这种优化。我用自述文件和测试 C 程序启动了一个回购协议:https://github.com/ndbroadbent/gcc_experiments
这里是测试程序:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
int main(int argc, const char* argv[]) {
if(argc != 3) {
printf("Usage: %s <a> <b>\n", argv[0]);
exit(1);
}
bool a = strtol(argv[1], NULL, 10) != 0;
bool b = strtol(argv[2], NULL, 10) != 0;
if (!a && b) {
printf("!a && b == true (a: %d, b: %d)\n", a, b);
} else {
printf("!a && b == false (a: %d, b: %d)\n", a, b);
}
}
我尝试用 gnu90
和 C99
标准编译这个程序。我知道 C99 有一个 bool
类型,但它仍然被视为整数,所以编译器不能根据布尔逻辑进行任何优化吗?
我可能读错了汇编,但看起来带有 -O3
的 C99 也包括 jne
和 je
指令,而不是只使用一个 "less than"操作和一个单一的跳转指令。看起来 C++ 也没有进行此优化。
编译器很清楚等价性并且能够基于它进行优化。不过,他们关于应该优化什么的想法可能是 opposite from yours。
为了完整起见,这里是执行 !a && b
的函数和执行“a < b”的函数的 clang 生成的汇编输出。两种情况下的汇编输出相同。
mov eax, edi
not al
and al, sil
ret
我看到了this really interesting tweet:
resisting my code golf instinct to turn
if(!bool1 && bool2)
intoif(bool1<bool2)
我以前从未见过,所以我想看看编译器是否也会使用这种优化。我用自述文件和测试 C 程序启动了一个回购协议:https://github.com/ndbroadbent/gcc_experiments
这里是测试程序:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
int main(int argc, const char* argv[]) {
if(argc != 3) {
printf("Usage: %s <a> <b>\n", argv[0]);
exit(1);
}
bool a = strtol(argv[1], NULL, 10) != 0;
bool b = strtol(argv[2], NULL, 10) != 0;
if (!a && b) {
printf("!a && b == true (a: %d, b: %d)\n", a, b);
} else {
printf("!a && b == false (a: %d, b: %d)\n", a, b);
}
}
我尝试用 gnu90
和 C99
标准编译这个程序。我知道 C99 有一个 bool
类型,但它仍然被视为整数,所以编译器不能根据布尔逻辑进行任何优化吗?
我可能读错了汇编,但看起来带有 -O3
的 C99 也包括 jne
和 je
指令,而不是只使用一个 "less than"操作和一个单一的跳转指令。看起来 C++ 也没有进行此优化。
编译器很清楚等价性并且能够基于它进行优化。不过,他们关于应该优化什么的想法可能是 opposite from yours。
为了完整起见,这里是执行 !a && b
的函数和执行“a < b”的函数的 clang 生成的汇编输出。两种情况下的汇编输出相同。
mov eax, edi
not al
and al, sil
ret