authorgravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2023-09-10 15:59:02+02:00
committergravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2023-09-10 15:59:02+02:00
log55694c2a4df8d11f5197b57393b0c64664d045b9
treeb213b7f9757ffc9f44189c0bbb59db6685da1fa6
parent673ebfabd1c85c7f701e588aff1a05deaf29cd94

wasm: implement comparison on f80 and f128


1 files changed, 41 insertions(+), 20 deletions(-)

src/arch/wasm/CodeGen.zig+41-20
......@@ -3470,10 +3470,10 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO
34703470 // both lhs and rhs, as well as checking the payload are matching of lhs and rhs
34713471 return func.cmpOptionals(lhs, rhs, ty, op);
34723472 }
3473 } else if (ty.isAnyFloat()) {
3474 return func.cmpFloat(ty, lhs, rhs, op);
34733475 } else if (isByRef(ty, mod)) {
34743476 return func.cmpBigInt(lhs, rhs, ty, op);
3475 } else if (ty.isAnyFloat() and ty.floatBits(func.target) == 16) {
3476 return func.cmpFloat16(lhs, rhs, op);
34773477 }
34783478
34793479 // ensure that when we compare pointers, we emit
......@@ -3505,26 +3505,47 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO
35053505 return WValue{ .stack = {} };
35063506}
35073507
3508/// Compares 16-bit floats
3509/// NOTE: The result value remains on top of the stack.
3510fn cmpFloat16(func: *CodeGen, lhs: WValue, rhs: WValue, op: std.math.CompareOperator) InnerError!WValue {
3511 const opcode: wasm.Opcode = buildOpcode(.{
3512 .op = switch (op) {
3513 .lt => .lt,
3514 .lte => .le,
3515 .eq => .eq,
3516 .neq => .ne,
3517 .gte => .ge,
3518 .gt => .gt,
3508/// Compares two floats.
3509/// NOTE: Leaves the result of the comparison on top of the stack.
3510fn cmpFloat(func: *CodeGen, ty: Type, lhs: WValue, rhs: WValue, cmp_op: std.math.CompareOperator) InnerError!WValue {
3511 const float_bits = ty.floatBits(func.target);
3512
3513 const op: Op = switch (cmp_op) {
3514 .lt => .lt,
3515 .lte => .le,
3516 .eq => .eq,
3517 .neq => .ne,
3518 .gte => .ge,
3519 .gt => .gt,
3520 };
3521
3522 switch (float_bits) {
3523 16 => {
3524 _ = try func.fpext(lhs, Type.f16, Type.f32);
3525 _ = try func.fpext(rhs, Type.f16, Type.f32);
3526 const opcode = buildOpcode(.{ .op = op, .valtype1 = .f32 });
3527 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
3528 return .stack;
35193529 },
3520 .valtype1 = .f32,
3521 .signedness = .unsigned,
3522 });
3523 _ = try func.fpext(lhs, Type.f16, Type.f32);
3524 _ = try func.fpext(rhs, Type.f16, Type.f32);
3525 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
3530 32, 64 => {
3531 try func.emitWValue(lhs);
3532 try func.emitWValue(rhs);
3533 const val_type: wasm.Valtype = if (float_bits == 32) .f32 else .f64;
3534 const opcode = buildOpcode(.{ .op = op, .valtype1 = val_type });
3535 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
3536 return .stack;
3537 },
3538 80, 128 => {
3539 var fn_name_buf: [32]u8 = undefined;
3540 const fn_name = std.fmt.bufPrint(&fn_name_buf, "__{s}{s}f2", .{
3541 @tagName(op), target_util.compilerRtFloatAbbrev(float_bits),
3542 }) catch unreachable;
35263543
3527 return WValue{ .stack = {} };
3544 const result = try func.callIntrinsic(fn_name, &.{ ty.ip_index, ty.ip_index }, Type.bool, &.{ lhs, rhs });
3545 return func.cmp(result, WValue{ .imm32 = 0 }, Type.i32, cmp_op);
3546 },
3547 else => unreachable,
3548 }
35283549}
35293550
35303551fn airCmpVector(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {