authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-04-02 16:50:39+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-04-02 21:54:01+02:00
log5ba03369ee11b6b57dcad99ab7ed8ce3b08c7456
tree7c22ab203d3eaa3fb7d92736e02d2320cc89f6ec
parent219fa192c6311c627d4b507c928ebcf2920af9e8

wasm: Implement `@mulAdd` for f32, f64

This implements the `mul_add` AIR instruction for floats of bitsize 32 and 64. f16's will require us being able to extend and truncate f16's to correctly store and load them without losing the accuracy.

1 files changed, 23 insertions(+), 3 deletions(-)

src/arch/wasm/CodeGen.zig+23-3
......@@ -1309,6 +1309,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
13091309 .xor => self.airBinOp(inst, .xor),
13101310 .max => self.airMaxMin(inst, .max),
13111311 .min => self.airMaxMin(inst, .min),
1312 .mul_add => self.airMulAdd(inst),
13121313
13131314 .add_with_overflow => self.airBinOpOverflow(inst, .add),
13141315 .sub_with_overflow => self.airBinOpOverflow(inst, .sub),
......@@ -1468,7 +1469,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
14681469 .atomic_store_seq_cst,
14691470 .atomic_rmw,
14701471 .tag_name,
1471 .mul_add,
14721472 => |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
14731473 };
14741474}
......@@ -1721,8 +1721,7 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue {
17211721 else
17221722 .signed;
17231723
1724 // TODO: Revisit below to determine if optional zero-sized pointers should still have abi-size 4.
1725 const abi_size = if (ty.isPtrLikeOptional()) @as(u8, 4) else @intCast(u8, ty.abiSize(self.target));
1724 const abi_size = @intCast(u8, ty.abiSize(self.target));
17261725
17271726 const opcode = buildOpcode(.{
17281727 .valtype1 = typeToValtype(ty, self.target),
......@@ -3912,3 +3911,24 @@ fn airMaxMin(self: *Self, inst: Air.Inst.Index, op: enum { max, min }) InnerErro
39123911
39133912 return result;
39143913}
3914
3915fn airMulAdd(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
3916 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
3917 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3918 const bin_op = self.air.extraData(Air.Bin, pl_op.payload).data;
3919 const ty = self.air.typeOfIndex(inst);
3920 if (ty.zigTypeTag() == .Vector) {
3921 return self.fail("TODO: `@mulAdd` for vectors", .{});
3922 }
3923
3924 if (ty.floatBits(self.target) == 16) {
3925 return self.fail("TODO: `@mulAdd` for f16", .{});
3926 }
3927
3928 const addend = try self.resolveInst(pl_op.operand);
3929 const lhs = try self.resolveInst(bin_op.lhs);
3930 const rhs = try self.resolveInst(bin_op.rhs);
3931
3932 const mul_result = try self.binOp(lhs, rhs, ty, .mul);
3933 return self.binOp(mul_result, addend, ty, .add);
3934}