1

In LLVM IR, phi nodes are a key component of SSA (Static Single Assignment) form and are used to represent control flow in a program. As far as I know the mem2reg optimization pass in LLVM is used to convert memory accesses into SSA form by introducing phi nodes.

However when I'm trying to compile the simple app.c program:

#include <stdio.h>
int main(){
  int x = 1;
  if(x > 2){
   x++;
  }else{
   x--;
  }
  printf("%d", x);
}

by running the next commands:

clang -S -emit-llvm -O -Xclang -disable-llvm-passes app.c
opt -S -mem2reg -o opt.ll app.ll

I get the next results. app.ll:

define i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  store i32 0, ptr %1, align 4
  call void @llvm.lifetime.start.p0(i64 4, ptr %2) #3
  store i32 1, ptr %2, align 4, !tbaa !5
  %3 = load i32, ptr %2, align 4, !tbaa !5
  %4 = icmp sgt i32 %3, 2
  br i1 %4, label %5, label %8

5:                                                ; preds = %0
  %6 = load i32, ptr %2, align 4, !tbaa !5
  %7 = add nsw i32 %6, 1
  store i32 %7, ptr %2, align 4, !tbaa !5
  br label %11

8:                                                ; preds = %0
  %9 = load i32, ptr %2, align 4, !tbaa !5
  %10 = add nsw i32 %9, -1
  store i32 %10, ptr %2, align 4, !tbaa !5
  br label %11

11:                                               ; preds = %8, %5
  %12 = load i32, ptr %2, align 4, !tbaa !5
  %13 = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %12)
  call void @llvm.lifetime.end.p0(i64 4, ptr %2) #3
  %14 = load i32, ptr %1, align 4
  ret i32 %14
}

As you can see, here is no phi nodes and I'm not sure that we can call it SSA form. After applying mem2reg optimization (opt.ll):

define i32 @main() #0 {
  %1 = icmp sgt i32 1, 2
  br i1 %1, label %2, label %4

2:                                                ; preds = %0
  %3 = add nsw i32 1, 1
  br label %6

4:                                                ; preds = %0
  %5 = add nsw i32 1, -1
  br label %6

6:                                                ; preds = %4, %2
  %.0 = phi i32 [ %3, %2 ], [ %5, %4 ]
  %7 = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %.0)
  ret i32 0
}

and it looks like a SSA form.

Do phi nodes already exist in LLVM IR before the mem2reg optimization pass is applied? Or are they only introduced by the mem2reg pass as part of the process of converting memory accesses to SSA form? I would appreciate any insights or clarifications on this topic. Thank you!

Volodya Lombrozo
  • 2,325
  • 2
  • 16
  • 34
  • 1
    Before applying LLVM optimizations, PHI nodes (or any other types of instructions) exist if and only if the frontend generated them. That said, I'd say most frontends (including clang) generate code without PHI nodes and then rely on the LLVM optimizer to add them. – sepp2k Mar 22 '23 at 11:29
  • Thank you, @sepp2k, for the information. I was wondering, can we refer to code without PHI nodes as code in SSA form? Or is it not necessary to have PHI nodes for code to be considered in SSA form? – Volodya Lombrozo Mar 23 '23 at 07:50

0 Answers0