clang -O3 for循环的LLVM IR

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
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏haifeiWu与他朋友们的专栏

复杂业务下向Mysql导入30万条数据代码优化的踩坑记录

从毕业到现在第一次接触到超过30万条数据导入MySQL的场景(有点low),就是在顺丰公司接入我司EMM产品时需要将AD中的员工数据导入MySQL中,因此楼主负...

30940
来自专栏FSociety

SQL中GROUP BY用法示例

GROUP BY我们可以先从字面上来理解,GROUP表示分组,BY后面写字段名,就表示根据哪个字段进行分组,如果有用Excel比较多的话,GROUP BY比较类...

5.2K20
来自专栏儿童编程

《动物魔法学校》儿童学编程Scratch之“外观”部分

导读:本文通过一个案例《动物魔法学校》来学习Scratch语言的“外观”部分。之后通过一系列其他功能的综合运用对作品功能进行了扩展。

19440
来自专栏儿童编程

什么样的人生才是有意义的人生——没有标准的标准答案

【导读】其实我们可以跳出这个小圈圈去更加科客观地看一下这个世界。在夜晚的时候我们仰望天空,浩瀚的宇宙中整个地球只是一粒浮尘,何况地球上一个小小的人类?在漫长的历...

1.8K50
来自专栏儿童编程

声音功能让儿童编程更有创造性

导读:Scratch中声音功能非常强大,除了常规的音效,你甚至可以模拟各种乐器的各个发音、设置节拍、休止……如果你愿意,甚至可以用它创作一个交响乐。我们可以引导...

13940
来自专栏儿童编程

儿童创造力教育与编程教育的碰撞——MIT雷斯尼克教授最新理论梗概

儿童编程教育已经在我国各一线二线城市疯狂出现,颇有“烂大街”的趋势。我们不禁要问很多很多问题:

22670
来自专栏儿童编程

天干地支五行八卦的对应关系

19890
来自专栏Ken的杂谈

【系统设置】CentOS 修改机器名

18430
来自专栏儿童编程

一张图理清《梅花易数》梗概

学《易经》的目的不一定是为了卜卦,但是了解卜卦绝对能够让你更好地了解易学。今天用一张思维导图对《梅花易数》的主要内容进行概括,希望能够给学友们提供帮助。

32540
来自专栏儿童编程

我不是算命先生,却对占卜有了疑惑——如何论证“占卜前提”的正确与否

事出有因,我对《周易》感兴趣了很多年。只是觉得特别有趣,断断续续学习了一些皮毛。这几天又偶然接触到了《梅花易数》,觉得很是精彩,将五行八卦天干地支都串联了起来。...

15610

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励