| ... | @@ -4433,7 +4433,6 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4433,7 +4433,6 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4433 | const ty = func.air.typeOfIndex(inst); | 4433 | const ty = func.air.typeOfIndex(inst); |
| 4434 | const elem_ty = ty.childType(); | 4434 | const elem_ty = ty.childType(); |
| 4435 | | 4435 | |
| 4436 | const result = try func.allocLocal(ty); | | |
| 4437 | if (determineSimdStoreStrategy(ty, func.target) == .direct) blk: { | 4436 | if (determineSimdStoreStrategy(ty, func.target) == .direct) blk: { |
| 4438 | switch (operand) { | 4437 | switch (operand) { |
| 4439 | // when the operand lives in the linear memory section, we can directly | 4438 | // when the operand lives in the linear memory section, we can directly |
| ... | @@ -4447,6 +4446,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4447,6 +4446,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4447 | 64 => std.wasm.simdOpcode(.v128_load64_splat), | 4446 | 64 => std.wasm.simdOpcode(.v128_load64_splat), |
| 4448 | else => break :blk, // Cannot make use of simd-instructions | 4447 | else => break :blk, // Cannot make use of simd-instructions |
| 4449 | }; | 4448 | }; |
| | 4449 | const result = try func.allocLocal(ty); |
| 4450 | try func.emitWValue(operand); | 4450 | try func.emitWValue(operand); |
| 4451 | // TODO: Add helper functions for simd opcodes | 4451 | // TODO: Add helper functions for simd opcodes |
| 4452 | const extra_index = @intCast(u32, func.mir_extra.items.len); | 4452 | const extra_index = @intCast(u32, func.mir_extra.items.len); |
| ... | @@ -4468,6 +4468,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4468,6 +4468,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4468 | 64 => if (elem_ty.isInt()) std.wasm.simdOpcode(.i64x2_splat) else std.wasm.simdOpcode(.f64x2_splat), | 4468 | 64 => if (elem_ty.isInt()) std.wasm.simdOpcode(.i64x2_splat) else std.wasm.simdOpcode(.f64x2_splat), |
| 4469 | else => break :blk, // Cannot make use of simd-instructions | 4469 | else => break :blk, // Cannot make use of simd-instructions |
| 4470 | }; | 4470 | }; |
| | 4471 | const result = try func.allocLocal(ty); |
| 4471 | try func.emitWValue(operand); | 4472 | try func.emitWValue(operand); |
| 4472 | const extra_index = @intCast(u32, func.mir_extra.items.len); | 4473 | const extra_index = @intCast(u32, func.mir_extra.items.len); |
| 4473 | try func.mir_extra.append(func.gpa, opcode); | 4474 | try func.mir_extra.append(func.gpa, opcode); |
| ... | @@ -4478,8 +4479,22 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4478,8 +4479,22 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4478 | else => unreachable, | 4479 | else => unreachable, |
| 4479 | } | 4480 | } |
| 4480 | } | 4481 | } |
| | 4482 | const elem_size = elem_ty.bitSize(func.target); |
| | 4483 | const vector_len = @intCast(usize, ty.vectorLen()); |
| | 4484 | if ((!std.math.isPowerOfTwo(elem_size) or elem_size % 8 != 0) and vector_len > 1) { |
| | 4485 | return func.fail("TODO: WebAssembly `@splat` for arbitrary element bitsize {d}", .{elem_size}); |
| | 4486 | } |
| | 4487 | |
| | 4488 | const result = try func.allocStack(ty); |
| | 4489 | const elem_byte_size = @intCast(u32, elem_ty.abiSize(func.target)); |
| | 4490 | var index: usize = 0; |
| | 4491 | var offset: u32 = 0; |
| | 4492 | while (index < vector_len) : (index += 1) { |
| | 4493 | try func.store(result, operand, elem_ty, offset); |
| | 4494 | offset += elem_byte_size; |
| | 4495 | } |
| 4481 | | 4496 | |
| 4482 | return func.fail("TODO: Implement wasm airSplat unrolled", .{}); | 4497 | return func.finishAir(inst, result, &.{ty_op.operand}); |
| 4483 | } | 4498 | } |
| 4484 | | 4499 | |
| 4485 | fn airSelect(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 4500 | fn airSelect(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |