#Inefficient WASM instructions emitted by LLVM

1 messages · Page 1 of 1 (latest)

broken wasp
#
const row16: @Vector(8, i16) = block[8 * r ..][0..8].*;
const row32: @Vector(8, i32) = row16;
res[8 * r ..][0..8].* = @as(@Vector(8, f32), @floatFromInt(row32));

I'm a bit lost here. I'm trying to convert 8 i16 to 8 f32. The WASM instructions for this are roughly:

  • Load i16x8
  • Get low 4 elements as i32x4 (this exists as an instruction)
  • Get high 4 elements as i32x4 (this exists as an instruction)
  • Convert first i32x4 to f32x4 (this exists as an instruction)
  • Convert second i32x4 to f32x4 (this exists as an instruction)
  • Store it

But LLVM instead is literally picking out one element at a time from the i16x8 using extract_lane, converts it to float as a scalar, then stores that. I understand why it might do that if I went directly from i16->f32, but here I am literally guiding it through the intermediate i32 step, but with no luck. How do I fix this?

I looked for LLVM WASM intrinsics (https://codebrowser.dev/llvm/llvm_build/include/llvm/IR/IntrinsicsWebAssembly.h.html), but none of the instructions I need for this are in there.

broken wasp
#

For the record:

inline fn extendLowS(v: @Vector(8, i16)) @Vector(4, i32) {
    return asm volatile (
        \\local.get %[v]
        \\i32x4.extend_low_i16x8_s
        \\local.set %[ret]
        : [ret] "=r" (-> @Vector(4, i32)),
        : [v] "r" (v),
    );
}