authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-05 19:29:24+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-05 22:51:12+02:00
log0728847ce74aace8fe8e2a8f61da09002cd4ad7e
tree789b9d6f3025e9d4e4ed4cf85c14ce16e6f7450b
parent0fc1e8b54f2022081a642c13eb74dfdda5aad867

x64: handle unsigned mul_with_overflow for non-pow-2 ints


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

src/arch/x86_64/CodeGen.zig+55-23
...@@ -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 }
14891489
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});
14921525
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);
14951528
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);
15051530
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);
15121536
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 };
15231547
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 });
15431565
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 );
15481575
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}