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 没有优化 ifreturn 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() 中的代码的方式识别这种新形式。