if语句的“then”语句是否保证对应于相应分支的“未执行”路径?

huangapple go评论80阅读模式
英文:

Is the "then" statement of an if statement guaranteed to correspond to the "Not Taken" path of the corresponding branch?

问题

例如,在这段代码中:

if(x) {
    printf("A\n");
}
else {
    printf("B\n");
}

编译器组织了输出,以便当"x"为真时,分支被"不执行",从而执行了A。
我尝试添加likelyunlikely,并且这总是成立的:then语句总是对应于not taken

因此,我的问题是:这总是有保证的吗?

我对likely的理解是它应该为编译器提供关于如何布置事物的提示,所以在这种情况下被忽略了,因为它没有改变块的布局,我想知道是否有关于这一点的任何语言保证,或者编译器决定忽略了建议(或者只是还没有实现它)。

英文:

For example in this code:

if(x) {
    printf("A\n");
}
else {
    printf("B\n");
}

The compiler organized the output so that when "x" is true the branch is "not taken" and A executes.
I tried adding likely and unlikely and this was always the case: the then statement always corresponded to not taken.

So my question is: Is this always guaranteed to be the case?

My understanding of the likely was that it's supposed to give the compiler hints about how to lay things out, so it was ignored in this case since it didn't change the blocks layout and I'm wondering if there's any language guarantee on this or if the compiler decided to ignore the suggestion (or just didn't implement it yet).

答案1

得分: 1

代码部分不要翻译。

在语言标准中,根本没有说明编译后的机器指令中分支语句的布局方式。根据“as-if”规则,编译器可以以任何方式编译程序,只要可观察行为与抽象机器上允许的行为相匹配即可。机器指令中分支语句的布局方式不会影响可观察行为。

[[likely]][[unlikely]] 属性只是提示编译器,标记的路径在执行流程中可能比其他路径更或更不可能发生。编译器可以决定如何使用这些信息,或者是否使用。

因此,最多情况下,如果编译器未以最高性能的方式布局分支,假设启用了优化并且使用了 [[likely]][[unlikely]] 提供了必要的信息,这只是编译器实现质量的问题。但也有可能编译器实际上考虑了这些信息,但由于某种其他原因而采用了与预期不同的布局,例如,因为跳转指令可能更有效。在做出假设之前,请仔细分析您的特定测试案例,并在存在未优化的情况下提交错误报告。

此外,请确保编译器设置为 C++20 或更高版本,或者还支持先前标准版本中的属性。它们仅在 C++20 中引入,不支持的属性应该被忽略。在这种情况下,编译器可能会或可能不会发出警告。

英文:

There is nothing at all in the language standard that says anything about how branches are laid out in the compiled machine instructions. Under the as-if rule the compiler can compile the program in any way such that the observable behavior matches one that is permitted on the abstract machine. How branches are laid out in the machine instructions does not affect observable behavior.

The [[likely]] and [[unlikely]] attributes are only hints to the compiler that the marked path is more or less likely than other paths in the execution flow. It is up to the compiler to decide how or whether at all it uses that information.

So at most this is a quality-of-implementation issue for the compiler if it doesn't lay out the branches in the most performant way, assuming you have optimizations enabled and you are giving the necessary information with [[likely]] or [[unlikely]]. But maybe the compiler is actually taking that information in consideration but had some other reason to still do a different layout than you expect, e.g. because it may be more efficient of other reasons that the jump instruction. Analyse your specific test case carefully before making assumptions and file a bug report if there is a missed optimization.

Also, make sure that the compiler is set to C++20 or later mode or supports the attributes in previous standard versions as well. They were introduced only in C++20 and attributes that are unsupported should be ignored. Compilers may or may not give a warning in this case.

huangapple
  • 本文由 发表于 2023年7月28日 04:58:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76783371.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定