0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

llvm phinode, local variable, global variable

Last updated at Posted at 2024-07-29

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

reference: https://mapping-high-level-constructs-to-llvm-ir.readthedocs.io/en/latest/control-structures/ssa-phi.html

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
}

reference: https://mapping-high-level-constructs-to-llvm-ir.readthedocs.io/en/latest/basic-constructs/global-variables.html

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?