如果我这样做
typedef void Cb();
int foo(int const& a, Cb cb) {
int x = a;
cb();
return x - a;
}
并使用g++ -O3 -save-temps -c foo.cpp
进行编译,我看到减法被保留,而如果cb();
被注释掉,则整个函数优化为
xorl %eax, %eax
我可以对参数a
的规范做些什么,这样无论对cb()
的调用如何,都不会优化减法,也不会强制a
为唯一引用(即,它可以在别处引用,但是那些引用都不会被修改)?
答案 0 :(得分:15)
执行建议的优化是不正确的,因为其余代码可能是:
static int var;
void func()
{
var++;
}
// ...
foo(var, func);
我不知道您可以设置任何特定于编译器的属性来说cb()
不会修改a
。
答案 1 :(得分:15)
有__restrict
扩展程序,您可以在gcc.godbolt.org上尝试此操作:
typedef void Cb();
int foo(const int & __restrict a, Cb cb) {
int x = a;
cb();
return x - a;
}
奇怪的是,only clang does the optimization,gcc doesn't do it。
请注意,类似限制的别名被认为是C ++标准的一部分:
也许将来你可以按标准来做。
答案 2 :(得分:6)
为什么不在功能调用下移动int x = a;
行?
如果cb()
既不会影响x
也不影响a
,那么您应该这样做,我认为编译器会再次优化调用,因为x无法在两次调用之间发生变化。如果您无法重新排序这两个电话,您可能无法首先对其进行优化。
这不是你可以提示编译器要做的事情,因为在调用cb()
之后无法保证x和a都没有改变。
将此视为读/写访问顺序。如果在a
期间未对x
和cb()
发生读写访问,您可以手动重新排序函数调用。
如果写入a
或x
,则无法重新排序,优化也不正确。
如果读取了x
,则无法对函数调用进行重新排序,但如果只读取x
,则可以从中读取,并且仅在调用后定义x
如果您在通话前声明它,它将具有与a
相同的值。
答案 3 :(得分:5)
如果编译器支持该扩展,则可以在引用上使用C restrict
(某些编译器允许__restrict
或__restrict__
,它们是实现名称空间的一部分。)
这是您向编译器承诺的对象在任何地方都没有别名,因此可以对其进行优化。
如果你对编译器说谎,那么你就得到了你应得的破解代码。
答案 4 :(得分:-1)
__ attribute __((const))就够了
如下所述:https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Attributes.html,它告诉编译器给定的函数不会修改全局变量(尽管它可以读取它们)。
还有pure
的{{1}}子集,它也禁止全局读取。
考虑以下简化示例:
const
在int __attribute__((const)) g();
int f(int a) {
int x = a;
g();
return x - a;
}
4.8 x86_64 g++
上,汇编为:
-O3
与xor %eax,%eax
const
的大型函数在没有a
似乎没有更细粒度的属性表示函数不会根据需要修改给定的变量。
可以将__attribute __((const))应用于函数指针吗?
试试吧:
const
再一次,它编译为int f(int& a, void __attribute__((const)) (*g)(void)) {
int x = a;
(*g)();
return x - a;
}
,并编译为没有xor %eax,%eax
的大型函数,所以答案是肯定的。
在Function pointer to __attribute__((const)) function?
中询问了此语法它也出现在2011年的邮件列表上:http://comments.gmane.org/gmane.comp.gcc.help/38052至少在当时,它只适用于某些属性。
可以将__attribute __((const))添加到typedef吗?
这有效:
const
或:
typedef void __attribute__((const)) (*g_t)(void);
int f(int& a, g_t g) {
int x = a;
(*g)();
return x - a;
}
但我无法找到一种方法将属性放在typedef 和传递函数,而不是指针,如:
typedef void (g_t)(void);
int f(int& a, g_t __attribute__((const)) g) {
int x = a;
g();
return x - a;
}
GCC发出警告,说明在这种情况下该属性被忽略了。