what is phi node?
phi node is useful when there is branches, and variables depend on these branches.
For example:
b = 0
if (a == 2){
b = 1
}
In this case, we want llvm IR to be like this:
br i1 %cond, label %then, label %else
then:
%return_value = 0
br label %end
else:
%return_value = 1
br label %end
end:
%return_value = load i32, i32* %ptr_return_value
ret i32 %return_value
However, we cannot do this, because LLVM IR is SSA(it means we can assign one variable only once).
So, if there is no phi node, llvm IR is as follows:
br i1 %cond, label %then, label %else
then:
store i32 1111, i32* %ptr_return_value
br label %end
else:
store i32 2222, i32* %ptr_return_value
br label %end
end:
%return_value = load i32, i32* %ptr_return_value
ret i32 %return_value
We have to use stack memory, but it is not efficient to use memory.
So, we can use phi node!
If we use phi node, the above long code becomes like this:
then:
%result1 = call i32 @func1()
br label %end
else:
%result2 = call i32 @func2()
br label %end
end:
%result3 = phi i32 [%result1, %then], [%result2, %else]
To produce phi node, we should use mem2reg
.
In this case, %result3 is local temporary variable, so it uses register.
- So, what is Assemble like?
high-level language:
int max(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
LLVM IR is(if we use phi node):
define i32 @max(i32 %a, i32 %b) {
entry:
%0 = icmp sgt i32 %a, %b
br i1 %0, label %btrue, label %bfalse
btrue: ; preds = %2
br label %end
bfalse: ; preds = %2
br label %end
end: ; preds = %btrue, %bfalse
%retval = phi i32 [%a, %btrue], [%b, %bfalse]
ret i32 %retval
}
the assemble code is:
max: # @max
# %bb.0: # %entry
cmpl %esi, %edi
jg .LBB0_2
# %bb.1: # %bfalse
movl %esi, %edi
.LBB0_2: # %end
movl %edi, %eax
retq
Local Variables
Local symbols begin with a percent symbol (%).
- There are two kinds of local variables in LLVM:
- Register
- Stack-allocated local variables
The former is created by instroducing a new symbol for the variable.
%reg = add i32 4, 2
The latter is created by allocating the variable on the stack.
%stack = alloca i32
Global variabls
Global symbols begin with an at sign (@).
int variable = 21;
int main()
{
variable = variable * 2;
return variable;
}
The above code becomes:
@variable = global i32 21
define i32 @main() {
%1 = load i32, i32* @variable ; load the global variable
%2 = mul i32 %1, 2
store i32 %2, i32* @variable ; store instruction to write to global variable
ret i32 %2
}