当我们如果完成了对源码的转换,得到了LLVM的IR表示形式,它是作为一种向汇编代码转换的一个公共平台,依赖不同的后端会得到不同的汇编码,在转换为汇编码之前,如果我们对IR进行优化的话就可以得到执行效率更高的代码
在LLVM的架构当中,Pass的作用就是优化LLVM IR,Pass作用于LLVM IR,用来处理IR,分析IR,寻找优化的机会并修改IR,从而产生优化的代码。在下面命令行工具opt就是用来在LLVM IR上运行各种优化Pass的
通常来说编译器的优化会有多种级别,有0~3级别,优化级别越高,代码得到的优化也越多
首先我们先去写一个C语言程序
int main(int argc,char **argv) { int i,j,k,t=0; for (i=0; i<10; i++) { for (j=0; j<10; j++) { for (k=0; k<10; k++) { t++; } } for (j=0;j<10; j++) { t++; } } for (i=0; i<20; i++) { for (j=0; j<20; j++) { t++; } for (j=0; j<20; j++) { t++; } } return t; }
使用clang命令也就是clang -S -O0 -emit-llvm example.c 把源码转换成LLVM IR生成的包含LLVM IR的example.ll的文件内容如下所示
; ModuleID = 'example.c' source_filename = "example.c" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.13.0" ; Function Attrs: noinline nounwind optnone ssp uwtable define i32 @main(i32, i8**) #0 { %3 = alloca i32, align 4 %4 = alloca i32, align 4 %5 = alloca i8**, align 8 %6 = alloca i32, align 4 %7 = alloca i32, align 4 %8 = alloca i32, align 4 %9 = alloca i32, align 4 store i32 0, i32* %3, align 4 store i32 %0, i32* %4, align 4 store i8** %1, i8*** %5, align 8 store i32 0, i32* %9, align 4 store i32 0, i32* %6, align 4 br label %10 ; <label>:10: ; preds = %42, %2 %11 = load i32, i32* %6, align 4 %12 = icmp slt i32 %11, 10 br i1 %12, label %13, label %45 ; <label>:13: ; preds = %10 store i32 0, i32* %7, align 4 br label %14 ; <label>:14: ; preds = %28, %13 %15 = load i32, i32* %7, align 4 %16 = icmp slt i32 %15, 10 br i1 %16, label %17, label %31 ; <label>:17: ; preds = %14 store i32 0, i32* %8, align 4 br label %18 ; <label>:18: ; preds = %24, %17 %19 = load i32, i32* %8, align 4 %20 = icmp slt i32 %19, 10 br i1 %20, label %21, label %27 ; <label>:21: ; preds = %18 %22 = load i32, i32* %9, align 4 %23 = add nsw i32 %22, 1 store i32 %23, i32* %9, align 4 br label %24 ; <label>:24: ; preds = %21 %25 = load i32, i32* %8, align 4 %26 = add nsw i32 %25, 1 store i32 %26, i32* %8, align 4 br label %18 ; <label>:27: ; preds = %18 br label %28 ; <label>:28: ; preds = %27 %29 = load i32, i32* %7, align 4 %30 = add nsw i32 %29, 1 store i32 %30, i32* %7, align 4 br label %14 ; <label>:31: ; preds = %14 store i32 0, i32* %7, align 4 br label %32 ; <label>:32: ; preds = %38, %31 %33 = load i32, i32* %7, align 4 %34 = icmp slt i32 %33, 10 br i1 %34, label %35, label %41 ; <label>:35: ; preds = %32 %36 = load i32, i32* %9, align 4 %37 = add nsw i32 %36, 1 store i32 %37, i32* %9, align 4 br label %38 ; <label>:38: ; preds = %35 %39 = load i32, i32* %7, align 4 %40 = add nsw i32 %39, 1 store i32 %40, i32* %7, align 4 br label %32 ; <label>:41: ; preds = %32 br label %42 ; <label>:42: ; preds = %41 %43 = load i32, i32* %6, align 4 %44 = add nsw i32 %43, 1 store i32 %44, i32* %6, align 4 br label %10 ; <label>:45: ; preds = %10 store i32 0, i32* %6, align 4 br label %46 ; <label>:46: ; preds = %70, %45 %47 = load i32, i32* %6, align 4 %48 = icmp slt i32 %47, 20 br i1 %48, label %49, label %73 ; <label>:49: ; preds = %46 store i32 0, i32* %7, align 4 br label %50 ; <label>:50: ; preds = %56, %49 %51 = load i32, i32* %7, align 4 %52 = icmp slt i32 %51, 20 br i1 %52, label %53, label %59 ; <label>:53: ; preds = %50 %54 = load i32, i32* %9, align 4 %55 = add nsw i32 %54, 1 store i32 %55, i32* %9, align 4 br label %56 ; <label>:56: ; preds = %53 %57 = load i32, i32* %7, align 4 %58 = add nsw i32 %57, 1 store i32 %58, i32* %7, align 4 br label %50 ; <label>:59: ; preds = %50 store i32 0, i32* %7, align 4 br label %60 ; <label>:60: ; preds = %66, %59 %61 = load i32, i32* %7, align 4 %62 = icmp slt i32 %61, 20 br i1 %62, label %63, label %69 ; <label>:63: ; preds = %60 %64 = load i32, i32* %9, align 4 %65 = add nsw i32 %64, 1 store i32 %65, i32* %9, align 4 br label %66 ; <label>:66: ; preds = %63 %67 = load i32, i32* %7, align 4 %68 = add nsw i32 %67, 1 store i32 %68, i32* %7, align 4 br label %60 ; <label>:69: ; preds = %60 br label %70 ; <label>:70: ; preds = %69 %71 = load i32, i32* %6, align 4 %72 = add nsw i32 %71, 1 store i32 %72, i32* %6, align 4 br label %46 ; <label>:73: ; preds = %46 %74 = load i32, i32* %9, align 4 ret i32 %74 }
我们可以使用opt -O0 -S example.ll去进行优化包含IR的example.ll文件,我们还可以使用下面的命令进行优化
- opt -O1 -S example.ll
- opt -O2 -S example.ll
- opt -O3 -S example.ll
我们通过执行opt -O1 -S example.ll获得的结果如下所示,优化的直接返回1900了,其实上面的C程序返回的结果就是1900
; ModuleID = 'example.ll' source_filename = "example.c" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.13.0" ; Function Attrs: norecurse nounwind readnone define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 { ret i32 1900 } attributes #0 = { norecurse nounwind readnone }
文章来源: 基于LLVM的Pass优化