在clang中矢量化一个函数

rah*_*hul 11 c++ vector simd clang++

我正在尝试使用clang根据此clang参考向量化以下函数.它需要一个字节数组的向量,并根据此RFC应用掩码.

static void apply_mask(vector<uint8_t> &payload, uint8_t (&masking_key)[4]) {
  #pragma clang loop vectorize(enable) interleave(enable)
  for (size_t i = 0; i < payload.size(); i++) {
    payload[i] = payload[i] ^ masking_key[i % 4];
  }
}
Run Code Online (Sandbox Code Playgroud)

以下标志传递给clang:

-O3
-Rpass=loop-vectorize
-Rpass-analysis=loop-vectorize
Run Code Online (Sandbox Code Playgroud)

但是,矢量化失败并出现以下错误:

WebSocket.cpp:5:
WebSocket.h:14:
In file included from boost/asio/io_service.hpp:767:
In file included from boost/asio/impl/io_service.hpp:19:
In file included from boost/asio/detail/service_registry.hpp:143:
In file included from boost/asio/detail/impl/service_registry.ipp:19:
c++/v1/vector:1498:18: remark: loop not vectorized: could not determine number
      of loop iterations [-Rpass-analysis]
    return this->__begin_[__n];
                 ^
c++/v1/vector:1498:18: error: loop not vectorized: failed explicitly specified
      loop vectorization [-Werror,-Wpass-failed]
Run Code Online (Sandbox Code Playgroud)

如何将此for循环向量化?

rah*_*hul 5

感谢@PaulR和@PeterCordes。将循环展开4倍。

void apply_mask(vector<uint8_t> &payload, const uint8_t (&masking_key)[4]) {
  const size_t size = payload.size();
  const size_t size4 = size / 4;
  size_t i = 0;
  uint8_t *p = &payload[0];
  uint32_t *p32 = reinterpret_cast<uint32_t *>(p);
  const uint32_t m = *reinterpret_cast<const uint32_t *>(&masking_key[0]);

#pragma clang loop vectorize(enable) interleave(enable)
  for (i = 0; i < size4; i++) {
    p32[i] = p32[i] ^ m;
  }

  for (i = (size4*4); i < size; i++) {
    p[i] = p[i] ^ masking_key[i % 4];
  }
}
Run Code Online (Sandbox Code Playgroud)

gcc.godbolt代码

  • 展开是将其向量化的唯一方法,我在gcc.godbolt上的所有编译器上进行了尝试,没有人能够在不展开的情况下进行向量化。 (2认同)