Ограничения встроенного asm GCC для регистров SIMB XBurst (MXU2)? - PullRequest
1 голос
/ 28 октября 2019

Мы переписываем код SIMD MIPS gemmlowp с MSA на MXU2, который отличается от SIMA реализацией SIMD.

В исходном MSA регистры SIMD w0-w31 являются псевдонимами для регистров с плавающей запятой f0-f31, который может быть передан как встроенное ограничение asm:

inline void MipsMsaStore4x8(const RegBlockUint8<8, 4>& src,
std::uint8_t* dst_ptr, int stride) {
  // Assembly temporaries that will be handily referred to by their names.
  std::uint8_t *dst_ptr1, *dst_ptr2, *dst_ptr3;
  int tmp0, tmp1, tmp2, tmp3;
  asm volatile(
    GEMMLOWP_MIPS_XADDU " %[dst_ptr1], %[dst_ptr0], %[stride]\n"
    GEMMLOWP_MIPS_XLSA  " %[dst_ptr2], %[stride], %[dst_ptr0], 1\n"
    GEMMLOWP_MIPS_XLSA  " %[dst_ptr3], %[stride], %[dst_ptr1], 1\n"
    "copy_s.w             %[tmp0], %w[src0][0]\n"
    "copy_s.w             %[tmp1], %w[src0][1]\n"
    "copy_s.w             %[tmp2], %w[src0][2]\n"
    "copy_s.w             %[tmp3], %w[src0][3]\n"
    "swr                  %[tmp0], 0(%[dst_ptr0])\n"
    "swl                  %[tmp0], 3(%[dst_ptr0])\n"
    "swr                  %[tmp1], 4(%[dst_ptr0])\n"
    "swl                  %[tmp1], 7(%[dst_ptr0])\n"
    "swr                  %[tmp2], 0(%[dst_ptr1])\n"
    "swl                  %[tmp2], 3(%[dst_ptr1])\n"
    "swr                  %[tmp3], 4(%[dst_ptr1])\n"
    "swl                  %[tmp3], 7(%[dst_ptr1])\n"
    "copy_s.w             %[tmp0], %w[src1][0]\n"
    "copy_s.w             %[tmp1], %w[src1][1]\n"
    "copy_s.w             %[tmp2], %w[src1][2]\n"
    "copy_s.w             %[tmp3], %w[src1][3]\n"
    "swr                  %[tmp0], 0(%[dst_ptr2])\n"
    "swl                  %[tmp0], 3(%[dst_ptr2])\n"
    "swr                  %[tmp1], 4(%[dst_ptr2])\n"
    "swl                  %[tmp1], 7(%[dst_ptr2])\n"
    "swr                  %[tmp2], 0(%[dst_ptr3])\n"
    "swl                  %[tmp2], 3(%[dst_ptr3])\n"
    "swr                  %[tmp3], 4(%[dst_ptr3])\n"
    "swl                  %[tmp3], 7(%[dst_ptr3])\n"
    :
    // Outputs.
    [dst_ptr0] "+r"(dst_ptr), [dst_ptr1] "=&r"(dst_ptr1),
    [dst_ptr2] "=&r"(dst_ptr2), [dst_ptr3] "=&r"(dst_ptr3), [tmp0] "=&r (tmp0),
    [tmp1] "=&r"(tmp1), [tmp2] "=&r"(tmp2), [tmp3] "=&r"(tmp3)
    :
    // Inputs.
    [src0] "f"(src.buf.reg[0]), [src1] "f"(src.buf.reg[1]),
    [stride] "r"(stride)
    :
    // Clobbers.
    "memory");

Однако вместо этого MXU2 использует независимый регистровый файл vr0-vr31. Итак, наш код выглядит следующим образом:

 asm volatile(
    GEMMLOWP_MIPS_XADDU " %[dst_ptr1], %[dst_ptr0], %[stride]\n"
    GEMMLOWP_MIPS_XADDU " %[dst_ptr2], %[dst_ptr1], %[stride]\n"
    GEMMLOWP_MIPS_XADDU " %[dst_ptr3], %[dst_ptr2], %[stride]\n"
    "mtcpusw              %[tmp0], %vr[src0][0]\n"
    "mtcpusw              %[tmp1], %vr[src0][1]\n"
    "mtcpusw              %[tmp2], %vr[src0][2]\n"
    "mtcpusw              %[tmp3], %vr[src0][3]\n"
    "swr                  %[tmp0], 0(%[dst_ptr0])\n"
    "swl                  %[tmp0], 3(%[dst_ptr0])\n"
...
    "swr                  %[tmp3], 4(%[dst_ptr3])\n"
    "swl                  %[tmp3], 7(%[dst_ptr3])\n"
    :
    // Outputs.
    [dst_ptr0] "+r"(dst_ptr),
    [dst_ptr1] "=&r"(dst_ptr1),
    [dst_ptr2] "=&r"(dst_ptr2),
    [dst_ptr3] "=&r"(dst_ptr3),
    [tmp0] "=&r"(tmp0),
    [tmp1] "=&r"(tmp1),
    [tmp2] "=&r"(tmp2),
    [tmp3] "=&r"(tmp3)
    :
    // Inputs.
    [stride] "r"(stride),
    [src0] "vr"(src.buf.reg[0]),
    [src1] "vr"(src.buf.reg[1])
    :
    // Clobbers.
    "memory");

Но GCC не принимает 'vr' в качестве допустимого ограничения:

error: inconsistent operand constraints in an 'asm'

Что нам теперь делать?

...