【问题标题】:Why doesn't Clang vectorise big-int XOR?为什么 Clang 不向量化 big-int XOR?
【发布时间】:2014-03-12 12:31:43
【问题描述】:

当我编译这个简单的逐字异或示例时,Clang 3.4 不会对其进行向量化。为什么?它似乎比http://llvm.org/docs/Vectorizers.html#features 中的示例更简单,并且我们在单个单词之间没有数据依赖关系。所以理论上,这可以向量化。

#include <stdio.h>

void do_xor(const unsigned int num1[5], const unsigned int num2[5]) {
  unsigned int num3[5];

  // word-wise xor
  for (int i = 0; i < 5; ++i)
    num3[i] = num1[i] ^ num2[i];

  for (int i = 4; i >= 0; --i)
    printf("%08x", num3[i]);
  printf("\n");
}

使用clang -O3 -fslp-vectorize-aggressive -emit-llvm .....(强制矢量化)我们最终得到(剥离的非功能部分):

define void @do_xor(i32* nocapture readonly %num1, i32* nocapture readonly %num2) #0 {
.preheader4:
  %0 = load i32* %num1, align 4, !tbaa !1
  %1 = load i32* %num2, align 4, !tbaa !1
  %2 = xor i32 %1, %0
  %3 = getelementptr inbounds i32* %num1, i64 1
  %4 = load i32* %3, align 4, !tbaa !1
  %5 = getelementptr inbounds i32* %num2, i64 1
  %6 = load i32* %5, align 4, !tbaa !1
  %7 = xor i32 %6, %4
  %8 = getelementptr inbounds i32* %num1, i64 2
  %9 = load i32* %8, align 4, !tbaa !1
  %10 = getelementptr inbounds i32* %num2, i64 2
  %11 = load i32* %10, align 4, !tbaa !1
  %12 = xor i32 %11, %9
  %13 = getelementptr inbounds i32* %num1, i64 3
  %14 = load i32* %13, align 4, !tbaa !1
  %15 = getelementptr inbounds i32* %num2, i64 3
  %16 = load i32* %15, align 4, !tbaa !1
  %17 = xor i32 %16, %14
  %18 = getelementptr inbounds i32* %num1, i64 4
  %19 = load i32* %18, align 4, !tbaa !1
  %20 = getelementptr inbounds i32* %num2, i64 4
  %21 = load i32* %20, align 4, !tbaa !1
  %22 = xor i32 %21, %19
  %23 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([5 x i8]* @.str, i64 0, i64 0), i32 %22) #2
  %24 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([5 x i8]* @.str, i64 0, i64 0), i32 %17) #2
  %25 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([5 x i8]* @.str, i64 0, i64 0), i32 %12) #2
  %26 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([5 x i8]* @.str, i64 0, i64 0), i32 %7) #2
  %27 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([5 x i8]* @.str, i64 0, i64 0), i32 %2) #2
  %putchar = tail call i32 @putchar(i32 10) #2
  ret void
}

没有生成矢量代码。为什么?

【问题讨论】:

  • 该标志不会“强制”任何东西,矢量化循环及其加载/设置成本不可能比可以并行发出的 5 个简单、快速的按位 XOR 指令更快。另外,如何有效地处理第 5 个元素?
  • 我认为,IR 应该包含矢量代码。机器代码生成器应该决定向量是否比单个指令更有效并生成相应的代码。第 5 个元素总是可以作为单条指令处理——没问题?
  • 你应该让参数对齐到 16 个字节,然后才能向量化代码

标签: c clang vectorization llvm-ir


【解决方案1】:

我尝试连续增加 int 数组的大小(循环的大小),如果大整数 >= 14 个字,则似乎矢量化开始

但是我还是不明白为什么前端会有这个门槛。我仍然认为前端应该始终向量化,后端应该决定如何降低向量,因为它具有有关目标的信息(例如,完全支持的向量、指令的成本模型……)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-30
    • 2017-03-05
    • 2019-06-12
    • 2018-11-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多