| ... | @@ -1487,28 +1487,52 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1487,28 +1487,52 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1487 | break :result result; | 1487 | break :result result; |
| 1488 | } | 1488 | } |
| 1489 | | 1489 | |
| 1490 | const lhs = try self.resolveInst(bin_op.lhs); | 1490 | const dst_reg: Register = dst_reg: { |
| 1491 | const rhs = try self.resolveInst(bin_op.rhs); | 1491 | switch (int_info.signedness) { |
| | 1492 | .signed => { |
| | 1493 | const lhs = try self.resolveInst(bin_op.lhs); |
| | 1494 | const rhs = try self.resolveInst(bin_op.rhs); |
| | 1495 | |
| | 1496 | rhs.freezeIfRegister(&self.register_manager); |
| | 1497 | defer rhs.unfreezeIfRegister(&self.register_manager); |
| | 1498 | |
| | 1499 | // TODO check if we could reuse rhs instead, and swap the values out. |
| | 1500 | const dst_reg: Register = blk: { |
| | 1501 | if (self.reuseOperand(inst, bin_op.lhs, 0, lhs)) { |
| | 1502 | if (lhs.isRegister()) break :blk lhs.register; |
| | 1503 | } |
| | 1504 | break :blk try self.copyToTmpRegister(ty, lhs); |
| | 1505 | }; |
| | 1506 | self.register_manager.freezeRegs(&.{dst_reg}); |
| | 1507 | |
| | 1508 | const rhs_mcv = blk: { |
| | 1509 | if (rhs.isRegister() or rhs.isMemory()) break :blk rhs; |
| | 1510 | break :blk MCValue{ .register = try self.copyToTmpRegister(ty, rhs) }; |
| | 1511 | }; |
| | 1512 | rhs_mcv.freezeIfRegister(&self.register_manager); |
| | 1513 | defer rhs_mcv.unfreezeIfRegister(&self.register_manager); |
| | 1514 | |
| | 1515 | try self.genIntMulComplexOpMir(Type.isize, .{ .register = dst_reg }, rhs_mcv); |
| | 1516 | |
| | 1517 | break :dst_reg dst_reg; |
| | 1518 | }, |
| | 1519 | .unsigned => { |
| | 1520 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. |
| | 1521 | try self.register_manager.getReg(.rax, null); |
| | 1522 | try self.register_manager.getReg(.rdx, null); |
| | 1523 | self.register_manager.freezeRegs(&.{ .rax, .rdx }); |
| | 1524 | defer self.register_manager.unfreezeRegs(&.{.rdx}); |
| 1492 | | 1525 | |
| 1493 | rhs.freezeIfRegister(&self.register_manager); | 1526 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1494 | defer rhs.unfreezeIfRegister(&self.register_manager); | 1527 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1495 | | 1528 | |
| 1496 | // TODO check if we could reuse rhs instead, and swap the values out. | 1529 | try self.genIntMulDivOpMir(.mul, ty, .unsigned, lhs, rhs); |
| 1497 | const dst_mcv = blk: { | | |
| 1498 | if (self.reuseOperand(inst, bin_op.lhs, 0, lhs)) { | | |
| 1499 | if (lhs.isRegister()) break :blk lhs; | | |
| 1500 | } | | |
| 1501 | break :blk MCValue{ .register = try self.copyToTmpRegister(ty, lhs) }; | | |
| 1502 | }; | | |
| 1503 | dst_mcv.freezeIfRegister(&self.register_manager); | | |
| 1504 | defer dst_mcv.unfreezeIfRegister(&self.register_manager); | | |
| 1505 | | 1530 | |
| 1506 | const rhs_mcv = blk: { | 1531 | break :dst_reg registerAlias(.rax, @intCast(u32, ty.abiSize(self.target.*))); |
| 1507 | if (rhs.isRegister() or rhs.isMemory()) break :blk rhs; | 1532 | }, |
| 1508 | break :blk MCValue{ .register = try self.copyToTmpRegister(ty, rhs) }; | 1533 | } |
| 1509 | }; | 1534 | }; |
| 1510 | rhs_mcv.freezeIfRegister(&self.register_manager); | 1535 | defer self.register_manager.unfreezeRegs(&.{dst_reg}); |
| 1511 | defer rhs_mcv.unfreezeIfRegister(&self.register_manager); | | |
| 1512 | | 1536 | |
| 1513 | const tuple_ty = self.air.typeOfIndex(inst); | 1537 | const tuple_ty = self.air.typeOfIndex(inst); |
| 1514 | const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*)); | 1538 | const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*)); |
| ... | @@ -1521,8 +1545,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1521,8 +1545,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1521 | .unsigned => ty, | 1545 | .unsigned => ty, |
| 1522 | }; | 1546 | }; |
| 1523 | | 1547 | |
| 1524 | try self.genIntMulComplexOpMir(extended_ty, dst_mcv, rhs_mcv); | | |
| 1525 | | | |
| 1526 | const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }); | 1548 | const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }); |
| 1527 | self.register_manager.freezeRegs(&temp_regs); | 1549 | self.register_manager.freezeRegs(&temp_regs); |
| 1528 | defer self.register_manager.unfreezeRegs(&temp_regs); | 1550 | defer self.register_manager.unfreezeRegs(&temp_regs); |
| ... | @@ -1542,9 +1564,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1542,9 +1564,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1542 | }); | 1564 | }); |
| 1543 | | 1565 | |
| 1544 | const scratch_reg = temp_regs[1]; | 1566 | const scratch_reg = temp_regs[1]; |
| 1545 | try self.genSetReg(extended_ty, scratch_reg, dst_mcv); | 1567 | try self.genSetReg(extended_ty, scratch_reg, .{ .register = dst_reg }); |
| 1546 | try self.truncateRegister(ty, scratch_reg); | 1568 | try self.truncateRegister(ty, scratch_reg); |
| 1547 | try self.genBinMathOpMir(.cmp, extended_ty, dst_mcv, .{ .register = scratch_reg }); | 1569 | try self.genBinMathOpMir( |
| | 1570 | .cmp, |
| | 1571 | extended_ty, |
| | 1572 | .{ .register = dst_reg }, |
| | 1573 | .{ .register = scratch_reg }, |
| | 1574 | ); |
| 1548 | | 1575 | |
| 1549 | const eq_reg = temp_regs[2]; | 1576 | const eq_reg = temp_regs[2]; |
| 1550 | _ = try self.addInst(.{ | 1577 | _ = try self.addInst(.{ |
| ... | @@ -6626,7 +6653,12 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { | ... | @@ -6626,7 +6653,12 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { |
| 6626 | .unsigned => { | 6653 | .unsigned => { |
| 6627 | const shift = @intCast(u6, max_reg_bit_width - int_info.bits); | 6654 | const shift = @intCast(u6, max_reg_bit_width - int_info.bits); |
| 6628 | const mask = (~@as(u64, 0)) >> shift; | 6655 | const mask = (~@as(u64, 0)) >> shift; |
| 6629 | try self.genBinMathOpMir(.@"and", Type.usize, .{ .register = reg }, .{ .immediate = mask }); | 6656 | if (int_info.bits <= 32) { |
| | 6657 | try self.genBinMathOpMir(.@"and", Type.usize, .{ .register = reg }, .{ .immediate = mask }); |
| | 6658 | } else { |
| | 6659 | const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask }); |
| | 6660 | try self.genBinMathOpMir(.@"and", Type.usize, .{ .register = reg }, .{ .register = tmp_reg }); |
| | 6661 | } |
| 6630 | }, | 6662 | }, |
| 6631 | } | 6663 | } |
| 6632 | } | 6664 | } |