authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-07-25 07:10:56+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-08-11 11:08:00+02:00
log305b113a53cd5905d837ea620e2bcae8912c5938
tree51c4733dee0daaae76060204888f1a21fe0f8aa6
parentcc6f2b67c68ece7577e27e23846670d6566ad5f2
signaturelock-open Commit is signed but in an unrecognized format.

wasm: keep result of `cmp` on the stack

By keeping the result on the stack, we prevent codegen from generating unneccesary locals when we have subsequent instructions that do not have to be re-used.

1 files changed, 50 insertions(+), 75 deletions(-)

src/arch/wasm/CodeGen.zig+50-75
......@@ -2659,10 +2659,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner
26592659 const lhs = try self.resolveInst(bin_op.lhs);
26602660 const rhs = try self.resolveInst(bin_op.rhs);
26612661 const operand_ty = self.air.typeOf(bin_op.lhs);
2662 return self.cmp(lhs, rhs, operand_ty, op);
2662 return (try self.cmp(lhs, rhs, operand_ty, op)).toLocal(self, Type.u32); // comparison result is always 32 bits
26632663}
26642664
2665/// Compares two operands.
2666/// Asserts rhs is not a stack value when the lhs isn't a stack value either
2667/// NOTE: This leaves the result on top of the stack, rather than a new local.
26652668fn cmp(self: *Self, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOperator) InnerError!WValue {
2669 assert(!(lhs != .stack and rhs == .stack));
26662670 if (ty.zigTypeTag() == .Optional and !ty.optionalReprIsPayload()) {
26672671 var buf: Type.Payload.ElemType = undefined;
26682672 const payload_ty = ty.optionalChild(&buf);
......@@ -2704,9 +2708,7 @@ fn cmp(self: *Self, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOper
27042708 });
27052709 try self.addTag(Mir.Inst.Tag.fromOpcode(opcode));
27062710
2707 const cmp_tmp = try self.allocLocal(Type.initTag(.i32)); // bool is always i32
2708 try self.addLabel(.local_set, cmp_tmp.local);
2709 return cmp_tmp;
2711 return WValue{ .stack = {} };
27102712}
27112713
27122714fn cmpFloat16(self: *Self, lhs: WValue, rhs: WValue, op: std.math.CompareOperator) InnerError!WValue {
......@@ -2729,9 +2731,7 @@ fn cmpFloat16(self: *Self, lhs: WValue, rhs: WValue, op: std.math.CompareOperato
27292731 try self.emitWValue(ext_rhs);
27302732 try self.addTag(Mir.Inst.Tag.fromOpcode(opcode));
27312733
2732 const result = try self.allocLocal(Type.initTag(.i32)); // bool is always i32
2733 try self.addLabel(.local_set, result.local);
2734 return result;
2734 return WValue{ .stack = {} };
27352735}
27362736
27372737fn airCmpVector(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
......@@ -3982,13 +3982,16 @@ fn cmpOptionals(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std
39823982 try self.addImm32(0);
39833983 try self.addTag(if (op == .eq) .i32_ne else .i32_eq);
39843984 try self.addLabel(.local_set, result.local);
3985 return result;
3985 try self.emitWValue(result);
3986 return WValue{ .stack = {} };
39863987}
39873988
39883989/// Compares big integers by checking both its high bits and low bits.
3990/// NOTE: Leaves the result of the comparison on top of the stack.
39893991/// TODO: Lower this to compiler_rt call when bitsize > 128
39903992fn cmpBigInt(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {
39913993 assert(operand_ty.abiSize(self.target) >= 16);
3994 assert(!(lhs != .stack and rhs == .stack));
39923995 if (operand_ty.intInfo(self.target).bits > 128) {
39933996 return self.fail("TODO: Support cmpBigInt for integer bitsize: '{d}'", .{operand_ty.intInfo(self.target).bits});
39943997 }
......@@ -4012,20 +4015,15 @@ fn cmpBigInt(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.ma
40124015 },
40134016 else => {
40144017 const ty = if (operand_ty.isSignedInt()) Type.i64 else Type.u64;
4015 const high_bit_eql = try self.cmp(lhs_high_bit, rhs_high_bit, ty, .eq);
4016 const high_bit_cmp = try self.cmp(lhs_high_bit, rhs_high_bit, ty, op);
4017 const low_bit_cmp = try self.cmp(lhs_low_bit, rhs_low_bit, ty, op);
4018
4019 try self.emitWValue(low_bit_cmp);
4020 try self.emitWValue(high_bit_cmp);
4021 try self.emitWValue(high_bit_eql);
4018 // leave those value on top of the stack for '.select'
4019 _ = try self.cmp(lhs_low_bit, rhs_low_bit, ty, op);
4020 _ = try self.cmp(lhs_high_bit, rhs_high_bit, ty, op);
4021 _ = try self.cmp(lhs_high_bit, rhs_high_bit, ty, .eq);
40224022 try self.addTag(.select);
40234023 },
40244024 }
40254025
4026 const result = try self.allocLocal(Type.initTag(.i32));
4027 try self.addLabel(.local_set, result.local);
4028 return result;
4026 return WValue{ .stack = {} };
40294027}
40304028
40314029fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
......@@ -4350,7 +4348,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!W
43504348 if (wasm_bits == int_info.bits) {
43514349 const cmp_zero = try self.cmp(rhs, zero, lhs_ty, cmp_op);
43524350 const lt = try self.cmp(bin_op, lhs, lhs_ty, .lt);
4353 break :blk try (try self.binOp(cmp_zero, lt, Type.u32, .xor)).toLocal(self, Type.u32); // result of cmp_zero and lt is always 32bit
4351 break :blk try self.binOp(cmp_zero, lt, Type.u32, .xor);
43544352 }
43554353 const abs = try self.signAbsValue(bin_op, lhs_ty);
43564354 break :blk try self.cmp(abs, bin_op, lhs_ty, .neq);
......@@ -4358,11 +4356,12 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!W
43584356 try self.cmp(bin_op, lhs, lhs_ty, cmp_op)
43594357 else
43604358 try self.cmp(bin_op, result, lhs_ty, .neq);
4359 const overflow_local = try overflow_bit.toLocal(self, Type.u32);
43614360
43624361 const result_ptr = try self.allocStack(self.air.typeOfIndex(inst));
43634362 try self.store(result_ptr, result, lhs_ty, 0);
43644363 const offset = @intCast(u32, lhs_ty.abiSize(self.target));
4365 try self.store(result_ptr, overflow_bit, Type.initTag(.u1), offset);
4364 try self.store(result_ptr, overflow_local, Type.initTag(.u1), offset);
43664365
43674366 return result_ptr;
43684367}
......@@ -4384,9 +4383,9 @@ fn airAddSubWithOverflowBigInt(self: *Self, lhs: WValue, rhs: WValue, ty: Type,
43844383 const high_op_res = try (try self.binOp(lhs_high_bit, rhs_high_bit, Type.u64, op)).toLocal(self, Type.u64);
43854384
43864385 const lt = if (op == .add) blk: {
4387 break :blk try self.cmp(high_op_res, lhs_high_bit, Type.u64, .lt);
4386 break :blk try (try self.cmp(high_op_res, lhs_high_bit, Type.u64, .lt)).toLocal(self, Type.u32);
43884387 } else if (op == .sub) blk: {
4389 break :blk try self.cmp(lhs_high_bit, rhs_high_bit, Type.u64, .lt);
4388 break :blk try (try self.cmp(lhs_high_bit, rhs_high_bit, Type.u64, .lt)).toLocal(self, Type.u32);
43904389 } else unreachable;
43914390 const tmp = try self.intcast(lt, Type.u32, Type.u64);
43924391 const tmp_op = try (try self.binOp(low_op_res, tmp, Type.u64, op)).toLocal(self, Type.u64);
......@@ -4400,27 +4399,23 @@ fn airAddSubWithOverflowBigInt(self: *Self, lhs: WValue, rhs: WValue, ty: Type,
44004399 const wrap = try self.binOp(to_wrap, xor_op, Type.u64, .@"and");
44014400 break :blk try self.cmp(wrap, .{ .imm64 = 0 }, Type.i64, .lt); // i64 because signed
44024401 } else blk: {
4403 const eq = try self.cmp(tmp_op, lhs_low_bit, Type.u64, .eq);
4404 const op_eq = try self.cmp(tmp_op, lhs_low_bit, Type.u64, if (op == .add) .lt else .gt);
4405
44064402 const first_arg = if (op == .sub) arg: {
44074403 break :arg try self.cmp(high_op_res, lhs_high_bit, Type.u64, .gt);
44084404 } else lt;
44094405
44104406 try self.emitWValue(first_arg);
4411 try self.emitWValue(op_eq);
4412 try self.emitWValue(eq);
4407 _ = try self.cmp(tmp_op, lhs_low_bit, Type.u64, if (op == .add) .lt else .gt);
4408 _ = try self.cmp(tmp_op, lhs_low_bit, Type.u64, .eq);
44134409 try self.addTag(.select);
44144410
4415 const overflow_bit = try self.allocLocal(Type.initTag(.u1));
4416 try self.addLabel(.local_set, overflow_bit.local);
4417 break :blk overflow_bit;
4411 break :blk WValue{ .stack = {} };
44184412 };
4413 const overflow_local = try overflow_bit.toLocal(self, Type.initTag(.u1));
44194414
44204415 const result_ptr = try self.allocStack(result_ty);
44214416 try self.store(result_ptr, high_op_res, Type.u64, 0);
44224417 try self.store(result_ptr, tmp_op, Type.u64, 8);
4423 try self.store(result_ptr, overflow_bit, Type.initTag(.u1), 16);
4418 try self.store(result_ptr, overflow_local, Type.initTag(.u1), 16);
44244419
44254420 return result_ptr;
44264421}
......@@ -4455,11 +4450,12 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
44554450 const shr = try (try self.binOp(result, rhs, lhs_ty, .shr)).toLocal(self, lhs_ty);
44564451 break :blk try self.cmp(lhs, shr, lhs_ty, .neq);
44574452 };
4453 const overflow_local = try overflow_bit.toLocal(self, Type.initTag(.u1));
44584454
44594455 const result_ptr = try self.allocStack(self.air.typeOfIndex(inst));
44604456 try self.store(result_ptr, result, lhs_ty, 0);
44614457 const offset = @intCast(u32, lhs_ty.abiSize(self.target));
4462 try self.store(result_ptr, overflow_bit, Type.initTag(.u1), offset);
4458 try self.store(result_ptr, overflow_local, Type.initTag(.u1), offset);
44634459
44644460 return result_ptr;
44654461}
......@@ -4502,8 +4498,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
45024498 if (int_info.signedness == .unsigned) {
45034499 const shr = try self.binOp(bin_op, .{ .imm64 = int_info.bits }, new_ty, .shr);
45044500 const wrap = try self.intcast(shr, new_ty, lhs_ty);
4505 const cmp_res = try self.cmp(wrap, zero, lhs_ty, .neq);
4506 try self.emitWValue(cmp_res);
4501 _ = try self.cmp(wrap, zero, lhs_ty, .neq);
45074502 try self.addLabel(.local_set, overflow_bit.local);
45084503 break :blk try self.intcast(bin_op, new_ty, lhs_ty);
45094504 } else {
......@@ -4512,8 +4507,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
45124507
45134508 const shr_res = try self.binOp(bin_op, .{ .imm64 = int_info.bits }, new_ty, .shr);
45144509 const down_shr_res = try self.intcast(shr_res, new_ty, lhs_ty);
4515 const cmp_res = try self.cmp(down_shr_res, shr, lhs_ty, .neq);
4516 try self.emitWValue(cmp_res);
4510 _ = try self.cmp(down_shr_res, shr, lhs_ty, .neq);
45174511 try self.addLabel(.local_set, overflow_bit.local);
45184512 break :blk down_cast;
45194513 }
......@@ -4522,8 +4516,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
45224516 const rhs_abs = try self.signAbsValue(rhs, lhs_ty);
45234517 const bin_op = try (try self.binOp(lhs_abs, rhs_abs, lhs_ty, .mul)).toLocal(self, lhs_ty);
45244518 const mul_abs = try self.signAbsValue(bin_op, lhs_ty);
4525 const cmp_op = try self.cmp(mul_abs, bin_op, lhs_ty, .neq);
4526 try self.emitWValue(cmp_op);
4519 _ = try self.cmp(mul_abs, bin_op, lhs_ty, .neq);
45274520 try self.addLabel(.local_set, overflow_bit.local);
45284521 break :blk try self.wrapOperand(bin_op, lhs_ty);
45294522 } else blk: {
......@@ -4533,8 +4526,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
45334526 else
45344527 WValue{ .imm64 = int_info.bits };
45354528 const shr = try self.binOp(bin_op, shift_imm, lhs_ty, .shr);
4536 const cmp_op = try self.cmp(shr, zero, lhs_ty, .neq);
4537 try self.emitWValue(cmp_op);
4529 _ = try self.cmp(shr, zero, lhs_ty, .neq);
45384530 try self.addLabel(.local_set, overflow_bit.local);
45394531 break :blk try self.wrapOperand(bin_op, lhs_ty);
45404532 };
......@@ -4562,12 +4554,10 @@ fn airMaxMin(self: *Self, inst: Air.Inst.Index, op: enum { max, min }) InnerErro
45624554 const lhs = try self.resolveInst(bin_op.lhs);
45634555 const rhs = try self.resolveInst(bin_op.rhs);
45644556
4565 const cmp_result = try self.cmp(lhs, rhs, ty, if (op == .max) .gt else .lt);
4566
45674557 // operands to select from
45684558 try self.lowerToStack(lhs);
45694559 try self.lowerToStack(rhs);
4570 try self.emitWValue(cmp_result);
4560 _ = try self.cmp(lhs, rhs, ty, if (op == .max) .gt else .lt);
45714561
45724562 // based on the result from comparison, return operand 0 or 1.
45734563 try self.addTag(.select);
......@@ -4638,7 +4628,6 @@ fn airClz(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
46384628 128 => {
46394629 const msb = try self.load(operand, Type.u64, 0);
46404630 const lsb = try self.load(operand, Type.u64, 8);
4641 const neq = try self.cmp(lsb, .{ .imm64 = 0 }, Type.u64, .neq);
46424631
46434632 try self.emitWValue(lsb);
46444633 try self.addTag(.i64_clz);
......@@ -4646,7 +4635,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
46464635 try self.addTag(.i64_clz);
46474636 try self.emitWValue(.{ .imm64 = 64 });
46484637 try self.addTag(.i64_add);
4649 try self.emitWValue(neq);
4638 _ = try self.cmp(lsb, .{ .imm64 = 0 }, Type.u64, .neq);
46504639 try self.addTag(.select);
46514640 try self.addTag(.i32_wrap_i64);
46524641 },
......@@ -4700,7 +4689,6 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
47004689 128 => {
47014690 const msb = try self.load(operand, Type.u64, 0);
47024691 const lsb = try self.load(operand, Type.u64, 8);
4703 const neq = try self.cmp(msb, .{ .imm64 = 0 }, Type.u64, .neq);
47044692
47054693 try self.emitWValue(msb);
47064694 try self.addTag(.i64_ctz);
......@@ -4716,7 +4704,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
47164704 } else {
47174705 try self.addTag(.i64_add);
47184706 }
4719 try self.emitWValue(neq);
4707 _ = try self.cmp(msb, .{ .imm64 = 0 }, Type.u64, .neq);
47204708 try self.addTag(.select);
47214709 try self.addTag(.i32_wrap_i64);
47224710 },
......@@ -4952,15 +4940,13 @@ fn airDivFloor(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
49524940 64 => WValue{ .imm64 = 0 },
49534941 else => unreachable,
49544942 };
4955 const lhs_less_than_zero = try self.cmp(lhs_res, zero, ty, .lt);
4956 const rhs_less_than_zero = try self.cmp(rhs_res, zero, ty, .lt);
49574943
49584944 const div_result = try self.allocLocal(ty);
49594945 // leave on stack
49604946 _ = try self.binOp(lhs_res, rhs_res, ty, .div);
49614947 try self.addLabel(.local_tee, div_result.local);
4962 try self.emitWValue(lhs_less_than_zero);
4963 try self.emitWValue(rhs_less_than_zero);
4948 _ = try self.cmp(lhs_res, zero, ty, .lt);
4949 _ = try self.cmp(rhs_res, zero, ty, .lt);
49644950 switch (wasm_bits) {
49654951 32 => {
49664952 try self.addTag(.i32_xor);
......@@ -5140,19 +5126,17 @@ fn airSatBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue {
51405126 else => unreachable,
51415127 };
51425128
5143 const cmp_result = try self.cmp(bin_result, imm_val, ty, .lt);
51445129 try self.emitWValue(bin_result);
51455130 try self.emitWValue(imm_val);
5146 try self.emitWValue(cmp_result);
5131 _ = try self.cmp(bin_result, imm_val, ty, .lt);
51475132 } else {
5148 const cmp_result = try self.cmp(bin_result, lhs, ty, if (op == .add) .lt else .gt);
51495133 switch (wasm_bits) {
51505134 32 => try self.addImm32(if (op == .add) @as(i32, -1) else 0),
51515135 64 => try self.addImm64(if (op == .add) @bitCast(u64, @as(i64, -1)) else 0),
51525136 else => unreachable,
51535137 }
51545138 try self.emitWValue(bin_result);
5155 try self.emitWValue(cmp_result);
5139 _ = try self.cmp(bin_result, lhs, ty, if (op == .add) .lt else .gt);
51565140 }
51575141
51585142 try self.addTag(.select);
......@@ -5184,17 +5168,15 @@ fn signedSat(self: *Self, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op
51845168
51855169 const bin_result = try (try self.binOp(lhs, rhs, ty, op)).toLocal(self, ty);
51865170 if (!is_wasm_bits) {
5187 const cmp_result_lt = try self.cmp(bin_result, max_wvalue, ty, .lt);
51885171 try self.emitWValue(bin_result);
51895172 try self.emitWValue(max_wvalue);
5190 try self.emitWValue(cmp_result_lt);
5173 _ = try self.cmp(bin_result, max_wvalue, ty, .lt);
51915174 try self.addTag(.select);
51925175 try self.addLabel(.local_set, bin_result.local); // re-use local
51935176
5194 const cmp_result_gt = try self.cmp(bin_result, min_wvalue, ty, .gt);
51955177 try self.emitWValue(bin_result);
51965178 try self.emitWValue(min_wvalue);
5197 try self.emitWValue(cmp_result_gt);
5179 _ = try self.cmp(bin_result, min_wvalue, ty, .gt);
51985180 try self.addTag(.select);
51995181 try self.addLabel(.local_set, bin_result.local); // re-use local
52005182 return self.wrapOperand(bin_result, ty);
......@@ -5204,15 +5186,14 @@ fn signedSat(self: *Self, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op
52045186 64 => WValue{ .imm64 = 0 },
52055187 else => unreachable,
52065188 };
5207 const cmp_bin_result = try self.cmp(bin_result, lhs, ty, .lt);
5208 const cmp_zero_result = try self.cmp(rhs, zero, ty, if (op == .add) .lt else .gt);
5209 const cmp_bin_zero_result = try self.cmp(bin_result, zero, ty, .lt);
52105189 try self.emitWValue(max_wvalue);
52115190 try self.emitWValue(min_wvalue);
5212 try self.emitWValue(cmp_bin_zero_result);
5191 _ = try self.cmp(bin_result, zero, ty, .lt);
52135192 try self.addTag(.select);
52145193 try self.emitWValue(bin_result);
52155194 // leave on stack
5195 const cmp_zero_result = try self.cmp(rhs, zero, ty, if (op == .add) .lt else .gt);
5196 const cmp_bin_result = try self.cmp(bin_result, lhs, ty, .lt);
52165197 _ = try self.binOp(cmp_zero_result, cmp_bin_result, Type.u32, .xor); // comparisons always return i32, so provide u32 as type to xor.
52175198 try self.addTag(.select);
52185199 try self.addLabel(.local_set, bin_result.local); // re-use local
......@@ -5239,7 +5220,6 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
52395220 if (wasm_bits == int_info.bits) {
52405221 const shl = try (try self.binOp(lhs, rhs, ty, .shl)).toLocal(self, ty);
52415222 const shr = try (try self.binOp(shl, rhs, ty, .shr)).toLocal(self, ty);
5242 const cmp_result = try self.cmp(lhs, shr, ty, .neq);
52435223
52445224 switch (wasm_bits) {
52455225 32 => blk: {
......@@ -5247,10 +5227,9 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
52475227 try self.addImm32(-1);
52485228 break :blk;
52495229 }
5250 const less_than_zero = try self.cmp(lhs, .{ .imm32 = 0 }, ty, .lt);
52515230 try self.addImm32(std.math.minInt(i32));
52525231 try self.addImm32(std.math.maxInt(i32));
5253 try self.emitWValue(less_than_zero);
5232 _ = try self.cmp(lhs, .{ .imm32 = 0 }, ty, .lt);
52545233 try self.addTag(.select);
52555234 },
52565235 64 => blk: {
......@@ -5258,16 +5237,15 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
52585237 try self.addImm64(@bitCast(u64, @as(i64, -1)));
52595238 break :blk;
52605239 }
5261 const less_than_zero = try self.cmp(lhs, .{ .imm64 = 0 }, ty, .lt);
52625240 try self.addImm64(@bitCast(u64, @as(i64, std.math.minInt(i64))));
52635241 try self.addImm64(@bitCast(u64, @as(i64, std.math.maxInt(i64))));
5264 try self.emitWValue(less_than_zero);
5242 _ = try self.cmp(lhs, .{ .imm64 = 0 }, ty, .lt);
52655243 try self.addTag(.select);
52665244 },
52675245 else => unreachable,
52685246 }
52695247 try self.emitWValue(shl);
5270 try self.emitWValue(cmp_result);
5248 _ = try self.cmp(lhs, shr, ty, .neq);
52715249 try self.addTag(.select);
52725250 try self.addLabel(.local_set, result.local);
52735251 return result;
......@@ -5282,7 +5260,6 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
52825260 const shl_res = try (try self.binOp(lhs, shift_value, ty, .shl)).toLocal(self, ty);
52835261 const shl = try (try self.binOp(shl_res, rhs, ty, .shl)).toLocal(self, ty);
52845262 const shr = try (try self.binOp(shl, rhs, ty, .shr)).toLocal(self, ty);
5285 const cmp_result = try self.cmp(shl_res, shr, ty, .neq);
52865263
52875264 switch (wasm_bits) {
52885265 32 => blk: {
......@@ -5291,10 +5268,9 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
52915268 break :blk;
52925269 }
52935270
5294 const less_than_zero = try self.cmp(shl_res, .{ .imm32 = 0 }, ty, .lt);
52955271 try self.addImm32(std.math.minInt(i32));
52965272 try self.addImm32(std.math.maxInt(i32));
5297 try self.emitWValue(less_than_zero);
5273 _ = try self.cmp(shl_res, .{ .imm32 = 0 }, ty, .lt);
52985274 try self.addTag(.select);
52995275 },
53005276 64 => blk: {
......@@ -5303,16 +5279,15 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
53035279 break :blk;
53045280 }
53055281
5306 const less_than_zero = try self.cmp(shl_res, .{ .imm64 = 0 }, ty, .lt);
53075282 try self.addImm64(@bitCast(u64, @as(i64, std.math.minInt(i64))));
53085283 try self.addImm64(@bitCast(u64, @as(i64, std.math.maxInt(i64))));
5309 try self.emitWValue(less_than_zero);
5284 _ = try self.cmp(shl_res, .{ .imm64 = 0 }, ty, .lt);
53105285 try self.addTag(.select);
53115286 },
53125287 else => unreachable,
53135288 }
53145289 try self.emitWValue(shl);
5315 try self.emitWValue(cmp_result);
5290 _ = try self.cmp(shl_res, shr, ty, .neq);
53165291 try self.addTag(.select);
53175292 try self.addLabel(.local_set, result.local);
53185293 const shift_result = try (try self.binOp(result, shift_value, ty, .shr)).toLocal(self, ty);