基于LLVM的Pass优化

当我们如果完成了对源码的转换,得到了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命令行工具使用example.ll文件作为输入,运行优先级别对应的一系列Pass,它也能在同一个优先级别重复运行一些Pass。如果我们需要去查看在每一个优先级别运行了哪些Pass,我们只需要在opt命令之后加入–debug-pass=Structure命令行选项就可以了

我们通过执行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 }

猜你喜欢

转载自blog.csdn.net/zcmuczx/article/details/80855017