How do I eliminate LLVM function calls and replace them with basic instructions? - c++

My Problem
I am new to LLVM and C++.
I am currently creating an LLVM backend compiler and need to replace LLVM function calls with the instructions in its definition.
Is there already an existing pass that accomplishes this?
Examples
For example, I have the following C code, compiled to LLVM IR with clang-14 -S -emit-llvm.
int add(int a, int b) {
return a + b;
}
int main() {
int a = 10;
int b = 20;
int c = add(a, b);
return c;
}
Then, I get a LLVM IR code below.
define dso_local i32 #add(i32 noundef %a, i32 noundef %b) #0 {
entry:
%a.addr = alloca i32, align 4
%b.addr = alloca i32, align 4
store i32 %a, i32* %a.addr, align 4
store i32 %b, i32* %b.addr, align 4
%0 = load i32, i32* %a.addr, align 4
%1 = load i32, i32* %b.addr, align 4
%add = add nsw i32 %0, %1
ret i32 %add
}
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 #main() #0 {
entry:
%retval = alloca i32, align 4
%a = alloca i32, align 4
%b = alloca i32, align 4
%c = alloca i32, align 4
store i32 0, i32* %retval, align 4
store i32 10, i32* %a, align 4
store i32 20, i32* %b, align 4
%0 = load i32, i32* %a, align 4
%1 = load i32, i32* %b, align 4
%call = call i32 #add(i32 noundef %0, i32 noundef %1)
store i32 %call, i32* %c, align 4
%2 = load i32, i32* %c, align 4
ret i32 %2
}
I want to replace the function call #add with instructions in it's definition from the code above using opt command, and emit the following new code.
define dso_local i32 #main() #0 {
entry:
%retval = alloca i32, align 4
%a = alloca i32, align 4
%b = alloca i32, align 4
%c = alloca i32, align 4
store i32 0, i32* %retval, align 4
store i32 10, i32* %a, align 4
store i32 20, i32* %b, align 4
%0 = load i32, i32* %a, align 4
%1 = load i32, i32* %b, align 4
%add = add nsw i32 %0, %1
store i32 %add, i32* %c, align 4
%2 = load i32, i32* %c, align 4
ret i32 %2
}
I searched the following sites for such a path, but could not find one suitable.
https://llvm.org/docs/Passes.html#loops-natural-loop-information

Related

Why I and j are not aliases

here is the code:
int main() {
int i = 0;
int &j = i;
j = 10;
return i;
}
and its ir with O0 level optimization:
; Function Attrs: noinline norecurse nounwind optnone uwtable mustprogress
define dso_local i32 #main() #0 !dbg !7 {
entry:
%retval = alloca i32, align 4
%i = alloca i32, align 4
%j = alloca i32*, align 8
store i32 0, i32* %retval, align 4
call void #llvm.dbg.declare(metadata i32* %i, metadata !11, metadata !DIExpression()), !dbg !12
store i32 0, i32* %i, align 4, !dbg !12
call void #llvm.dbg.declare(metadata i32** %j, metadata !13, metadata !DIExpression()), !dbg !15
store i32* %i, i32** %j, align 8, !dbg !15
%0 = load i32*, i32** %j, align 8, !dbg !16
store i32 10, i32* %0, align 4, !dbg !17
%1 = load i32, i32* %i, align 4, !dbg !18
ret i32 %1, !dbg !19
}
and use command:
opt -disable-basic-aa --cfl-steens-aa -aa-eval print-all-alias-modref-info e0.ll
get result:
NoAlias: i32* %i, i32* %retval
NoAlias: i32* %retval, i32** %j
NoAlias: i32* %i, i32** %j
NoAlias: i32* %0, i32* %retval
MayAlias: i32* %0, i32* %i
NoAlias: i32* %0, i32** %j
Does anyone know why the result is 'MayAlias'.

LLVM IR get a pointer from a llvalue

I'm working with the LLVM IR in Ocaml to build a toy language and, now my problem is to convert the variable into the reference to this variable.
In other words, my simple program is this
int main(){
int i;
i = 2;
int *p;
p = &i;
print(*p);
return 0;
}
and my problem is to get the pointer of the variable i in the instruction p = &i;, my actual
IR generated is
define i32 #main() {
entry:
%i = alloca i32
store i32 2, i32* %i
%p = alloca i32*
%0 = getelementptr i32, i32* %i, i32 0
store i32* %0, i32** %p
%1 = load i32*, i32** %p
%2 = load i32, i32* %1
call void #print(i32 %2)
ret i32 0
}
I don't like this line %0 = getelementptr i32, i32* %i, i32 0, and I think that I'm only lucky that my code work as expected.
To summarize my question is, What is the good practice to make this memory operation with a variable like C language? In particular, I need to to the following
i = 2;
int *p;
p = &i;
And also
int *p;
p = &i;
*p = *p + 2;
I'm missing something because when I try to compile code like that *p = *p + 2; I receive some core dump.
I noted also that clang for my first example doesn't use getelementptr, but generate some code like that
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 #main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32*, align 8
store i32 0, i32* %1, align 4
store i32 2, i32* %2, align 4
store i32* %2, i32** %3, align 8
%4 = load i32*, i32** %3, align 8
%5 = load i32, i32* %4, align 4
%6 = call i32 (i32, ...) bitcast (i32 (...)* #print to i32 (i32, ...)*)(i32 %5)
ret i32 0
}
In my grammar, the *p is a pointer and I convert it into llvm IR into an llvm pointer type.

Is there any way to avoid deletion of duplicate load instruction when compiled using LLVM

I am working on creating LLVM front-end module pass. So, Basically I need to duplicate all load instructions and store in a different register. At -O0 for clang, opt and llc tool, this duplicated load instruction is removed. I looked at the final assembly using objdump, I could see that duplicate load instruction was removed. I want a solution that somehow does not delete duplicate load instruction.
Actual C program is,
int main(){
int* p = (int *)(0x600000);//Some address
int x=0x01, y=0x01;
int z;
z=x+y;
*p=z;
}
The corresponding IR is,
define i32 #main() #0 {
entry:
%p = alloca i32*, align 8
%x = alloca i32, align 4
%y = alloca i32, align 4
%z = alloca i32, align 4
store i32* inttoptr (i64 6291456 to i32*), i32** %p, align 8
store i32 1, i32* %x, align 4
store i32 1, i32* %y, align 4
%0 = load i32, i32* %x, align 4
%1 = load i32, i32* %y, align 4
%add = add nsw i32 %0, %1
store i32 %add, i32* %z, align 4
%2 = load i32, i32* %z, align 4
%3 = load i32*, i32** %p, align 8
store i32 %2, i32* %3, align 4
ret i32 0
}
But when my pass is enabled, this IR will change and I duplicate only load instructions with load address being same memory even for duplicated load.
The changed IR would be,
define i32 #main() #0 {
entry:
%p = alloca i32*, align 8
%x = alloca i32, align 4
%y = alloca i32, align 4
%z = alloca i32, align 4
store i32* inttoptr (i64 6291456 to i32*), i32** %p, align 8
store i32 1, i32* %x, align 4
store i32 1, i32* %y, align 4
%0 = load i32, i32* %x, align 4
%1 = load i32, i32* %y, align 4
%2 = load i32, i32* %x, align 4 //Added
%3 = load i32, i32* %y, align 4 //Added
%add = add nsw i32 %0, %1
store i32 %add, i32* %z, align 4
%4 = load i32, i32* %z, align 4
%5 = load i32*, i32** %p, align 8
%6 = load i32, i32* %z, align 4 //Added
%7 = load i32*, i32** %p, align 8 //Added
store i32 %4, i32* %5, align 4
ret i32 0
}
I am able to see the changed IR at IR level but not at the final assembly level after llc. I think llc is removing all duplicated loads. How do I stop llc from removing?
Note: I tried making all variables volatile. For this it works, I am able to see duplicated loads after llc. But, this is not a proper solution. I cannot make all thousand variables volatile :(.

LLVM: Instruction does not dominate all uses - No control flow

I implemented a function pass which iterates over basic block instructions and tracks all instructions that have a type of IntegerTy.
Here is the snippet of the pass that does it:
if (!I->isTerminator()){
Type::TypeID datatype = I->getType()->getTypeID();
if (datatype == llvm::Type::IntegerTyID) {
IRBuilder<> IRB(I);
Value* v_value = IRB.CreateZExt(I, IRB.getInt64Ty());
Value *args[] = {v_value};
IRB.CreateCall(NNT_log_int, args);
}
}
However the IRB.CreateZExt(I, IRB.getInt64Ty()); command seems to create a Instruction does not dominate all uses! problem.
I understand the nature of the issue (here and here there are similar problems).
My point of confusion that I apply this pass to a toy program with no if statements or any other control flow statements, yet I still encounter this problem.
The error message:
Instruction does not dominate all uses!
%2 = load i32, i32* %y, align 4
%1 = zext i32 %2 to i64
Instruction does not dominate all uses!
%4 = load i32, i32* %y, align 4
%3 = zext i32 %4 to i64
Note the fact that the inserted zext instructions name a constant with a counter number less than the previous instruction - I think this is the problem but I have no idea why my pass does this!!!
Here is the IR of my toy program before the application of the pass:
; Function Attrs: noinline nounwind optnone uwtable
define i32 #_Z3fooi(i32 %x) #4 {
entry:
%x.addr = alloca i32, align 4
%y = alloca i32, align 4
%z = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
store i32 0, i32* %y, align 4
%0 = load i32, i32* %x.addr, align 4
%add = add nsw i32 %0, 3
store i32 %add, i32* %y, align 4
%1 = load i32, i32* %y, align 4
store i32 %1, i32* %x.addr, align 4
%2 = load i32, i32* %y, align 4
ret i32 %2
}
; Function Attrs: noinline nounwind optnone uwtable
define i32 #_Z3bari(i32 %panos) #4 {
entry:
%panos.addr = alloca i32, align 4
%y = alloca i32, align 4
store i32 %panos, i32* %panos.addr, align 4
%0 = load i32, i32* %panos.addr, align 4
%add = add nsw i32 %0, 2
store i32 %add, i32* %y, align 4
%1 = load i32, i32* %y, align 4
ret i32 %1
}
Also, note that that the problematic instructions are before a terminator - Again I think that this is related.
Any ideas will be highly appreciated !
Your zext instruction uses I, but you're inserting it before I. When you create the IRBuilder, you should pass in the instruction after I as the insert point. For example like this:
IRBuilder<> IRB(I->getNextNode());

How to execute llvm code

I have a c code that calculates the factorial of an int "factorial.c". I compile it to llvm readable code "factorial.ll" and I modify in the compiled llvm code.
The objective is to execute the modified llvm code and to see its output, How can I do this?
It will depend on how your outputted LLVM is assembled and what libraries it links against, but for example executing the following factorial.ll with the shell command lli
$ lli factorial.ll
Factorial of 10 = 3628800
Will execute the main function with the JIT and use the standard printf to output the result to stdout.
#.str = private unnamed_addr constant [22 x i8] c"Factorial of %d = %d\0A\00", align 1
declare i32 #printf(i8*, ...)
define i32 #factorial(i32 %n) nounwind uwtable {
entry:
%n.addr = alloca i32, align 4
store i32 %n, i32* %n.addr, align 4
%0 = load i32* %n.addr, align 4
%cmp = icmp sle i32 %0, 1
br i1 %cmp, label %cond.true, label %cond.false
cond.true: ; preds = %entry
br label %cond.end
cond.false: ; preds = %entry
%1 = load i32* %n.addr, align 4
%2 = load i32* %n.addr, align 4
%sub = sub nsw i32 %2, 1
%call = call i32 #factorial(i32 %sub)
%mul = mul nsw i32 %1, %call
br label %cond.end
cond.end: ; preds = %cond.false, %cond.true
%cond = phi i32 [ 1, %cond.true ], [ %mul, %cond.false ]
ret i32 %cond
}
define i32 #main(i32 %argc, i8** %argv) nounwind uwtable {
entry:
%retval = alloca i32, align 4
%argc.addr = alloca i32, align 4
%argv.addr = alloca i8**, align 8
store i32 0, i32* %retval
store i32 %argc, i32* %argc.addr, align 4
store i8** %argv, i8*** %argv.addr, align 8
%call = call i32 #factorial(i32 10)
%call1 = call i32 (i8*, ...)* #printf(i8* getelementptr inbounds ([22 x i8]* #.str, i32 0, i32 0), i32 10, i32 %call)
ret i32 0
}