LLVM IR:有效地对向量求和

LLVM IR:有效地对向量求和,llvm,llvm-ir,llvm-3.2,Llvm,Llvm Ir,Llvm 3.2,我正在编写一个生成LLVM IR指令的编译器。我正在广泛研究向量 我希望能够对向量中的所有元素求和。现在,我只是单独提取每个元素并手动将它们相加,但我突然想到,这正是硬件应该能够帮助解决的问题(因为这听起来像是一个非常常见的操作)。但这似乎没有内在的原因 最好的方法是什么?我使用的是LLVM 3.2。首先,即使不使用内部函数,也可以生成log(n)向量加法(n为向量长度),而不是n标量加法,下面是向量大小为8的示例: define i32 @sum(<8 x i32> %a) {

我正在编写一个生成LLVM IR指令的编译器。我正在广泛研究向量

我希望能够对向量中的所有元素求和。现在,我只是单独提取每个元素并手动将它们相加,但我突然想到,这正是硬件应该能够帮助解决的问题(因为这听起来像是一个非常常见的操作)。但这似乎没有内在的原因


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

首先,即使不使用内部函数,也可以生成
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
}
define i32@sum(%a){
%v1=shufflevector%a,未定义,
%v2=shufflevector%a,未定义,
%sum1=添加%v1,%v2
%v3=shufflevector%sum1,未定义,
%v4=shufflevector%sum1,未定义,
%sum2=添加%v3,%v4
%v5=提取元素%sum2,i32 0
%v6=提取元素%sum2,i32 1
%sum3=添加i32%v5,%v6
ret i32%sum3
}
如果您的目标支持这些向量加法,则很可能会降低上述内容以使用这些指令,从而提高您的性能

关于内部函数,没有独立于目标的内部函数来处理这个问题。但是,如果您正在编译到x86,您确实可以访问
hadd
instrinsic(例如
llvm.x86.int\u x86\u ssse3\u phadd\u sw\u 128
以将两个
向量添加到一起)。您仍然需要执行与上述类似的操作,只能替换
add
指令

有关这方面的更多信息,您可以搜索“水平和”或“水平向量和”;例如,对于x86上的水平和,以下是一些相关的stackoverflow问题:


我完全没有想到这一点。它很优雅,工作也很好——我使用浮点和双精度,上面的代码反复转换为6和7条指令。我不认为我会做得比这更好(特别是如果代码是优化友好的)。也感谢那些让谷歌开心的神奇关键词;当你知道它叫什么的时候,找东西就容易多了。。。