1

我正在使用 LLVM C++ API 为 C 语言的子集编写编译器前端。我注意到生成的 IR 始终应用了恒定折叠优化。但我想禁用它并获得一个忠实的、未优化的 IR。有没有办法做到这一点?

以下是我使用模块生成 IR 的代码。

    llvm::verifyModule(kit.module, &llvm::outs());
    kit.module.print(llvm::outs(), nullptr);
    auto tirFile = "output.ir";
    error_code ec;
    llvm::raw_fd_ostream tirFileStream(tirFile, ec, llvm::sys::fs::F_None);
    kit.module.print(tirFileStream, nullptr);
    tirFileStream.flush();

似乎我使用的 LLVM 版本是 LLVM 10。

sumit@HAL9001:~$ llvm-config --version
10.0.0

例如,当我在以下 C 函数上运行编译器时

int arith() {
  return (10 - 10/3) << 3 | (23+8*12) & 1024;
}

它被编译为

define i32 @arith() {
entry:
  ret i32 56
}

常量的二元运算由编译器自己评估,即常量折叠;它没有被翻译成适当的 IR 代码。

4

2 回答 2

1

从此链接引用:

前端将代码降低到 IR 的方式导致这种常量折叠甚至在生成任何 LLVM IR 之前就发生了。本质上,当您进行 AST 遍历时,您将看到以下代码运行:

IRBuilder<> Builder; Value *LHS = Builder.getInt32(2); 
Value *RHS = Builder.getInt32(4); // LHS and RHS are ConstantInt values because they’re constant expressions.
Value *Res = Builder.CreateMul(LHS,RHS); // Because LHS and RHS are constant values, the IRBuilder folds this to a constant expression.

无法关闭此恒定折叠。(我还假设在 Clang AST 级别没有其他持续折叠)。

于 2020-12-11T08:17:52.957 回答
0

在 LLVM 11 中,您可以使用 IRBuilder<llvm::NoFolder>而不是IRBuilder<>

我很确定它也适用于 LLVM 10(尽管我尚未验证)。

不要忘记#include #include <llvm/IR/NoFolder.h>:)

于 2021-04-11T19:32:25.127 回答