Skip to content

Instantly share code, notes, and snippets.

@DerSaidin
Created November 11, 2018 18:59
Show Gist options
  • Save DerSaidin/3c8ed6c35938a04a34b279b5e4e0265f to your computer and use it in GitHub Desktop.
Save DerSaidin/3c8ed6c35938a04a34b279b5e4e0265f to your computer and use it in GitHub Desktop.
LLVM Optimization pass breakdown example
inline int square(int num) {
return num*num*num*num*num*num*num*num;
}
int foo(int n, int num) {
int res = 0;
for(int i = 0; i < n; i++)
res += square(num);
return res;
}
; ModuleID = 'a.ll'
source_filename = "a.cc"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
$_Z6squarei = comdat any
; Function Attrs: uwtable
define i32 @_Z3fooii(i32, i32) #0 {
%3 = alloca i32, align 4
%4 = alloca i32, align 4
%5 = alloca i32, align 4
%6 = alloca i32, align 4
store i32 %0, i32* %3, align 4, !tbaa !2
store i32 %1, i32* %4, align 4, !tbaa !2
%7 = bitcast i32* %5 to i8*
call void @llvm.lifetime.start.p0i8(i64 4, i8* %7) #3
store i32 0, i32* %5, align 4, !tbaa !2
%8 = bitcast i32* %6 to i8*
call void @llvm.lifetime.start.p0i8(i64 4, i8* %8) #3
store i32 0, i32* %6, align 4, !tbaa !2
br label %9
; <label>:9: ; preds = %20, %2
%10 = load i32, i32* %6, align 4, !tbaa !2
%11 = load i32, i32* %3, align 4, !tbaa !2
%12 = icmp slt i32 %10, %11
br i1 %12, label %15, label %13
; <label>:13: ; preds = %9
%14 = bitcast i32* %6 to i8*
call void @llvm.lifetime.end.p0i8(i64 4, i8* %14) #3
br label %23
; <label>:15: ; preds = %9
%16 = load i32, i32* %4, align 4, !tbaa !2
%17 = call i32 @_Z6squarei(i32 %16)
%18 = load i32, i32* %5, align 4, !tbaa !2
%19 = add nsw i32 %18, %17
store i32 %19, i32* %5, align 4, !tbaa !2
br label %20
; <label>:20: ; preds = %15
%21 = load i32, i32* %6, align 4, !tbaa !2
%22 = add nsw i32 %21, 1
store i32 %22, i32* %6, align 4, !tbaa !2
br label %9
; <label>:23: ; preds = %13
%24 = load i32, i32* %5, align 4, !tbaa !2
%25 = bitcast i32* %5 to i8*
call void @llvm.lifetime.end.p0i8(i64 4, i8* %25) #3
ret i32 %24
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
; Function Attrs: inlinehint nounwind uwtable
define linkonce_odr i32 @_Z6squarei(i32) #2 comdat {
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4, !tbaa !2
%3 = load i32, i32* %2, align 4, !tbaa !2
%4 = load i32, i32* %2, align 4, !tbaa !2
%5 = mul nsw i32 %3, %4
%6 = load i32, i32* %2, align 4, !tbaa !2
%7 = mul nsw i32 %5, %6
%8 = load i32, i32* %2, align 4, !tbaa !2
%9 = mul nsw i32 %7, %8
%10 = load i32, i32* %2, align 4, !tbaa !2
%11 = mul nsw i32 %9, %10
%12 = load i32, i32* %2, align 4, !tbaa !2
%13 = mul nsw i32 %11, %12
%14 = load i32, i32* %2, align 4, !tbaa !2
%15 = mul nsw i32 %13, %14
%16 = load i32, i32* %2, align 4, !tbaa !2
%17 = mul nsw i32 %15, %16
ret i32 %17
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { argmemonly nounwind }
attributes #2 = { inlinehint nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #3 = { nounwind }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.2 (tags/RELEASE_502/final)"}
!2 = !{!3, !3, i64 0}
!3 = !{!"int", !4, i64 0}
!4 = !{!"omnipotent char", !5, i64 0}
!5 = !{!"Simple C++ TBAA"}
; ModuleID = 'a.ll'
source_filename = "a.cc"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
$_Z6squarei = comdat any
; Function Attrs: uwtable
define i32 @_Z3fooii(i32, i32) #0 {
br label %3
; <label>:3: ; preds = %9, %2
%.01 = phi i32 [ 0, %2 ], [ %8, %9 ]
%.0 = phi i32 [ 0, %2 ], [ %10, %9 ]
%4 = icmp slt i32 %.0, %0
br i1 %4, label %6, label %5
; <label>:5: ; preds = %3
br label %11
; <label>:6: ; preds = %3
%7 = call i32 @_Z6squarei(i32 %1)
%8 = add nsw i32 %.01, %7
br label %9
; <label>:9: ; preds = %6
%10 = add nsw i32 %.0, 1
br label %3
; <label>:11: ; preds = %5
ret i32 %.01
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
; Function Attrs: inlinehint nounwind uwtable
define linkonce_odr i32 @_Z6squarei(i32) #2 comdat {
%2 = mul nsw i32 %0, %0
%3 = mul nsw i32 %2, %0
%4 = mul nsw i32 %3, %0
%5 = mul nsw i32 %4, %0
%6 = mul nsw i32 %5, %0
%7 = mul nsw i32 %6, %0
%8 = mul nsw i32 %7, %0
ret i32 %8
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { argmemonly nounwind }
attributes #2 = { inlinehint nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.2 (tags/RELEASE_502/final)"}
; ModuleID = 'a.ll'
source_filename = "a.cc"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
$_Z6squarei = comdat any
; Function Attrs: uwtable
define i32 @_Z3fooii(i32, i32) #0 {
br label %3
; <label>:3: ; preds = %9, %2
%.01 = phi i32 [ 0, %2 ], [ %8, %9 ]
%.0 = phi i32 [ 0, %2 ], [ %10, %9 ]
%4 = icmp slt i32 %.0, %0
br i1 %4, label %6, label %5
; <label>:5: ; preds = %3
br label %11
; <label>:6: ; preds = %3
%7 = call i32 @_Z6squarei(i32 %1)
%8 = add nsw i32 %7, %.01
br label %9
; <label>:9: ; preds = %6
%10 = add nsw i32 %.0, 1
br label %3
; <label>:11: ; preds = %5
ret i32 %.01
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
; Function Attrs: inlinehint nounwind uwtable
define linkonce_odr i32 @_Z6squarei(i32) #2 comdat {
%2 = mul i32 %0, %0
%3 = mul i32 %2, %2
%4 = mul i32 %3, %3
ret i32 %4
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { argmemonly nounwind }
attributes #2 = { inlinehint nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.2 (tags/RELEASE_502/final)"}
; ModuleID = 'a.ll'
source_filename = "a.cc"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: uwtable
define i32 @_Z3fooii(i32, i32) #0 {
br label %3
; <label>:3: ; preds = %11, %2
%.01 = phi i32 [ 0, %2 ], [ %10, %11 ]
%.0 = phi i32 [ 0, %2 ], [ %12, %11 ]
%4 = icmp slt i32 %.0, %0
br i1 %4, label %6, label %5
; <label>:5: ; preds = %3
br label %13
; <label>:6: ; preds = %3
%7 = mul i32 %1, %1
%8 = mul i32 %7, %7
%9 = mul i32 %8, %8
%10 = add nsw i32 %9, %.01
br label %11
; <label>:11: ; preds = %6
%12 = add nsw i32 %.0, 1
br label %3
; <label>:13: ; preds = %5
ret i32 %.01
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { argmemonly nounwind }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.2 (tags/RELEASE_502/final)"}
; ModuleID = 'a.ll'
source_filename = "a.cc"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: uwtable
define i32 @_Z3fooii(i32, i32) #0 {
%3 = mul i32 %1, %1
%4 = mul i32 %3, %3
%5 = mul i32 %4, %4
br label %6
; <label>:6: ; preds = %11, %2
%.01 = phi i32 [ 0, %2 ], [ %10, %11 ]
%.0 = phi i32 [ 0, %2 ], [ %12, %11 ]
%7 = icmp slt i32 %.0, %0
br i1 %7, label %9, label %8
; <label>:8: ; preds = %6
%.01.lcssa = phi i32 [ %.01, %6 ]
br label %13
; <label>:9: ; preds = %6
%10 = add nsw i32 %5, %.01
br label %11
; <label>:11: ; preds = %9
%12 = add nsw i32 %.0, 1
br label %6
; <label>:13: ; preds = %8
ret i32 %.01.lcssa
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { argmemonly nounwind }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.2 (tags/RELEASE_502/final)"}
; ModuleID = 'a.ll'
source_filename = "a.cc"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: uwtable
define i32 @_Z3fooii(i32, i32) #0 {
%3 = mul i32 %1, %1
%4 = mul i32 %3, %3
%5 = mul i32 %4, %4
%6 = icmp sgt i32 %0, 0
%smax = select i1 %6, i32 %0, i32 0
br label %7
; <label>:7: ; preds = %2
%8 = mul i32 %5, %smax
br label %9
; <label>:9: ; preds = %7
ret i32 %8
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { argmemonly nounwind }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.2 (tags/RELEASE_502/final)"}
; ModuleID = 'a.ll'
source_filename = "a.cc"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: uwtable
define i32 @_Z3fooii(i32, i32) #0 {
%3 = mul i32 %1, %1
%4 = mul i32 %3, %3
%5 = icmp sgt i32 %0, 0
%smax = select i1 %5, i32 %0, i32 0
%6 = mul i32 %4, %smax
%7 = mul i32 %6, %4
ret i32 %7
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
attributes #0 = { uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { argmemonly nounwind }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 5.0.2 (tags/RELEASE_502/final)"}
#!/usr/bin/env bash
# Adding "-O1 -Xclang -disable-llvm-passes" is disables optimziations like "-O0",
# but doing "-O0" also adds a optnone attribute to each function.
# This attribute would tell opt not to optimize each function, which would break this example.
clang a.cc -O1 -Xclang -disable-llvm-passes -emit-llvm -S -o a.ll
opt -S a.ll -o b0.ll
opt -mem2reg -S a.ll -o b1.ll
opt -mem2reg -reassociate -S a.ll -o b2.ll
opt -mem2reg -reassociate -inline -S a.ll -o b3.ll
opt -mem2reg -reassociate -inline -licm -S a.ll -o b4.ll
opt -mem2reg -reassociate -inline -licm -indvars -loop-deletion -S a.ll -o b5.ll
opt -mem2reg -reassociate -inline -licm -indvars -loop-deletion -simplifycfg -S a.ll -o b6.ll
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment