O3都是怪物,这里分析的是CLANG怪物,示例程序遍历数组每个元素然后放大。

void foreach_scale(int arr[],int elem){
for(int i=0;i<elem;i++){
arr[i] += (elem*1024);
}
}

这里删去了用处不大的内容,只保留了关键的LLVM IR。通过分析可以看到,如果循环小于8 LLVM IR会使用vector,vector使用SIMD指令高效进行计算,如果大于8则是普通的for形式。

; Function Attrs: norecurse nounwind
define void @"\01?foreach_scale@@YAXQAHH@Z"(i32* nocapture %arr, i32 %elem) local_unnamed_addr #0 {
entry:
;elem>0则进入循环,否则整个函数结束
%cmp5 = icmp sgt i32 %elem, 0
br i1 %cmp5, label %for.body.lr.ph, label %for.cond.cleanup for.body.lr.ph:
%mul = shl i32 %elem, 10;
; elem和8进行比较(utl表示unsigned less than)
; elem<8则跳到正常循环%for.body.preheader,否则跳到%vector.ph
%min.iters.check = icmp ult i32 %elem, 8
br i1 %min.iters.check, label %for.body.preheader, label %vector.ph for.body.preheader:
;phi表示SSA里面的φ函数,详细参见LLVM DOC
%i.06.ph = phi i32 [ 0, %for.body.lr.ph ], [ %n.vec, %middle.block ]
br label %for.body vector.ph:
%n.vec = and i32 %elem, -8
;首先构造<%mul val val val>,然后shufflevector构造<%mul %mul %mul %mul>
%broadcast.splatinsert9 = insertelement <4 x i32> undef, i32 %mul, i32 0
%broadcast.splat10 = shufflevector <4 x i32> %broadcast.splatinsert9, <4 x i32> undef, <4 x i32> zeroinitializer
;ditto, %broadcast.splatinsert9 == <%mul %mul %mul %mul>
%broadcast.splatinsert11 = insertelement <4 x i32> undef, i32 %mul, i32 0
%broadcast.splat12 = shufflevector <4 x i32> %broadcast.splatinsert11, <4 x i32> undef, <4 x i32> zeroinitializer
br label %vector.body vector.body:
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ] ;从arr指向的内存加载数据
;%0现在表示<arr[0] arr[1] arr[2] arr[3]>
%0 = getelementoptr inbounds i32, i32* %arr, i32 %index
%1 = bitcast i32* %0 to <4 x i32>*
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4, !tbaa !3 ;%2表示<arr[4] arr[5] arr[6] arr[7]>
%2 = getelementptr i32, i32* %0, i32 4
%3 = bitcast i32* %2 to <4 x i32>*
%wide.load8 = load <4 x i32>, <4 x i32>* %3, align 4, !tbaa !3 ;<arr[0] arr[1] arr[2] arr[3]>与<%mul %mul %mul %mul>相加,得到vector:%4
;<arr[4] arr[5] arr[6] arr[7]>与<%mul %mul %mul %mul>相加,得到vector:%5
%4 = add nsw <4 x i32> %wide.load, %broadcast.splat10
%5 = add nsw <4 x i32> %wide.load8, %broadcast.splat12 ;%4,%5写回内存
%6 = bitcast i32* %0 to <4 x i32>*
store <4 x i32> %4, <4 x i32>* %6, align 4, !tbaa !3
%7 = bitcast i32* %2 to <4 x i32>*
store <4 x i32> %5, <4 x i32>* %7, align 4, !tbaa !3 %index.next = add i32 %index, 8
%8 = icmp eq i32 %index.next, %n.vec
br i1 %8, label %middle.block, label %vector.body, !llvm.loop !7 middle.block:
%cmp.n = icmp eq i32 %n.vec, %elem
br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader ;函数返回
for.cond.cleanup:
ret void for.body:
%i.06 = phi i32 [ %inc, %for.body ], [ %i.06.ph, %for.body.preheader ]‘
; arr[i] = arr[i]+ (elem*1024),其中%mul=(elem*1024)
%arrayidx = getelementptr inbounds i32, i32* %arr, i32 %i.06
%9 = load i32, i32* %arrayidx, align 4, !tbaa !3
%add = add nsw i32 %9, %mul
store i32 %add, i32* %arrayidx, align 4, !tbaa !3
; i++
%inc = add nuw nsw i32 %i.06, 1
; 循环条件i<elem判断
%exitcond = icmp eq i32 %inc, %elem
br i1 %exitcond, label %for.cond.cleanup, label %for.body, !llvm.loop !10
}

clang -O3 for循环的LLVM IR的更多相关文章

  1. LLVM 笔记(五)—— LLVM IR

    ilocker:关注 Android 安全(新手) QQ: 2597294287 LLVM 的 IR (Intermediate Representation) 是其设计中的最重要的部分.优化器在进行 ...

  2. 手写token解析器、语法解析器、LLVM IR生成器(GO语言)

    最近开始尝试用go写点东西,正好在看LLVM的资料,就写了点相关的内容 - 前端解析器+中间代码生成(本地代码的汇编.执行则靠LLVM工具链完成) https://github.com/daibinh ...

  3. [转帖]什么是 LLVM?Swift, Rust, Clang 等语言背后的支持

    要了解用于以编程方式生成机器原生代码的编译器框架是如何让新语言的推出以及对现有的语言进行增强比以往更加容易了. https://www.oschina.net/translate/what-is-ll ...

  4. LLVM,Clang

    在使用xcode时常常会遇到这2个概念,今天总结一下. wiki中关于llvm的描述: LLVM提供了完整編譯系統的中間層,它會將中間語言(IF, Intermediate form)從編譯器取出與最 ...

  5. ios llvm and clang build tools

    1. 使用 libclan g或 clang 插件 包括( libclang 和  Clangkit) 备注: Clangkit,它是基于 clang 提供的功能,用 Objective-C 进行封装 ...

  6. LLVM每日谈之二十 Everything &amp;&amp; Clang driver

    作者:史宁宁(snsn1984) 近期在读<Getting Started with LLVM Core Libraries>.这是读的第一本LLVM的书.非常多地方尽管讲的是自己知道的东 ...

  7. iOS开发系列-LLVM、Clang

    LLVM LLVM计划启动于2000年,最初由University of Illinois at Urbana-Champaign的Chris Lattner主持开展. 我们可以认为LLVM是一个完整 ...

  8. llvm+clang编译安装

    最近一段时间在llvm+clang上做一些东西,所以顺便将自己如何编译安装llvm+clang写了篇文章发在这里,希望能帮助刚接触llvm+clang的童鞋少走一些弯路(我刚接触的时候为了编译安装这个 ...

  9. 编译器:gcc, clang, llvm

    clang Clang是LLVM的前端,可以用来编译C,C++,ObjectiveC等语言.传统的编译器通常分为三个部分,前端(frontEnd),优化器(Optimizer)和后端(backEnd) ...

随机推荐

  1. 开发环境入门 linux基础 (部分)网络 SSH 更名 DNS解析 元字符

    nginx---> web ifconfig 查看网络配置信息 id add show 查看当前网卡信息(最小安装下) mtu 是指网卡传输的最大单元 单位:字节 网卡配置 临时配置 ifcon ...

  2. Python代码规范总结

    1.缩进问题: Tip:用4个空格来缩进代码 不要用Tab键或者是Tab和空格混用, vim用户可以将tab键设置为4个空格的长度.要么选择垂直对齐换行的元素, 或者是使用4空格悬挂式缩进(第一行没有 ...

  3. mysql添加用户

    增加新用户: 格式:grant select on 数据库.* to 用户名@登录主机 identified by "密码" 例1.增加一个用户test1密码为abc,让他可以在任 ...

  4. 生产环境该如何选择lvs的工作模式,和哪一种算法

    lvs的工作模式有这几种: 1.RR : 轮叫算法,平均分配,你一个,我一个: 2.WRR :加权轮叫算法,谁的处理能力强,谁的权重就高: 3.LC :最少链接算法,谁的连接数最少,谁就处理更多的链接 ...

  5. 问题:oracle 排序 null值放在最后;结果: ORACLE中null的排序问题

    ORACLE中null的排序问题 关键字: oracle nulls 问题描述:    在平时的业务处理中,经常遇到要对业务数据进行排序,并且要对null值也做相应的排序.在Oracle中,进行Ord ...

  6. Python之条件语句以及循环

    Python代码的缩进规则.具有相同缩进的代码被视为代码块 缩进请严格按照Python的习惯写法:4个空格,不要使用Tab,更不要混合Tab和空格,否则很容易造成因为缩进引起的语法错误. 注意: if ...

  7. js中的操作符

    写在前面 js语法 DOM对象(把body,div,p等节点树看成一个对象) BOM对象(把浏览器的地址栏历史记录DOM等装在一个对象) 浏览器是宿主,但js的宿主不限于浏览器,也可以是服务器,如no ...

  8. VS项目模板文件位置

    目录: D:\Users\lyn\Documents\Visual Studio 2012\Templates\ProjectTemplates   模板文件完整路径: D:\Users\lyn\Do ...

  9. 使用ffmpeg转换视频格式

    命令: ffmpeg -i infile -ab 128 -acodec libmp3lame -ac 1 -ar 22050 -r 29.97 -qscale 6 -y outfile   说明: ...

  10. Apollo问题

    1.安装问题: 一不小心安装了NVIDIA,导致bash docker/scripts/dev_start.sh无法启动:[ERROR] Failed to start docker containe ...