LLVM IR:有效地对矢量求和

时间:2013-02-07 00:15:45

标签: llvm llvm-ir llvm-3.2

我正在编写一个生成LLVM IR指令的编译器。我正在广泛地使用矢量。

我希望能够对向量中的所有元素求和。现在我只是单独提取每个元素并手动添加它们,但它让我觉得这正是硬件应该能够帮助的东西(因为它听起来像一个非常常见的操作)。但似乎没有内在的做法。

最好的方法是什么?我正在使用LLVM 3.2。

1 个答案:

答案 0 :(得分:3)

首先,即使不使用内在函数,也可以生成log(n)向量加法(n为向量长度)而不是n标量加法,这是一个向量大小为8的示例:

define i32 @sum(<8 x i32> %a) {
  %v1 = shufflevector <8 x i32> %a, <8 x i32> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  %v2 = shufflevector <8 x i32> %a, <8 x i32> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
  %sum1 = add <4 x i32> %v1, %v2
  %v3 = shufflevector <4 x i32> %sum1, <4 x i32> undef, <2 x i32> <i32 0, i32 1>
  %v4 = shufflevector <4 x i32> %sum1, <4 x i32> undef, <2 x i32> <i32 2, i32 3>
  %sum2 = add <2 x i32> %v3, %v4
  %v5 = extractelement <2 x i32> %sum2, i32 0
  %v6 = extractelement <2 x i32> %sum2, i32 1
  %sum3 = add i32 %v5, %v6
  ret i32 %sum3
}

如果您的目标支持这些矢量添加,那么很可能会降低上述内容以使用这些指令,从而为您提供性能。

关于内在函数,没有与目标无关的内在函数来处理这个问题。但是,如果您要编译为x86,则可以访问hadd个instrinsics(例如llvm.x86.int_x86_ssse3_phadd_sw_128一起添加两个<4 x i32>向量)。您仍然需要执行与上述类似的操作,只能替换add指令。

有关此内容的更多信息,您可以搜索“水平和”或“水平矢量和”;例如,以下是x86上水平和的一些相关stackoverflow问题: