编译器优化:何为SLP矢量化( 三 )


b. 函数follow_def_uses 去寻找对b, e, h 使用的语句,将(3, 6) 和 (6, 9) 加入P ,如(c)
c. 函数follow_use_defs 去寻找 c, f, j 进行def的语句,将(2, 5) 和 (5, 8) 加入P ,如(d)
d. 再执行一次follow_def_uses,发现没有新的语句对可以加入P了,停止 。
(4)执行combine_packs:
a. (1), (4))和 (4), (7) 合并为 (1), (4), (7)
b. (3), (6) 和 (6), (9) 合并为 (3), (6), (9)
c. (2), (5) 和 (5), (8) 合并为 (2), (5), (8)
合并后状态,如(e) 。
(5) 执行调度:注意依赖关系,比如 3 依赖于1, 2,最终状态如(f) 。
2.Loop-Aware SLP 算法介绍LLVM 中的 SLP vectorization ,是受Loop-Aware SLP in GCC(by Ira Rosen, Dorit Nuzman,Ayal Zaks) [4]这篇论文启发来实现的 。

编译器优化:何为SLP矢量化

文章插图
 
2.1 简介Loop-Aware 方法是对基础 SLP 方法的改进,更加重视对跟Loop相关的向量化机会挖掘,其思想是 :
首先,通过循环展开将迭代间并行转换为迭代内并行,使循环体内的同构语句条数足够多;
再利用 SLP 方法进行向量发掘 。当循环展开次数为 1 时,Loop-Aware 方法相当于 SLP 方法,当循环展开次数为向量化因子 (vector factor,简称 VF) 时,将同一条语句展开后的多条语句打包成向量 。然而,当循环展开不合法或者并行度低于向量化因子时,Loop-Aware 方法无法简单实施 。
换言之,Loop-Aware 向量化方法的实质就是当迭代内并行度较低时,通过循环展开将迭代间并行转换为迭代内并行,其要求循环的迭代间并行度较高 。
一个典型例子,它可以使能以下因同构语句条数不够多而原始SLP无法矢量化的场景:
for (i=0; i<N; i++){ a[2*i] = b[2*i] + x0; a[2*i+1] = b[2*i+1] + x1;}需要借助loop unroll,最终矢量化为以下形式:
for (i=0; i<N/2; i++){ va[4*i:4*i+3] = vb[4*i:4*i+3] + {x0,x1,x0,x1};}2.2 具体差异与原始SLP方法的差别,论文作者在其提交给GCC的PATCH中有说明[5],主要有以下三条:
(1)Loop-Aware SLP 着眼于Loop相关的bb块,而不是程序中的任意bb块 。这么做的原因有两个,一是可以复用已有的循环矢量化的框架,二是大多数有价值的优化机会都在循环中 。
(2)原始SLP算法起始于相邻内存的load或stroe,称之为seed,根据def-use扩展,并合并成Vectorize Size(VS)大小的组 。Loop-Aware SLP的seed来自于interleaving analysis之后预先确定的一组相邻store,所以不需要原始算法中的合并这一步骤 。具体来说就是,Loop-Aware借助loop-unroll使得在寻找seed时就能天然地找到能够刚好合并到一个向量寄存器中的指令,而原始SLP需要在合并阶段做排布 。
(3)Loop-Aware SLP结合了SLP-based和Loop-based矢量化,所以对于以下循环:
for (i=0; i<N; i++){a[4*i] = b[4*i] + x0;a[4*i+1] = b[4*i+1] + x1;a[4*i+2] = b[4*i+2] + x2;a[4*i+3] = b[4*i+3] + x3;c<i> = 0;}可以优化成以下形式:
for (i=0; i<N/4; i++){//SLP矢量化部分va[16*i:16*i+3] = vb[16*i:16*i+3] + {x0,x1,x2,x3};va[16*i+4:16*i+7] = vb[16*i+4:16*i+7] + {x0,x1,x2,x3};va[16*i+8:16*i+11] = vb[16*i+8:16*i+11] + {x0,x1,x2,x3};va[16*i+12:16*i+15] = vb[16*i+12:16*i+15] + {x0,x1,x2,x3};//Loop矢量化部分vc[4*i:4*i+3] = {0,0,0,0};}3.源码阅读SLP 是一个 transform pass,在 LLVM 14 中该pass 的实现代码位于
llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp 和 llvm/Transforms/Vectorize/SLPVectorizer.h中 。
3.1 提供的选项(1)开源选项
编译器优化:何为SLP矢量化

文章插图
 
(2)毕昇编译器额外提供选项
编译器优化:何为SLP矢量化

文章插图
 
3.2 实现该 pass 的实现较为复杂,源码有10k+,粗略结构如下:
编译器优化:何为SLP矢量化


推荐阅读