是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数


#include <iostream>
int ExpensiveFunction() {
// Do expensive calculation
// ...
std::cout << "You shouldn't see this!" << std::endl;
return 42;
}
void print(int num)
{
}
int main()
{
print(ExpensiveFunction());
return 0;
}

我希望编译器识别print是一个空函数,从而完全删除print调用和语句的参数评估:

print(ExpensiveFunction());

然而,无论我使用哪种优化设置(使用MSVC(,它都将始终执行昂贵函数的计算。

我认识到,删除对ExpensiveFunction调用的优化可能是一种破坏性的优化,但我认为这应该是可能的,而无需将打印转换为将在最优化的配置中编译出来的宏。

有没有可能指导任何C++编译器这样做?

编辑:我添加了一个std::cout语句

有可能指导任何C++编译器这样做吗?

可能不是直接的-这是一个实现质量问题。

Clang和GCC(对于最近测试的版本(都使用标准的-O3标志来执行此操作。实际上,他们甚至用-O1-O2。。。您必须完全禁用优化,以便它们发出对ExpensiveFunction的调用。

使用x64 MSVC 19.24进行快速尝试表明,它也会优化调用,至少使用/O2

此处列出了MSVC命令行选项。

GCC命令行选项在手册中,优化特定选项在这里。

一般来说,你可以通过Matt Godbolt的编译器资源管理器看到几个不同的编译器同时对同一代码做什么,就像这样


请注意,这只是在测试您的样本代码-如果ExpensiveFunction有可观察到的副作用,优化器将无法删除它。


编辑,因此ExpensiveFunction确实有明显的副作用。

我认识到,删除对ExpensiveFunction调用的优化可能是一种破坏性优化,

没有所谓的"破坏性优化"。优化是指在不改变功能特性的情况下改善程序的非功能特性(通常是性能或大小(,功能特性被专门定义为可见的副作用。

让我们考虑一下你的标题,根据问题的正文进行更正:

是否有C++编译器选项允许主动删除所有函数调用,并将参数传递给非空体的函数?

如果编译器可以通过丢弃需要时间的东西来加快代码的速度,即使它们具有外部可观察的效果,生活也变得非常简单:它可以用替换每个程序

int main() {}

并称之为"破坏性优化"。这是你更正标题的正确解决方案,对吧?

。。。但我觉得这应该是可能的,而无需将打印转换为将以最优化的配置编译出来的宏。

您也可以将ExpensiveFunction的主体设为有条件的,例如,如果它确实是调试输出,您希望在某些构建中禁用其可观察的副作用

int ExpensiveFunction() {
#ifndef DEBUG
// Do expensive calculation
// ...
std::cout << "You shouldn't see this!" << std::endl;
#endif
return 42;
}

但是禁用具有可观察到的副作用的代码必须始终在您的手动控制之下,除非您对我上面的额外简化的整个程序优化感到满意。

对于GCC和Clang,可以使用__attribute__((pure))向编译器保证ExpensiveFunction()没有任何副作用,如果不使用其结果,则可以将其删除。在一些简单的情况下,这些编译器无论如何都可以计算出函数的纯性,但使用属性可以在更复杂的情况下以及在其他翻译单元中定义的函数中获得这种效果。

不幸的是,据我所知,微软风投公司没有任何类似的设施。有关详细信息,请参阅不同编译器中的纯/常量函数属性。

对于MSVC,您需要/O2(优化(、/GL+/LTCG(链接时代码生成(和/OPT:REF(消除从未引用的函数和数据(。