1

我想在使用 gcc 编译时保留所有死代码(或者任何明显可以优化的代码),但即使使用-O0,一些死代码仍然被优化。如何在不更改源代码的情况下保留所有代码?示例代码如下,使用 编译时g++ -S -O0 main.ccif-statement会在汇编代码中进行优化(没有cmpljmp代码)。

int main() {
  constexpr int a = 123; // or const int a = 0; I do not want to remove `const` or `constexpr` qualifier.
  if (a) // or just if (123)
    return 1;
  return 0;
}

一个相关的问题在这里:禁用 gcc 中的“if(0)”消除。但是那里的答案需要您更改我不想做的源代码(删除 const/constexpr 限定符)。

难道是我不更改我的源代码而只使用一些编译器标志来实现这一点?

4

1 回答 1

1

在这种情况下,GCC 不可能保持条件,因为它在编译的早期阶段就被删除了。

首先,这里是GCC的编译步骤:

  1. 以 GENERIC 表示 (HL-IR) 生成 AST 的代码解析(语法和语义)
  2. 高级 GIMPLE 生成 (ML-IR)
  3. 低级 GIMPLE 生成 (ML-IR)
  4. 树 SSA 优化 (ML-IR)
  5. RTL 生成 (LL-IR)
  6. 代码优化
  7. 装配代

在生成(理论上未优化的)高级 GIMPLE 表示之后,条件已经被删除。因此,在任何优化步骤之前。可以通过使用 GCC 标志检查这一点-fdump-tree-all并查看第一个生成的 GIMPLE 代码。结果如下:

;; Function int main() (null)
;; enabled by -tree-original
{
  const int a = 123;

  <<cleanup_point   const int a = 123;>>;
  return <retval> = 1;
  return <retval> = 0;
}
return <retval> = 0;

可以注意到,生成的代码与constexpr和相同const。实际上,在 HL GIMPLE 代码中constexpr被视为一个简单的const变量。

很难知道何时在步骤 1 中完全删除了条件,因为 GENERIC 是 GCC 的依赖于实现的内部表示。它不是很灵活/可定制。AFAIK,甚至还不可能生成 AST/GENERIC 表示。您可以使用一些 GCC 插件自己提取它,但这是一项非常棘手的任务。

于 2021-07-05T19:48:20.743 回答