赞
踩
本文概述了LLVM创建人类可读的代码结构可视化和相关依赖分析passes的功能。
程序代码示例(vector_sum)
void vector_sum(int length, float * in1, float * in2, float * out){ for(int i = 0; i < length; i++) out[i] = in1[i] + in2[i]; } #include<malloc.h> #include<stdio.h> #include<stdlib.h> int main(int argc, char* argv[]){ if(argc != 2) return 1; int length = atoi(argv[1]); float* in1 = (float*)malloc(length * sizeof(float)); float* in2 = (float*)malloc(length * sizeof(float)); float* out = (float*)malloc(length * sizeof(float)); for(int i = 0; i < length; i++){ in1[i] = drand48(); in2[i] = drand48(); } vector_sum(length, in1, in2, out); printf("%f\n", out[length−1]); return 0; }
这个函数的LLVM IR (vector_sum)
$ clang −emit − llvm example.c −O1 −S −o − | less define void @vector_sum ( i32 %length , float * nocapture readonly %in1 , float * nocapture readonly %in2 , float * nocapture %out ) #0 { entry : %cmp9 = icmp sgt i32 %length , 0 br i1 %cmp9 , label %for.body , label %for.end for.body : ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next , %for.body ] , [ 0 , %entry ] %arrayidx = getelementptr inbounds float * %in1 , i64 %indvars.iv %0 = load float * %arrayidx , align 4 , ! tbaa ! 1 %arrayidx2 = getelementptr inbounds float * %in2 , i64 %indvars.iv %1 = load float * %arrayidx2 , align 4 , ! tbaa ! 1 %add = fadd float %0 , %1 %arrayidx4 = getelementptr inbounds float * %out , i64 %indvars.iv store float %add , float * %arrayidx4 , align 4 , ! tbaa ! 1 %indvars.iv.next = add nuw nsw i64 %indvars.iv , 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 %exitcond = icmp eq i32 %lftr.wideiv , %length br i1 %exitcond , label %for.end , label %for.body for.end : ; preds = %for.body, %entry ret void }
在LLVM中,从命令行可以得到两种形式的图:
$ clang −emit − llvm −S −c example . c −o − | opt −O1 | opt −dot − callgraph −o / dev / null && dot −Tpdf callgraph . dot −o callgraph . pdf
$ clang −emit − llvm −S −c example . c −o − | opt −O1 | opt −dot − cfg −o / dev / null && dot −Tpdf cfg . vector_sum . dot −o cfg . vector_sum . pdf
$ . / graph − llvm − ir . / example . ll && dot −Tpdf vector_sum . dot −o vector_sum . pdf
/* fibo.c -- Fibonacci C program to be debugged */ #include<stdio.h> int fib(int n){ int f, f0 = 1, f1 = 1; while(n > 1){ n = n − 1; f = f0 + f1; f0 = f1; f1 = f; } return f; } int main(){ int n = 9; while(n > 0){ printf("fib(%d)=%dN", n, fib(n)); n = n − 1; } return 0; }
注意,未初始化的int f
变成了undef
→
关注依赖关系的两个LLVM passes:
两者都利用别名分析(Alias Analysis)
来降低 O(n^2) 的强度。
Clobber
—— clobbers内存的指令,例如一个may-aliased storeDef
—— 指令定义/生成所需的内存位置NonLocal
—— 在当前基本块之外(需要检查前一个块)NonFuncLocal
—— 在当前函数外部define void @vector_sum ( i32 %length , float * nocapture readonly %in1 , float * nocapture readonly %in2 , float * nocapture %out ) #0 { entry : %cmp9 = icmp sgt i32 %length , 0 br i1 %cmp9 , label %for.body , label %for.end for.body : ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next , %for.body ] , [ 0 , %entry ] %arrayidx = getelementptr inbounds float * %in1 , i64 %indvars.iv %0 = load float * %arrayidx , align 4 , ! tbaa ! 1 %arrayidx2 = getelementptr inbounds float * %in2 , i64 %indvars.iv %1 = load float * %arrayidx2 , align 4 , ! tbaa ! 1 %add = fadd float %0 , %1 %arrayidx4 = getelementptr inbounds float * %out , i64 %indvars.iv store float %add , float * %arrayidx4 , align 4 , ! tbaa ! 1 %indvars.iv.next = add nuw nsw i64 %indvars.iv , 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 %exitcond = icmp eq i32 %lftr.wideiv , %length br i1 %exitcond , label %for.end , label %for.body for.end : ; preds = %for.body, %entry ret void }
内存依赖分析打印输出:
$ clang −emit − llvm example.c −O1 −S −o − | opt −memdep −print−memdeps −o / dev / null
Function vector_sum memory dependencies :
Unknown in block %for.body
Unknown in block %entry
%0 = load float * %arrayidx , align 4 , ! tbaa ! 1
Unknown in block %for.body
Unknown in block %entry
%1 = load float * %arrayidx2 , align 4 , ! tbaa ! 1
Def from : %1 = load float * %arrayidx2 , align 4 , ! tbaa ! 1
store float %add , float * %arrayidx4 , align 4 , ! tbaa ! 1
为什么store
只依赖于两次load
中的一次?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。