authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-10 01:13:13+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-10 01:15:14+02:00
log252c5a2339820d15bc7a063cdd68cc65b49ed413
tree662b34aeaaa8fd8f5f4391634d3551f7936e4a87
parentc3b7a5cc26d11a0349ff1d7812b00687cfa41c2e

x64: migrate mod and rem into genBinOp


1 files changed, 60 insertions(+), 82 deletions(-)

src/arch/x86_64/CodeGen.zig+60-82
...@@ -595,8 +595,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -595,8 +595,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
595 .mul => try self.airBinOp(inst),595 .mul => try self.airBinOp(inst),
596 .mulwrap => try self.airBinOp(inst),596 .mulwrap => try self.airBinOp(inst),
597 .mul_sat => try self.airMulSat(inst),597 .mul_sat => try self.airMulSat(inst),
598 .rem => try self.airRem(inst),598 .rem => try self.airBinOp(inst),
599 .mod => try self.airMod(inst),599 .mod => try self.airBinOp(inst),
600 .shl, .shl_exact => try self.airShl(inst),600 .shl, .shl_exact => try self.airShl(inst),
601 .shl_sat => try self.airShlSat(inst),601 .shl_sat => try self.airShlSat(inst),
602 .min => try self.airMin(inst),602 .min => try self.airMin(inst),
...@@ -1539,6 +1539,7 @@ fn genIntMulDivOpMir(...@@ -1539,6 +1539,7 @@ fn genIntMulDivOpMir(
1539 }1539 }
1540}1540}
15411541
1542/// Always returns a register.
1542/// Clobbers .rax and .rdx registers.1543/// Clobbers .rax and .rdx registers.
1543fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue {1544fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue {
1544 const signedness = ty.intInfo(self.target.*).signedness;1545 const signedness = ty.intInfo(self.target.*).signedness;
...@@ -1687,86 +1688,6 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {...@@ -1687,86 +1688,6 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
1687 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1688 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1688}1689}
16891690
1690fn airRem(self: *Self, inst: Air.Inst.Index) !void {
1691 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1692
1693 if (self.liveness.isUnused(inst)) {
1694 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1695 }
1696 const ty = self.air.typeOfIndex(inst);
1697 if (ty.zigTypeTag() != .Int) {
1698 return self.fail("TODO implement .rem for operands of dst type {}", .{ty.zigTypeTag()});
1699 }
1700 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
1701 try self.register_manager.getReg(.rax, null);
1702 try self.register_manager.getReg(.rdx, inst);
1703 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx });
1704 defer for (reg_locks) |reg| {
1705 self.register_manager.unlockReg(reg);
1706 };
1707
1708 const lhs = try self.resolveInst(bin_op.lhs);
1709 const rhs = try self.resolveInst(bin_op.rhs);
1710
1711 const signedness = ty.intInfo(self.target.*).signedness;
1712 try self.genIntMulDivOpMir(switch (signedness) {
1713 .signed => .idiv,
1714 .unsigned => .div,
1715 }, ty, signedness, lhs, rhs);
1716
1717 const result: MCValue = .{ .register = .rdx };
1718
1719 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1720}
1721
1722fn airMod(self: *Self, inst: Air.Inst.Index) !void {
1723 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1724
1725 if (self.liveness.isUnused(inst)) {
1726 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1727 }
1728
1729 const ty = self.air.typeOfIndex(inst);
1730 if (ty.zigTypeTag() != .Int) {
1731 return self.fail("TODO implement .mod for operands of dst type {}", .{ty.zigTypeTag()});
1732 }
1733 const signedness = ty.intInfo(self.target.*).signedness;
1734
1735 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
1736 try self.register_manager.getReg(.rax, null);
1737 try self.register_manager.getReg(.rdx, if (signedness == .unsigned) inst else null);
1738 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx });
1739 defer for (reg_locks) |reg| {
1740 self.register_manager.unlockReg(reg);
1741 };
1742
1743 const lhs = try self.resolveInst(bin_op.lhs);
1744 const rhs = try self.resolveInst(bin_op.rhs);
1745
1746 const result: MCValue = result: {
1747 switch (signedness) {
1748 .unsigned => {
1749 try self.genIntMulDivOpMir(switch (signedness) {
1750 .signed => .idiv,
1751 .unsigned => .div,
1752 }, ty, signedness, lhs, rhs);
1753 break :result MCValue{ .register = .rdx };
1754 },
1755 .signed => {
1756 const div_floor = try self.genInlineIntDivFloor(ty, lhs, rhs);
1757 try self.genIntMulComplexOpMir(ty, div_floor, rhs);
1758
1759 const result = try self.copyToRegisterWithInstTracking(inst, ty, lhs);
1760 try self.genBinOpMir(.sub, ty, result, div_floor);
1761
1762 break :result result;
1763 },
1764 }
1765 };
1766
1767 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1768}
1769
1770fn airShl(self: *Self, inst: Air.Inst.Index) !void {1691fn airShl(self: *Self, inst: Air.Inst.Index) !void {
1771 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1692 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1772 if (self.liveness.isUnused(inst)) {1693 if (self.liveness.isUnused(inst)) {
...@@ -3234,12 +3155,18 @@ fn genBinOp(...@@ -3234,12 +3155,18 @@ fn genBinOp(
3234 .subwrap,3155 .subwrap,
3235 .mul,3156 .mul,
3236 .mulwrap,3157 .mulwrap,
3158 .div_exact,
3159 .div_trunc,
3160 .rem,
3161 .mod,
3237 .shl,3162 .shl,
3238 .shr,3163 .shr,
3239 .ptr_add,3164 .ptr_add,
3240 .ptr_sub,3165 .ptr_sub,
3241 => false,3166 => false,
32423167
3168 .div_float => return self.fail("TODO implement genBinOp for {}", .{tag}),
3169
3243 else => unreachable,3170 else => unreachable,
3244 };3171 };
3245 const dst_ty = self.air.typeOf(op_lhs);3172 const dst_ty = self.air.typeOf(op_lhs);
...@@ -3278,6 +3205,57 @@ fn genBinOp(...@@ -3278,6 +3205,57 @@ fn genBinOp(
3278 .unsigned => MCValue{ .register = registerAlias(.rax, @intCast(u32, dst_ty.abiSize(self.target.*))) },3205 .unsigned => MCValue{ .register = registerAlias(.rax, @intCast(u32, dst_ty.abiSize(self.target.*))) },
3279 };3206 };
3280 },3207 },
3208 .mod,
3209 .rem,
3210 => {
3211 const int_info = dst_ty.intInfo(self.target.*);
3212 const track_inst_rdx: ?Air.Inst.Index = switch (tag) {
3213 .mod => if (int_info.signedness == .unsigned) maybe_inst else null,
3214 .rem => maybe_inst,
3215 else => unreachable,
3216 };
3217
3218 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
3219 try self.register_manager.getReg(.rax, null);
3220 try self.register_manager.getReg(.rdx, track_inst_rdx);
3221 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx });
3222 defer for (reg_locks) |reg| {
3223 self.register_manager.unlockReg(reg);
3224 };
3225
3226 const lhs = try self.resolveInst(op_lhs);
3227 const rhs = try self.resolveInst(op_rhs);
3228
3229 switch (int_info.signedness) {
3230 .signed => {
3231 switch (tag) {
3232 .rem => {
3233 try self.genIntMulDivOpMir(.idiv, dst_ty, .signed, lhs, rhs);
3234 return MCValue{ .register = .rdx };
3235 },
3236 .mod => {
3237 const div_floor = try self.genInlineIntDivFloor(dst_ty, lhs, rhs);
3238 try self.genIntMulComplexOpMir(dst_ty, div_floor, rhs);
3239 const div_floor_lock = self.register_manager.lockReg(div_floor.register);
3240 defer if (div_floor_lock) |lock| self.register_manager.unlockReg(lock);
3241
3242 const result: MCValue = if (maybe_inst) |inst|
3243 try self.copyToRegisterWithInstTracking(inst, dst_ty, lhs)
3244 else
3245 MCValue{ .register = try self.copyToTmpRegister(dst_ty, lhs) };
3246 try self.genBinOpMir(.sub, dst_ty, result, div_floor);
3247
3248 return result;
3249 },
3250 else => unreachable,
3251 }
3252 },
3253 .unsigned => {
3254 try self.genIntMulDivOpMir(.div, dst_ty, .unsigned, lhs, rhs);
3255 return MCValue{ .register = .rdx };
3256 },
3257 }
3258 },
3281 else => {},3259 else => {},
3282 }3260 }
32833261