Consider the following C program:
#include <stdlib.h>
int main() {
int * ptr = malloc(8);
*ptr = 14;
return 4;
}
Compiling with 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
}
...
The call to malloc is gone because it is a builtin function that clang knows about.
If we run clang -S -emit-llvm -O1 -fno-builtin instead we 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, metadata !DIExpression()), !dbg !23
store i32 14, i32* %2, align 4, !dbg !24, !tbaa !25
ret i32 4, !dbg !29
}
...
clang can't know what malloc is and has to leave the call in.
How can I get from the second LLVM program to the first using LLVM's opt command? How do I tell opt to use the knowledge about builtin functions that clang apparently has?
In this specific example, the problem is that
clang -fno-builtinwill produce LLVM code that explicitly marks calls to builtin functions withnobuiltin, i.e.attributes #3 = { nobuiltin nounwind "no-builtins" }.Generally, which builtin functions are available is guessed by pass
-targetlibinfo. You have to be careful to declare and use builtin functions at exactly the correct parameter and return types or LLVM will (correctly) not recognize them as builtins.