clang/llvm 为什么不优化这个?
Why doesn't clang/llvm optimize this?
使用 clang 3.9 编译此代码时:
constexpr bool is_small(long long v) {
return v < 0x4000000000000000;
}
int foo();
int f(int a) {
if (is_small(a)) return a;
else return foo();
}
它生成等同于 int f(int a) { return a; }
的程序集,因为它确定 is_small(a)
将始终为真,因为 a
是一个 int
,这(在我的平台上)总是小于 0x4000000000000000
.
当我将 is_small
更改为:
constexpr bool is_small(long long v) {
return v >= -0x4000000000000000;
}
正如预期的那样,情况完全相同。
但是,当我更改 is_small
以检查两个条件时:
constexpr bool is_small(long long v) {
return v < 0x4000000000000000 && v >= -0x4000000000000000;
}
clang 没有优化 if
和 return foo()
部分。
(这里是 Godbolt 上的上述片段,可以玩一下:https://godbolt.org/g/fnoE9A)
为什么会这样?它清楚地得出结论,条件单独总是正确的,为什么这不扩展到两者的逻辑合取?
没有充分的理由,这是 LLVM 缺少的优化。已归档 https://llvm.org/bugs/show_bug.cgi?id=30794 以确保它得到修复。
基本上 LLVM 会先优化 is_small
,然后再将其内联并优化 f() 中的使用。优化 is_small
时将比较 v < 0x4000000000000000 && v >= -0x4000000000000000
变成 v + 0x4000000000000000 > -1
的问题。内联后,优化器无法以允许不断折叠 f() 中的代码的方式识别这种新形式。
使用 clang 3.9 编译此代码时:
constexpr bool is_small(long long v) {
return v < 0x4000000000000000;
}
int foo();
int f(int a) {
if (is_small(a)) return a;
else return foo();
}
它生成等同于 int f(int a) { return a; }
的程序集,因为它确定 is_small(a)
将始终为真,因为 a
是一个 int
,这(在我的平台上)总是小于 0x4000000000000000
.
当我将 is_small
更改为:
constexpr bool is_small(long long v) {
return v >= -0x4000000000000000;
}
正如预期的那样,情况完全相同。
但是,当我更改 is_small
以检查两个条件时:
constexpr bool is_small(long long v) {
return v < 0x4000000000000000 && v >= -0x4000000000000000;
}
clang 没有优化 if
和 return foo()
部分。
(这里是 Godbolt 上的上述片段,可以玩一下:https://godbolt.org/g/fnoE9A)
为什么会这样?它清楚地得出结论,条件单独总是正确的,为什么这不扩展到两者的逻辑合取?
没有充分的理由,这是 LLVM 缺少的优化。已归档 https://llvm.org/bugs/show_bug.cgi?id=30794 以确保它得到修复。
基本上 LLVM 会先优化 is_small
,然后再将其内联并优化 f() 中的使用。优化 is_small
时将比较 v < 0x4000000000000000 && v >= -0x4000000000000000
变成 v + 0x4000000000000000 > -1
的问题。内联后,优化器无法以允许不断折叠 f() 中的代码的方式识别这种新形式。