我需要做什么才能获得在编译器优化代码中调用的函数?

Ham*_*mer 4 c++ optimization compilation llvm ios

我正在研究和ios项目使用Apple LLVM 4.0进行优化编译.我实现了两个不同版本的函数,一个在C中,一个在NEON中.我想测试他们彼此的表现.我的想法是将它们称为相同的次数,然后在Time Profiler中查找它们以查看在每个中花费的相对时间.最初我的代码看起来像

used_value = score_squareNEON(patch, image, current_pos);
used_value = score_squareC(patch, image, current_pos);
Run Code Online (Sandbox Code Playgroud)

当我描述NEON代码根本没有出现的时候.接下来我试过了

for(int i = 0; i < successively_bigger_numbers; i++)
{
    used_value = score_squareNEON(patch, image, current_pos);
{
used_value = score_squareC(patch, image, current_pos);
Run Code Online (Sandbox Code Playgroud)

仍然没有NEON代码的贡献.接下来是

used_value = score_squareNEON(patch, image, current_pos);
test = score_squareC(patch, image, current_pos);
Run Code Online (Sandbox Code Playgroud)

测试从未被读过的地方.没有.然后

test = score_squareNEON(patch, image, current_pos);
test = 0;
other_used_variable += test;
used_value = score_squareC(patch, image, current_pos);
Run Code Online (Sandbox Code Playgroud)

依然没有.最终使它执行这两个功能的是

value = score_squareNEON(patch, image, current_pos);
test = score_squareC(patch, image, current_pos);
...
min = (value+test)/2; //before it was min=value;
Run Code Online (Sandbox Code Playgroud)

同样非常重要.这些函数都在我调用它们的同一个文件中定义.当我尝试将函数声明移动到另一个文件时,在每个示例中都会调用它们.

首先,我对编译器非常尊重.其次,我需要做些什么才能确保调用函数?这使我开始质疑我之前所有的事情.如果在正常模式下会怎么样?

timerStart();
functionCall();
timerEnd();
Run Code Online (Sandbox Code Playgroud)

中间的功能完全优化了吗?我是否需要每次都以某种方式开始检查,或者是否有我可以使用的技巧?当编译器优化整个函数调用时,有哪些规则可以控制?

Dan*_*her 5

同样非常重要.这些函数都在我调用它们的同一个文件中定义.当我尝试将函数声明移动到另一个文件时,在每个示例中都会调用它们.

当编译器可以证明函数调用没有副作用,并且未使用其结果时,它可以删除调用.如果无法证明,则无法删除调用,因为只要编译器可以知道,该函数可能有副作用,并且这些不能被消除.

声明变量将函数调用的结果赋给¹应该足以强制编译器在程序中保留函数调用(6.7.3,N1570中的第7段):

具有挥发性限定类型的对象可以以实现未知的方式修改或具有其他未知的副作用.因此,任何涉及这种对象的表达都应严格按照抽象机的规则进行评估,如5.1.2.3所述.此外,在每个序列点,最后存储在对象中的值应与抽象机器规定的值一致,除非由前面提到的未知因素修改.什么构成对具有volatile-quali fi ed类型的对象的访问是实现定义的.

对于C++,据我所知,保证不那么明确,但我认为1.9应该优先:

程序执行,1.9(6)和(7):

抽象机器的可观察行为是它对易失性数据的读写顺序以及对库I/O函数的调用.6)

访问由volatile lvalue(3.10)指定的对象,修改对象,调用库I/O函数或调用执行任何这些操作的函数都是副作用,这些都是执行环境状态的变化.表达的评估可能产生副作用.在称为序列点的执行序列中的某些特定点处,先前评估的所有副作用应该是完整的,并且不会发生后续评估的副作用.

在7.1.5.1中:

[注意:volatile是对实现的暗示,以避免涉及对象的激进优化,因为对象的值可能会被实现无法检测到的方式更改.有关详细语义,请参见1.9.一般来说,volatile的语义在C++中与在C中的相同.]

¹ void fun()当然,这不起作用.