不指定函数参数求值的确切顺序如何帮助 C 和 C++ 编译器生成优化代码?
How not specify an exact order of evaluation of function argument helps C & C++ compiler to generate optimized code?
#include <iostream>
int foo() {
std::cout<<"foo() is called\n";
return 9;
}
int bar() {
std::cout<<"bar() is called\n";
return 18;
}
int main() {
std::cout<<foo()<<' '<<bar()<<' '<<'\n';
}
// Above program's behaviour is unspecified
// clang++ evaluates function arguments from left to right: http://melpon.org/wandbox/permlink/STnvMm1YVrrSRSsB
// g++ & MSVC++ evaluates function arguments from right to left
// so either foo() or bar() can be called first depending upon compiler.
上述程序的输出依赖于编译器。计算函数参数的顺序是 未指定。我读到这个的原因是它可以产生高度优化的代码。 不指定函数参数求值的确切顺序如何帮助编译器生成优化代码?
据我所知,Java、C#、D 等语言严格规定了求值顺序。
求值顺序与传递参数的方式有关。如果堆栈用于传递参数,从右到左求值有助于提高性能,因为这是将参数压入堆栈的方式。
例如,使用以下代码:
void foo(bar(), baz());
假设调用约定是 'passing arguments through the stack',C 调用约定要求从最后一个参数开始将参数压入堆栈 - 这样当被调用函数读取它时,它会首先弹出第一个参数并能够支持可变函数。如果评估顺序是从左到右,bar()
的结果必须保存在临时中,而不是 baz()
调用,它的结果被推送,然后是临时推送。但是,从右到左的评估允许编译器避免临时。
如果参数通过寄存器传递,求值顺序并不过分重要。
我认为问题的整个前提是错误的:
How not specify an exact order of evaluation of function argument helps C & C++ compiler to generate optimized code?
这与优化代码无关(尽管它确实允许这样做)。它是关于不惩罚编译器,因为底层硬件具有某些 ABI 约束。
一些系统依赖于以相反顺序将参数推入堆栈,而其他系统则依赖于正向顺序。 C++ 可在具有各种约束的各种系统上运行。如果您在语言级别执行命令,您将需要某些系统支付罚款才能执行该命令。
C++的第一条规则是"If you don't use it then you should not have to pay for it"。因此强制执行命令将违反 C++ 的基本指令。
没有。至少,今天不是。也许过去是这样。
A proposal for C++17 建议定义函数调用的左右求值顺序,operator<<
等等。
如该论文第 7 节所述,该提案通过编译 Windows NT 内核进行了测试,实际上它在某些基准测试中导致速度 提高 .作者评论:
It is worth noting that these results are for the worst case scenario where the optimizers have not yet been updated to be aware of, and take advantage of the new evaluation rules and they are blindly forced to evaluate function calls from left to right.
表明速度还有进一步提升的空间。
C 和 C++ 标准没有指定函数参数的计算顺序的最初原因是为编译器提供更多优化机会。不幸的是,在最初设计这些语言时,这个基本原理还没有得到广泛实验的支持。但这是有道理的。
这个问题在过去几年里一直被提出来。请参阅 Herb Sutter 的 this 博客 post,不要忘记阅读评论。
提案 P0145R1 建议最好为函数参数和其他运算符指定计算顺序。它说:
The order of expression evaluation, as
it is currently specified in the standard, undermines advices,
popular programming idioms, or the relative safety of standard library
facilities. The traps aren’t just for novices or the careless
programmer. They affect all of us indiscriminately, even when we know
the rules.
您可以在该文档中找到有关这如何影响优化机会的更多信息。
在过去的几个月里,人们对语言的这种变化如何影响优化、兼容性和可移植性进行了非常广泛的讨论。线程开始 here and continues here。你可以在那里找到很多例子。
#include <iostream>
int foo() {
std::cout<<"foo() is called\n";
return 9;
}
int bar() {
std::cout<<"bar() is called\n";
return 18;
}
int main() {
std::cout<<foo()<<' '<<bar()<<' '<<'\n';
}
// Above program's behaviour is unspecified
// clang++ evaluates function arguments from left to right: http://melpon.org/wandbox/permlink/STnvMm1YVrrSRSsB
// g++ & MSVC++ evaluates function arguments from right to left
// so either foo() or bar() can be called first depending upon compiler.
上述程序的输出依赖于编译器。计算函数参数的顺序是 未指定。我读到这个的原因是它可以产生高度优化的代码。 不指定函数参数求值的确切顺序如何帮助编译器生成优化代码?
据我所知,Java、C#、D 等语言严格规定了求值顺序。
求值顺序与传递参数的方式有关。如果堆栈用于传递参数,从右到左求值有助于提高性能,因为这是将参数压入堆栈的方式。
例如,使用以下代码:
void foo(bar(), baz());
假设调用约定是 'passing arguments through the stack',C 调用约定要求从最后一个参数开始将参数压入堆栈 - 这样当被调用函数读取它时,它会首先弹出第一个参数并能够支持可变函数。如果评估顺序是从左到右,bar()
的结果必须保存在临时中,而不是 baz()
调用,它的结果被推送,然后是临时推送。但是,从右到左的评估允许编译器避免临时。
如果参数通过寄存器传递,求值顺序并不过分重要。
我认为问题的整个前提是错误的:
How not specify an exact order of evaluation of function argument helps C & C++ compiler to generate optimized code?
这与优化代码无关(尽管它确实允许这样做)。它是关于不惩罚编译器,因为底层硬件具有某些 ABI 约束。
一些系统依赖于以相反顺序将参数推入堆栈,而其他系统则依赖于正向顺序。 C++ 可在具有各种约束的各种系统上运行。如果您在语言级别执行命令,您将需要某些系统支付罚款才能执行该命令。
C++的第一条规则是"If you don't use it then you should not have to pay for it"。因此强制执行命令将违反 C++ 的基本指令。
没有。至少,今天不是。也许过去是这样。
A proposal for C++17 建议定义函数调用的左右求值顺序,operator<<
等等。
如该论文第 7 节所述,该提案通过编译 Windows NT 内核进行了测试,实际上它在某些基准测试中导致速度 提高 .作者评论:
It is worth noting that these results are for the worst case scenario where the optimizers have not yet been updated to be aware of, and take advantage of the new evaluation rules and they are blindly forced to evaluate function calls from left to right.
表明速度还有进一步提升的空间。
C 和 C++ 标准没有指定函数参数的计算顺序的最初原因是为编译器提供更多优化机会。不幸的是,在最初设计这些语言时,这个基本原理还没有得到广泛实验的支持。但这是有道理的。
这个问题在过去几年里一直被提出来。请参阅 Herb Sutter 的 this 博客 post,不要忘记阅读评论。
提案 P0145R1 建议最好为函数参数和其他运算符指定计算顺序。它说:
The order of expression evaluation, as it is currently specified in the standard, undermines advices, popular programming idioms, or the relative safety of standard library facilities. The traps aren’t just for novices or the careless programmer. They affect all of us indiscriminately, even when we know the rules.
您可以在该文档中找到有关这如何影响优化机会的更多信息。
在过去的几个月里,人们对语言的这种变化如何影响优化、兼容性和可移植性进行了非常广泛的讨论。线程开始 here and continues here。你可以在那里找到很多例子。