gpt4 book ai didi

x86 - 我可以使用 LLVM jit 生成 AVX 矢量化代码吗?

转载 作者:行者123 更新时间:2023-12-04 15:22:48 26 4
gpt4 key购买 nike

我知道我可以在 EngineBuilder 中设置 mcpu 和 mattr 来生成矢量化代码。
但我发现铿锵前线必须涉及使用-mavx 的AVX。否则生成的程序集仅使用 xmm 寄存器。

有没有办法让 LLVM 知道可以在不涉及前端的情况下将 8 个浮点数放入 AVX 寄存器中?

我的测试代码只是向量添加:

float a[N], b[N];
float c[N];
// initialize a and b
for (int i = 0; i < N; ++i)
c[i] = a[i] + b[i];

最佳答案

TL;DR : 是的。您只需调用opt并告诉它向量化你的代码。

你绝对可以在没有 clang 的情况下做到这一点。矢量化器都是关于 LLVM IR 的,它们并不在 Clang 中。

我通过使用没有优化的 clang 从您的示例中得到了这个 IR(是的,我作弊了,然后注释了一两个):(数据布局和三元组很重要!)

target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.9.0"

define float* @f(i32 %N, float* nocapture readonly %a, float* nocapture readonly %b, float* %c) {
entry:
%cmp10 = icmp sgt i32 %N, 0 ; check for early exit
br i1 %cmp10, 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* %a, i64 %indvars.iv
%0 = load float* %arrayidx, align 4 ; %0 = a[i]
%arrayidx2 = getelementptr inbounds float* %b, i64 %indvars.iv
%1 = load float* %arrayidx2, align 4 ; %1 = a[i]

%add = fadd float %0, %1 ; %add = %0 + %1

%arrayidx4 = getelementptr inbounds float* %c, i64 %indvars.iv
store float %add, float* %arrayidx4, align 4 ; c[i] = %add

%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, %N ; test for loop exit
br i1 %exitcond, label %for.end, label %for.body

for.end: ; preds = %for.body, %entry
ret float* %c
}

现在你想对代码进行矢量化。然后,让我们通过循环矢量化器运行它。
opt a.ll -S -march=x86-64 -mcpu=btver2 -loop-vectorize

(我用 -S 运行它以获取控制台的输出)

现在我们用一个巨大的 vector.body 对 IR 进行了矢量化处理。 ,以及一些检查、预标题和额外的簿记代码。您将在文件中间看到:
  %171 = getelementptr inbounds float* %b, i64 %98
%172 = insertelement <8 x float*> %170, float* %171, i32 7
%173 = getelementptr float* %109, i32 0
%174 = bitcast float* %173 to <8 x float>*
%wide.load18 = load <8 x float>* %174, align 4
%175 = getelementptr float* %109, i32 8
%176 = bitcast float* %175 to <8 x float>*
%wide.load19 = load <8 x float>* %176, align 4
%177 = getelementptr float* %109, i32 16
%178 = bitcast float* %177 to <8 x float>*
%wide.load20 = load <8 x float>* %178, align 4
%179 = getelementptr float* %109, i32 24
%180 = bitcast float* %179 to <8 x float>*
%wide.load21 = load <8 x float>* %180, align 4
%181 = fadd <8 x float> %wide.load, %wide.load18
%182 = fadd <8 x float> %wide.load15, %wide.load19
%183 = fadd <8 x float> %wide.load16, %wide.load20
%184 = fadd <8 x float> %wide.load17, %wide.load21
%185 = getelementptr inbounds float* %c, i64 %5
%186 = insertelement <8 x float*> undef, float* %185, i32 0

这有点复杂,但大多数浮点加法( fadd )都在那里,并且只在向量上完成。让我们让它更简单,并使用 -O2 运行其他优化。或 -O3 .通过删除和/或折叠不需要或不盈利的部分,这将使 IR 变得更小、更简单。
opt a.ll -S -march=x86-64 -mcpu=btver2 -loop-vectorize -O3

嗯……因为我们现在已经有了 IR,它已经在向量上起作用了,我们只需要发射它。让我们迈出最后一步,调用 llc :
opt a.ll -S -march=x86-64 -mcpu=core-avx2 -loop-vectorize -O3 | llc -mcpu=core-avx2

查看反汇编,你有一个紧密的内部循环(如果你和我的名字相同,这应该是标签 LBB0_5 ),还有一堆记账代码。

您的代码现在已矢量化。

关于x86 - 我可以使用 LLVM jit 生成 AVX 矢量化代码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22548397/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com