| ... | ... | @@ -4430,9 +4430,56 @@ fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4430 | 4430 | fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4431 | 4431 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; |
| 4432 | 4432 | const operand = try func.resolveInst(ty_op.operand); |
| 4433 | const ty = func.air.typeOfIndex(inst); |
| 4434 | const elem_ty = ty.childType(); |
| 4433 | 4435 | |
| 4434 | | _ = operand; |
| 4435 | | return func.fail("TODO: Implement wasm airSplat", .{}); |
| 4436 | const result = try func.allocLocal(ty); |
| 4437 | if (determineSimdStoreStrategy(ty, func.target) == .direct) blk: { |
| 4438 | switch (operand) { |
| 4439 | // when the operand lives in the linear memory section, we can directly |
| 4440 | // load and splat the value at once. Meaning we do not first have to load |
| 4441 | // the scalar value onto the stack. |
| 4442 | .stack_offset, .memory, .memory_offset => { |
| 4443 | const opcode = switch (elem_ty.bitSize(func.target)) { |
| 4444 | 8 => std.wasm.simdOpcode(.v128_load8_splat), |
| 4445 | 16 => std.wasm.simdOpcode(.v128_load16_splat), |
| 4446 | 32 => std.wasm.simdOpcode(.v128_load32_splat), |
| 4447 | 64 => std.wasm.simdOpcode(.v128_load64_splat), |
| 4448 | else => break :blk, // Cannot make use of simd-instructions |
| 4449 | }; |
| 4450 | try func.emitWValue(operand); |
| 4451 | // TODO: Add helper functions for simd opcodes |
| 4452 | const extra_index = @intCast(u32, func.mir_extra.items.len); |
| 4453 | // stores as := opcode, offset, alignment (opcode::memarg) |
| 4454 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 4455 | opcode, |
| 4456 | operand.offset(), |
| 4457 | elem_ty.abiAlignment(func.target), |
| 4458 | }); |
| 4459 | try func.addInst(.{ .tag = .simd, .data = .{ .payload = extra_index } }); |
| 4460 | try func.addLabel(.local_set, result.local.value); |
| 4461 | return func.finishAir(inst, result, &.{ty_op.operand}); |
| 4462 | }, |
| 4463 | .local => { |
| 4464 | const opcode = switch (elem_ty.bitSize(func.target)) { |
| 4465 | 8 => std.wasm.simdOpcode(.i8x16_splat), |
| 4466 | 16 => std.wasm.simdOpcode(.i16x8_splat), |
| 4467 | 32 => if (elem_ty.isInt()) std.wasm.simdOpcode(.i32x4_splat) else std.wasm.simdOpcode(.f32x4_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 |
| 4470 | }; |
| 4471 | try func.emitWValue(operand); |
| 4472 | const extra_index = @intCast(u32, func.mir_extra.items.len); |
| 4473 | try func.mir_extra.append(func.gpa, opcode); |
| 4474 | try func.addInst(.{ .tag = .simd, .data = .{ .payload = extra_index } }); |
| 4475 | try func.addLabel(.local_set, result.local.value); |
| 4476 | return func.finishAir(inst, result, &.{ty_op.operand}); |
| 4477 | }, |
| 4478 | else => unreachable, |
| 4479 | } |
| 4480 | } |
| 4481 | |
| 4482 | return func.fail("TODO: Implement wasm airSplat unrolled", .{}); |
| 4436 | 4483 | } |
| 4437 | 4484 | |
| 4438 | 4485 | fn airSelect(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |