如何使LLVM的`opt`命令优化内置函数?

问题描述

考虑以下C程序:

#include <stdlib.h>

int main() {
    int * ptr = malloc(8);
    *ptr = 14;
    return 4;
}

使用clang -S -emit-llvm -O1 emits the following进行编译:

...
; Function Attrs: norecurse nounwind readnone uwtable
define dso_local i32 @main() local_unnamed_addr #0 !dbg !7 {
  call void @llvm.dbg.value(Metadata i32* undef,Metadata !13,Metadata !DIExpression()),!dbg !15
  ret i32 4,!dbg !16
}
...

malloc调用已消失,因为它是clang知道的内置函数。 如果我们运行clang -S -emit-llvm -O1 -fno-builtin,则我们get the following

...
; Function Attrs: nounwind uwtable
define dso_local i32 @main() local_unnamed_addr #0 !dbg !14 {
  %1 = call noalias i8* @malloc(i64 8) #3,!dbg !22
  %2 = bitcast i8* %1 to i32*,!dbg !22
  call void @llvm.dbg.value(Metadata i32* %2,Metadata !20,!dbg !23
  store i32 14,i32* %2,align 4,!dbg !24,!tbaa !25
  ret i32 4,!dbg !29
}
...

clang不知道malloc是什么,必须将呼叫保留。

如何使用LLVM的opt命令从第二个LLVM程序转到第一个?如何告诉opt使用clang显然具有的有关内置函数的知识?

解决方法

在此特定示例中,问题在于clang -fno-builtin将产生LLVM代码,该代码显式标记使用nobuiltin(即attributes #3 = { nobuiltin nounwind "no-builtins" })对内置函数的调用。

通常,可以通过-targetlibinfo来猜测哪些内置功能可用。您必须小心地在正确的参数处声明和使用内置函数,然后返回类型,否则LLVM将(正确)将其识别为内置函数。