authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-29 10:11:24+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-30 00:37:42+02:00
logf9773ab622d84527ddfdb08d07443ec05cf28737
tree75747d45594e877f6ab1821ac739e6693bb76e8a
parent12e1304805cbe132d17b31bac2e8123869007e4d

x64: clean up abstraction for generating integer division


3 files changed, 33 insertions(+), 29 deletions(-)

src/arch/x86_64/CodeGen.zig+27-27
......@@ -1501,11 +1501,12 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
15011501 return self.fail("TODO implement airShlWithOverflow for {}", .{self.target.cpu.arch});
15021502}
15031503
1504/// Generates signed or unsigned integer division.
1504/// Generates signed or unsigned integer multiplication/division.
15051505/// Requires use of .rax and .rdx registers. Spills them if necessary.
15061506/// Quotient is saved in .rax and remainder in .rdx.
1507fn genIntDivOpMir(
1507fn genIntMulDivOpMir(
15081508 self: *Self,
1509 tag: Mir.Inst.Tag,
15091510 ty: Type,
15101511 signedness: std.builtin.Signedness,
15111512 lhs: MCValue,
......@@ -1513,7 +1514,7 @@ fn genIntDivOpMir(
15131514) !void {
15141515 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
15151516 if (abi_size > 8) {
1516 return self.fail("TODO implement genIntDivOpMir for ABI size larger than 8", .{});
1517 return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{});
15171518 }
15181519
15191520 try self.register_manager.getReg(.rax, null);
......@@ -1521,17 +1522,7 @@ fn genIntDivOpMir(
15211522 self.register_manager.freezeRegs(&.{ .rax, .rdx });
15221523 defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });
15231524
1524 const dividend = switch (lhs) {
1525 .register => lhs,
1526 else => blk: {
1527 const reg = try self.copyToTmpRegister(ty, lhs);
1528 break :blk MCValue{ .register = reg };
1529 },
1530 };
1531 try self.genSetReg(ty, .rax, dividend);
1532
1533 self.register_manager.freezeRegs(&.{dividend.register});
1534 defer self.register_manager.unfreezeRegs(&.{dividend.register});
1525 try self.genSetReg(ty, .rax, lhs);
15351526
15361527 switch (signedness) {
15371528 .signed => {
......@@ -1555,22 +1546,19 @@ fn genIntDivOpMir(
15551546 },
15561547 }
15571548
1558 const divisor = switch (rhs) {
1549 const factor = switch (rhs) {
15591550 .register => rhs,
1551 .stack_offset => rhs,
15601552 else => blk: {
15611553 const reg = try self.copyToTmpRegister(ty, rhs);
15621554 break :blk MCValue{ .register = reg };
15631555 },
15641556 };
1565 const op_tag: Mir.Inst.Tag = switch (signedness) {
1566 .signed => .idiv,
1567 .unsigned => .div,
1568 };
15691557
1570 switch (divisor) {
1558 switch (factor) {
15711559 .register => |reg| {
15721560 _ = try self.addInst(.{
1573 .tag = op_tag,
1561 .tag = tag,
15741562 .ops = (Mir.Ops{
15751563 .reg1 = reg,
15761564 }).encode(),
......@@ -1579,7 +1567,7 @@ fn genIntDivOpMir(
15791567 },
15801568 .stack_offset => |off| {
15811569 _ = try self.addInst(.{
1582 .tag = op_tag,
1570 .tag = tag,
15831571 .ops = (Mir.Ops{
15841572 .reg2 = .rbp,
15851573 .flags = switch (abi_size) {
......@@ -1612,7 +1600,10 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
16121600 self.register_manager.freezeRegs(&.{divisor});
16131601 defer self.register_manager.unfreezeRegs(&.{ dividend, divisor });
16141602
1615 try self.genIntDivOpMir(Type.isize, signedness, .{ .register = dividend }, .{ .register = divisor });
1603 try self.genIntMulDivOpMir(switch (signedness) {
1604 .signed => .idiv,
1605 .unsigned => .div,
1606 }, Type.isize, signedness, .{ .register = dividend }, .{ .register = divisor });
16161607
16171608 _ = try self.addInst(.{
16181609 .tag = .xor,
......@@ -1673,13 +1664,16 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
16731664
16741665 const signedness = ty.intInfo(self.target.*).signedness;
16751666 if (signedness == .unsigned) {
1676 try self.genIntDivOpMir(ty, signedness, lhs, rhs);
1667 try self.genIntMulDivOpMir(.div, ty, signedness, lhs, rhs);
16771668 break :result MCValue{ .register = .rax };
16781669 }
16791670
16801671 switch (tag) {
16811672 .div_exact, .div_trunc => {
1682 try self.genIntDivOpMir(ty, signedness, lhs, rhs);
1673 try self.genIntMulDivOpMir(switch (signedness) {
1674 .signed => .idiv,
1675 .unsigned => .div,
1676 }, ty, signedness, lhs, rhs);
16831677 break :result MCValue{ .register = .rax };
16841678 },
16851679 .div_floor => {
......@@ -1704,7 +1698,10 @@ fn airRem(self: *Self, inst: Air.Inst.Index) !void {
17041698 const lhs = try self.resolveInst(bin_op.lhs);
17051699 const rhs = try self.resolveInst(bin_op.rhs);
17061700 const signedness = ty.intInfo(self.target.*).signedness;
1707 try self.genIntDivOpMir(ty, signedness, lhs, rhs);
1701 try self.genIntMulDivOpMir(switch (signedness) {
1702 .signed => .idiv,
1703 .unsigned => .div,
1704 }, ty, signedness, lhs, rhs);
17081705 break :result MCValue{ .register = .rdx };
17091706 };
17101707 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
......@@ -1725,7 +1722,10 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
17251722 const signedness = ty.intInfo(self.target.*).signedness;
17261723 switch (signedness) {
17271724 .unsigned => {
1728 try self.genIntDivOpMir(ty, signedness, lhs, rhs);
1725 try self.genIntMulDivOpMir(switch (signedness) {
1726 .signed => .idiv,
1727 .unsigned => .div,
1728 }, ty, signedness, lhs, rhs);
17291729 break :result MCValue{ .register = .rdx };
17301730 },
17311731 .signed => {
src/arch/x86_64/Emit.zig+5-2
......@@ -145,6 +145,7 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
145145 .sar => try emit.mirShift(.sar, inst),
146146
147147 .imul => try emit.mirMulDiv(.imul, inst),
148 .mul => try emit.mirMulDiv(.mul, inst),
148149 .idiv => try emit.mirMulDiv(.idiv, inst),
149150 .div => try emit.mirMulDiv(.div, inst),
150151 .imul_complex => try emit.mirIMulComplex(inst),
......@@ -1164,6 +1165,7 @@ const Tag = enum {
11641165 brk,
11651166 nop,
11661167 imul,
1168 mul,
11671169 idiv,
11681170 div,
11691171 syscall,
......@@ -1411,7 +1413,7 @@ inline fn getOpCode(tag: Tag, enc: Encoding, is_one_byte: bool) ?OpCode {
14111413 .setnl, .setge => OpCode.twoByte(0x0f, 0x9d),
14121414 .setle, .setng => OpCode.twoByte(0x0f, 0x9e),
14131415 .setnle, .setg => OpCode.twoByte(0x0f, 0x9f),
1414 .idiv, .div, .imul => OpCode.oneByte(if (is_one_byte) 0xf6 else 0xf7),
1416 .idiv, .div, .imul, .mul => OpCode.oneByte(if (is_one_byte) 0xf6 else 0xf7),
14151417 .fisttp16 => OpCode.oneByte(0xdf),
14161418 .fisttp32 => OpCode.oneByte(0xdb),
14171419 .fisttp64 => OpCode.oneByte(0xdd),
......@@ -1554,9 +1556,10 @@ inline fn getModRmExt(tag: Tag) ?u3 {
15541556 => 0x4,
15551557 .shr => 0x5,
15561558 .sar => 0x7,
1559 .mul => 0x4,
15571560 .imul => 0x5,
1558 .idiv => 0x7,
15591561 .div => 0x6,
1562 .idiv => 0x7,
15601563 .fisttp16 => 0x1,
15611564 .fisttp32 => 0x1,
15621565 .fisttp64 => 0x1,
src/arch/x86_64/Mir.zig+1
......@@ -227,6 +227,7 @@ pub const Inst = struct {
227227 /// 0b11 qword ptr [reg2 + imm32]
228228 imul,
229229 idiv,
230 mul,
230231 div,
231232
232233 /// ops flags: form: