LLVM中的自动向量化:Auto-Vectorization in LLVM

1)Auto-Vectorization in LLVM — LLVM 21.0.0git documentation

2)

LLVM有两个矢量器:循环矢量器和SLP矢量器。这些矢量器专注于不同的优化机会,并使用不同的技术。SLP矢量化器将代码中的多个标量合并为矢量,而循环矢量化器则扩展循环中的指令,以对多个连续迭代进行操作。
默认情况下,循环矢量器和SLP矢量器都处于启用状态。

3)相关命令参数

clang ... -fno-vectorize  file.c
clang  -mllvm -force-vector-width=8 ...
opt -loop-vectorize -force-vector-width=8 ...
clang  -mllvm -force-vector-interleave=2 ...
opt -loop-vectorize -force-vector-interleave=2 ...

#pragma clang-loop指令允许为后续的for、while、do-while或基于c++11范围的for循环指定循环矢量化提示。该指令允许启用或禁用矢量化和交织。矢量宽度和交织计数也可以手动指定。以下示例明确启用了矢量化和交织:

4)

#pragma clang loop vectorize(enable) interleave(enable)
while(...) {
  ...
}


#pragma clang loop vectorize_width(2) interleave_count(2)
for(...) {
  ...
}
#pragma clang loop vectorize(enable)
for (int i = 0; i < Length; i++) {
  switch(A[i]) {
  case 0: A[i] = i*2; break;
  case 1: A[i] = i;   break;
  default: A[i] = 0;
  }
}

5)Loops with unknown trip count

循环矢量器支持行程计数未知的循环。在下面的循环中,迭代的开始和结束点是未知的,循环矢量化器有一种机制来矢量化不从零开始的循环。在这个例子中,'n'可能不是向量宽度的倍数,矢量器必须将最后几次迭代作为标量代码执行。保留循环的标量副本会增加代码大小。

void bar(float *A, float* B, float K, int start, int end) {
  for (int i = start; i < end; ++i)
    A[i] *= B[i] + K;
}

6)Runtime Checks of Pointers

在下面的例子中,如果指针A和B指向连续的地址,那么对代码进行矢量化是非法的,因为A的一些元素将在从数组B读取之前被写入。
一些程序员使用“restrict”关键字来通知编译器指针是不相交的,但在我们的例子中,循环矢量器无法知道指针A和B是唯一的。循环矢量器通过放置代码来处理这个循环,这些代码在运行时检查数组A和B是否指向不相交的内存位置。如果数组A和B重叠,则执行循环的标量版本。

void bar(float *A, float* B, float K, int n) {
  for (int i = 0; i < n; ++i)
    A[i] *= B[i] + K;
}

7)Reductions

在这个例子中,sum变量由循环的连续迭代使用。通常,这会阻止矢量化,但矢量化器可以检测到“sum”是一个缩减变量。变量“sum”变成一个整数向量,在循环结束时,数组的元素被加在一起以创建正确的结果。我们支持多种不同的缩减操作,如加法、乘法、XOR、AND和OR。

int foo(int *A, int n) {
  unsigned sum = 0;
  for (int i = 0; i < n; ++i)
    sum += A[i] + 5;
  return sum;
}

8)Inductions

在这个例子中,感应变量i的值被保存到一个数组中。循环矢量器知道对感应变量进行矢量化。

void bar(float *A, int n) {
  for (int i = 0; i < n; ++i)
    A[i] = i;
}

9)If Conversion

循环矢量器能够“展平”代码中的IF语句,并生成单个指令流。循环矢量器支持最内层循环中的任何控制流。最内层的循环可能包含IF、ELSE甚至GOTO的复杂嵌套。

int foo(int *A, int *B, int n) {
  unsigned sum = 0;
  for (int i = 0; i < n; ++i)
    if (A[i] > B[i])
      sum += A[i] + 5;
  return sum;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值