以下是我声称完成同样事情的两个功能:
bool fast(int x)
{
return x & 4242;
}
bool slow(int x)
{
return x && (x & 4242);
}
Run Code Online (Sandbox Code Playgroud)
从逻辑上讲,他们做同样的事情,只是为了100%肯定我写了一个测试,通过他们两个运行所有40亿个可能的输入,并且他们匹配.但汇编代码是一个不同的故事:
fast:
andl $4242, %edi
setne %al
ret
slow:
xorl %eax, %eax
testl %edi, %edi
je .L3
andl $4242, %edi
setne %al
.L3:
rep
ret
Run Code Online (Sandbox Code Playgroud)
令我感到惊讶的是,GCC无法实现消除冗余测试的逻辑上的飞跃.我用-O2,-O3和-Os尝试了g ++ 4.4.3和4.7.2,所有这些都生成了相同的代码.该平台是Linux x86_64.
有人可以解释为什么GCC不够聪明,不能在两种情况下生成相同的代码吗?我还想知道其他编译器是否可以做得更好.
编辑以添加测试工具:
#include <cstdlib>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
// make vector filled with numbers starting from argv[1]
int seed = atoi(argv[1]);
vector<int> v(100000); …Run Code Online (Sandbox Code Playgroud) 我正在阅读Agner Fog的" 用C++优化软件 "(特定于英特尔,AMD和威盛的x86处理器),它在第34页说明
布尔变量存储为8位整数,值0表示false,1表示true.布尔变量是超定的,因为所有具有布尔变量作为输入的运算符检查输入是否具有除0或1之外的任何其他值,但是具有布尔值作为输出的运算符不能产生除0或1之外的其他值.布尔变量作为输入效率低于必要的效率.
这今天仍然适用于编译器吗?你能举个例子吗?作者说
如果确定操作数没有除0和1之外的其他值,则可以使布尔运算更有效.编译器没有做出这样的假设的原因是变量可能具有其他值,如果它们是未初始化或来自不明来源.
这是否意味着如果我拿一个函数指针bool(*)()作为示例并调用它,那么对它的操作会产生效率低下的代码?或者是通过取消引用指针或从引用读取然后对其进行操作来访问布尔值的情况?
#include <iostream>
int main(int argc, char* argv[])
{
unsigned long mask = 0x00000001;
unsigned long mask1 = 0x00000001;
unsigned long mask2 = 0x00000010;
if ((mask and mask1) && (mask and mask2))// CONDITION_1 is True.
std::cout << "Ohhhhhhh..." << std::endl;
if ((mask & mask1) && (mask & mask2)) //CONDITION_2 is False.
std::cout << "No Output..." << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我认为CONDITION_1和CONDITION_2都是假的,但我的想法显然是错误的,为什么'和'和'&'在C++中不一样?