使用 gcc 编译时禁用所有明显的消除(不更改我的源代码!)
disable all obvious elimination when compiling with gcc (without changing my source code!)
我想在用 gcc 编译时保留所有死代码(或任何明显可以优化的代码),但即使使用 -O0
,一些死代码仍然被优化。如何在不更改源代码 的情况下保留所有代码?示例代码如下,用g++ -S -O0 main.cc
编译时,if-statement
会在汇编代码中进行优化(不会有cmpl
和jmp
代码)。
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;
}
这里有一个相关问题:Disable "if(0)" elimination in gcc。但是那里的答案需要您更改源代码(删除 const/constexpr 限定符),我不想这样做。
难道我没有更改我的源代码,只是使用了一些编译器标志来实现这个?
在这种情况下,GCC 无法保留条件,因为它在编译的早期阶段就被删除了。
首先是GCC的编译步骤:
- 代码解析(语法和语义)生成 GENERIC 表示 (HL-IR) 中的 AST
- 高级 GIMPLE 生成 (ML-IR)
- 低级 GIMPLE 生成 (ML-IR)
- 树 SSA 优化 (ML-IR)
- RTL 生成 (LL-IR)
- 代码优化
- 程序集生成
在生成(理论上未优化的)高级 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
的结果代码相同。实际上,constexpr
在 HL GIMPLE 代码中被视为一个简单的 const
变量。
很难知道何时在步骤 1 中完全删除了条件,因为 GENERIC 是 GCC 的依赖于实现的内部表示。不是很flexible/customizable。 AFAIK,甚至还不可能生成 AST/GENERIC 表示。您可以使用一些 GCC 插件自行提取它,但这是一项非常棘手的任务。
我想在用 gcc 编译时保留所有死代码(或任何明显可以优化的代码),但即使使用 -O0
,一些死代码仍然被优化。如何在不更改源代码 的情况下保留所有代码?示例代码如下,用g++ -S -O0 main.cc
编译时,if-statement
会在汇编代码中进行优化(不会有cmpl
和jmp
代码)。
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;
}
这里有一个相关问题:Disable "if(0)" elimination in gcc。但是那里的答案需要您更改源代码(删除 const/constexpr 限定符),我不想这样做。
难道我没有更改我的源代码,只是使用了一些编译器标志来实现这个?
在这种情况下,GCC 无法保留条件,因为它在编译的早期阶段就被删除了。
首先是GCC的编译步骤:
- 代码解析(语法和语义)生成 GENERIC 表示 (HL-IR) 中的 AST
- 高级 GIMPLE 生成 (ML-IR)
- 低级 GIMPLE 生成 (ML-IR)
- 树 SSA 优化 (ML-IR)
- RTL 生成 (LL-IR)
- 代码优化
- 程序集生成
在生成(理论上未优化的)高级 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
的结果代码相同。实际上,constexpr
在 HL GIMPLE 代码中被视为一个简单的 const
变量。
很难知道何时在步骤 1 中完全删除了条件,因为 GENERIC 是 GCC 的依赖于实现的内部表示。不是很flexible/customizable。 AFAIK,甚至还不可能生成 AST/GENERIC 表示。您可以使用一些 GCC 插件自行提取它,但这是一项非常棘手的任务。