LLVM ScalarEvolution Pass 无法计算循环向量器的退出计数

Posted

技术标签:

【中文标题】LLVM ScalarEvolution Pass 无法计算循环向量器的退出计数【英文标题】:LLVM ScalarEvolution Pass Cannot Compute Exit Count for Loop Vectorizer 【发布时间】:2014-11-18 06:58:02 【问题描述】:

我正在尝试弄清楚如何运行 LLVM 的内置循环矢量化器。我有一个小程序,其中包含一个非常简单的循环(我曾经有过一些输出,这就是为什么尽管从未使用过 stdio.h 仍然包含在内):

  1 #include <stdio.h>
  2 
  3 unsigned NUM_ELS = 10000;
  4 
  5 int main() 
  6     int A[NUM_ELS];
  7 
  8 #pragma clang loop vectorize(enable)
  9     for (int i = 0; i < NUM_ELS; ++i) 
 10         A[i] = i*2;
 11     
 12 
 13     return 0;
 14 

如您所见,它没有任何用处;我只需要 for 循环可以矢量化。我正在用

将它编译成 LLVM 字节码
clang -emit-llvm -O0 -c loop1.c -o loop1.bc
llvm-dis -f loop1.bc

然后我正在应用矢量化器

opt -loop-vectorize -force-vector-width=4 -S -debug loop1.ll

但是,调试输出给了我这个:

LV: Checking a loop in "main" from loop1.bc
LV: Loop hints: force=? width=4 unroll=0
LV: Found a loop: for.cond
LV: SCEV could not compute the loop exit count.
LV: Not vectorizing: Cannot prove legality.

我在 LLVM 源代码中进行了一些研究,看起来 SCEV 来自 ScalarEvolution 通道,它的任务(除其他外)计算返回到循环条件的后边数,其中这种情况(如果我没记错的话)应该是行程计数减去第一次行程(在这种情况下为 9,999)。我在一个更大的基准上运行了这个 pass,它在每个循环中都给了我完全相同的错误,所以我猜这不是循环本身,而是我没有给它足够的信息。

我花了相当多的时间梳理文档和 Google 结果,以找到使用此转换的完整 opt 命令的示例,但到目前为止还没有成功;对于我可能遗漏的任何提示,我将不胜感激(我是矢量化代码的新手,所以它可能非常明显)。

谢谢,

斯蒂芬

【问题讨论】:

【参考方案1】:

矢量化取决于之前需要运行的其他优化的数量。它们根本不会在 -O0 处运行,因此您不能期望您的代码会在那里“只是”矢量化。

在 opt cmdline 中的 -loop-vectorize 之前添加 -O2 会有所帮助(确保您的“A”数组是外部的/以某种方式使用,否则一切都会被优化掉)。

【讨论】:

我可以发誓我已经尝试过了(尽管使用 -O3 而不是 -O2),但无法使优化注释起作用,因此看不到矢量化的发生。但是,回到这一点并遵循您的建议已经奏效。我不知道为什么我假设标量进化正在运行,而它显然不是。谢谢!

以上是关于LLVM ScalarEvolution Pass 无法计算循环向量器的退出计数的主要内容,如果未能解决你的问题,请参考以下文章

LLVM 之 IR 篇:如何基于传统 Pass 框架扩展 LLVM IR 优化器

LLVM 之 IR 篇:如何基于新 Pass 框架扩展 LLVM IR 优化器

开发和调试第一个 LLVM Pass

LLVM 之 IR 篇:如何编写内联 Pass

LLVM 之 IR 篇:如何编写内联 Pass

LLVM每日谈之五十五 浅谈对Pass的错误认知及其原因