| ... | ... | @@ -4162,22 +4162,14 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!W |
| 4162 | 4162 | 64 => WValue{ .imm64 = 0 }, |
| 4163 | 4163 | else => unreachable, |
| 4164 | 4164 | }; |
| 4165 | | const shift_amt = wasm_bits - int_info.bits; |
| 4166 | | const shift_val = switch (wasm_bits) { |
| 4167 | | 32 => WValue{ .imm32 = shift_amt }, |
| 4168 | | 64 => WValue{ .imm64 = shift_amt }, |
| 4169 | | else => unreachable, |
| 4170 | | }; |
| 4171 | 4165 | |
| 4172 | 4166 | // for signed integers, we first apply signed shifts by the difference in bits |
| 4173 | 4167 | // to get the signed value, as we store it internally as 2's complement. |
| 4174 | 4168 | const lhs = if (wasm_bits != int_info.bits and is_signed) blk: { |
| 4175 | | const shl = try self.binOp(lhs_op, shift_val, lhs_ty, .shl); |
| 4176 | | break :blk try self.binOp(shl, shift_val, lhs_ty, .shr); |
| 4169 | break :blk try self.signAbsValue(lhs_op, lhs_ty); |
| 4177 | 4170 | } else lhs_op; |
| 4178 | 4171 | const rhs = if (wasm_bits != int_info.bits and is_signed) blk: { |
| 4179 | | const shl = try self.binOp(rhs_op, shift_val, lhs_ty, .shl); |
| 4180 | | break :blk try self.binOp(shl, shift_val, lhs_ty, .shr); |
| 4172 | break :blk try self.signAbsValue(rhs_op, lhs_ty); |
| 4181 | 4173 | } else rhs_op; |
| 4182 | 4174 | |
| 4183 | 4175 | const bin_op = try self.binOp(lhs, rhs, lhs_ty, op); |
| ... | ... | @@ -4192,9 +4184,8 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!W |
| 4192 | 4184 | const lt = try self.cmp(bin_op, lhs, lhs_ty, .lt); |
| 4193 | 4185 | break :blk try self.binOp(cmp_zero, lt, Type.u32, .xor); // result of cmp_zero and lt is always 32bit |
| 4194 | 4186 | } |
| 4195 | | const shl = try self.binOp(bin_op, shift_val, lhs_ty, .shl); |
| 4196 | | const shr = try self.binOp(shl, shift_val, lhs_ty, .shr); |
| 4197 | | break :blk try self.cmp(shr, bin_op, lhs_ty, .neq); |
| 4187 | const abs = try self.signAbsValue(bin_op, lhs_ty); |
| 4188 | break :blk try self.cmp(abs, bin_op, lhs_ty, .neq); |
| 4198 | 4189 | } else if (wasm_bits == int_info.bits) |
| 4199 | 4190 | try self.cmp(bin_op, lhs, lhs_ty, cmp_op) |
| 4200 | 4191 | else |
| ... | ... | @@ -4289,17 +4280,9 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4289 | 4280 | } else shl; |
| 4290 | 4281 | |
| 4291 | 4282 | const overflow_bit = if (wasm_bits != int_info.bits and is_signed) blk: { |
| 4292 | | const shift_amt = wasm_bits - int_info.bits; |
| 4293 | | const shift_val = switch (wasm_bits) { |
| 4294 | | 32 => WValue{ .imm32 = shift_amt }, |
| 4295 | | 64 => WValue{ .imm64 = shift_amt }, |
| 4296 | | else => unreachable, |
| 4297 | | }; |
| 4298 | | |
| 4299 | | const secondary_shl = try self.binOp(shl, shift_val, lhs_ty, .shl); |
| 4300 | | const initial_shr = try self.binOp(secondary_shl, shift_val, lhs_ty, .shr); |
| 4301 | | const shr = try self.wrapBinOp(initial_shr, rhs, lhs_ty, .shr); |
| 4302 | | break :blk try self.cmp(lhs, shr, lhs_ty, .neq); |
| 4283 | const abs = try self.signAbsValue(shl, lhs_ty); |
| 4284 | const wrapped = try self.wrapBinOp(abs, rhs, lhs_ty, .shr); |
| 4285 | break :blk try self.cmp(lhs, wrapped, lhs_ty, .neq); |
| 4303 | 4286 | } else blk: { |
| 4304 | 4287 | const shr = try self.binOp(result, rhs, lhs_ty, .shr); |
| 4305 | 4288 | break :blk try self.cmp(lhs, shr, lhs_ty, .neq); |
| ... | ... | @@ -4367,21 +4350,11 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 4367 | 4350 | break :blk down_cast; |
| 4368 | 4351 | } |
| 4369 | 4352 | } else if (int_info.signedness == .signed) blk: { |
| 4370 | | const shift_imm = if (wasm_bits == 32) |
| 4371 | | WValue{ .imm32 = wasm_bits - int_info.bits } |
| 4372 | | else |
| 4373 | | WValue{ .imm64 = wasm_bits - int_info.bits }; |
| 4374 | | |
| 4375 | | const lhs_shl = try self.binOp(lhs, shift_imm, lhs_ty, .shl); |
| 4376 | | const lhs_shr = try self.binOp(lhs_shl, shift_imm, lhs_ty, .shr); |
| 4377 | | const rhs_shl = try self.binOp(rhs, shift_imm, lhs_ty, .shl); |
| 4378 | | const rhs_shr = try self.binOp(rhs_shl, shift_imm, lhs_ty, .shr); |
| 4379 | | |
| 4380 | | const bin_op = try self.binOp(lhs_shr, rhs_shr, lhs_ty, .mul); |
| 4381 | | const shl = try self.binOp(bin_op, shift_imm, lhs_ty, .shl); |
| 4382 | | const shr = try self.binOp(shl, shift_imm, lhs_ty, .shr); |
| 4383 | | |
| 4384 | | const cmp_op = try self.cmp(shr, bin_op, lhs_ty, .neq); |
| 4353 | const lhs_abs = try self.signAbsValue(lhs, lhs_ty); |
| 4354 | const rhs_abs = try self.signAbsValue(rhs, lhs_ty); |
| 4355 | const bin_op = try self.binOp(lhs_abs, rhs_abs, lhs_ty, .mul); |
| 4356 | const mul_abs = try self.signAbsValue(bin_op, lhs_ty); |
| 4357 | const cmp_op = try self.cmp(mul_abs, bin_op, lhs_ty, .neq); |
| 4385 | 4358 | try self.emitWValue(cmp_op); |
| 4386 | 4359 | try self.addLabel(.local_set, overflow_bit.local); |
| 4387 | 4360 | break :blk try self.wrapOperand(bin_op, lhs_ty); |