Clang 在 LLVM IR 中生成本地存储

标签 clang llvm llvm-ir

我正在通过 Clang 学习 LLVM IR,发现 C 函数如下:

int inc(int x)
{
  return x+1;
}

生成此 IR(优化已关闭):

define i32 @inc(i32 %x) #0 {
entry:
  %x.addr = alloca i32, align 4
  store i32 %x, i32* %x.addr, align 4
  %0 = load i32, i32* %x.addr, align 4
  %add = add nsw i32 %0, 1
  ret i32 %add
}

我的问题是确切地知道为什么它首先分配一个本地 (x.addr) 存储,然后从中加载。

最佳答案

因为这是未优化的代码。 Clang(前端)并没有花费太多(几乎没有?)时间来弄清楚如何使其发出的代码最佳。它将它留给后端优化(LLVM)。局部变量在未优化模式下“在堆栈上”,这意味着 alloca。这也意味着 x 有一个可寻址的位置,以后可能会用到也可能不会用到。如果不进行优化,编译器将不知道它是否会被使用,因此它无论如何都会保守地生成一个可寻址的位置。

int inc(int x)
{
  x = x + 1;
  int* px = &x;
  return x;
}

现在 Clang 发出:

define i32 @inc(i32 %x) #0 {
entry:
  %x.addr = alloca i32, align 4
  %px = alloca i32*, align 8
  store i32 %x, i32* %x.addr, align 4
  %0 = load i32, i32* %x.addr, align 4
  %add = add nsw i32 %0, 1
  store i32 %add, i32* %x.addr, align 4
  store i32* %x.addr, i32** %px, align 8
  %1 = load i32, i32* %x.addr, align 4
  ret i32 %1
}

看到现在用于指针的地址 %x.addr 了吗?

当然,如果你通过优化器运行它,你会得到:

define i32 @inc(i32 %x) #0 {
entry:
  %add = add nsw i32 %x, 1
  ret i32 %add
}

这可能更符合您对编译器的期望。

关于Clang 在 LLVM IR 中生成本地存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31450376/

相关文章:

c++ - clang ASTContext.getParents 总是返回一个空列表

clang - 糟糕的 rand() 实现

ios - 需要理解这个警告 "Attributes on method implementation and its declaration must match"

open-source - Apple 的 OpenCL 实现是否使用 CLang 和 LLVM 开源?

c++ - 插装代码导致无限递归循环

c++ - 集成 LLVM passes

objective-c - Xcode 存档 clang : error: cannot specify -o when generating multiple output files

macos - 如何在我的新 MacBook Pro(使用 Mac OS Catalina)上安装 openMP?

c++ - LLVM isa<> 是如何实现的?

c++ - 将 LLVM getOrInsertFunction 链接到 LLVM 传递中的外部 C++ 函数