authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-04 15:58:55-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-04 16:26:56-04:00
log644d943861ece8ef2c394bf4a4fdf0da9500c2cd
treef3498537472125a3676d0e6a85b97492990e3ec6
parent2a5335d7b6628115ce29c3c712b55c661181e1d1

x86_64: implement 128-bit integer comparisons


2 files changed, 153 insertions(+), 31 deletions(-)

src/arch/x86_64/CodeGen.zig+153-30
...@@ -7962,10 +7962,10 @@ fn genBinOpMir(...@@ -7962,10 +7962,10 @@ fn genBinOpMir(
7962 .air_ref,7962 .air_ref,
7963 => unreachable,7963 => unreachable,
7964 .immediate,7964 .immediate,
7965 .eflags,
7965 .register,7966 .register,
7966 .register_pair,7967 .register_pair,
7967 .register_offset,7968 .register_offset,
7968 .eflags,
7969 .indirect,7969 .indirect,
7970 .lea_direct,7970 .lea_direct,
7971 .lea_got,7971 .lea_got,
...@@ -8750,33 +8750,122 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8750,33 +8750,122 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8750 .lt, .gte => {},8750 .lt, .gte => {},
8751 .lte, .gt => unreachable,8751 .lte, .gt => unreachable,
8752 .eq, .neq => {8752 .eq, .neq => {
8753 const dst_addr_mcv: MCValue = switch (dst_mcv) {8753 const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock };
8754 .memory, .indirect, .load_frame => dst_mcv.address(),8754
8755 else => .{ .register = try self.copyToTmpRegister(8755 const resolved_dst_mcv = switch (dst_mcv) {
8756 Type.usize,8756 else => dst_mcv,
8757 dst_mcv.address(),8757 .air_ref => |dst_ref| try self.resolveInst(dst_ref),
8758 ) },
8759 };8758 };
8760 const dst_addr_lock = if (dst_addr_mcv.getReg()) |reg|8759 const dst_info: OpInfo = switch (resolved_dst_mcv) {
8761 self.register_manager.lockReg(reg)8760 .none,
8762 else8761 .unreach,
8763 null;8762 .dead,
8764 defer if (dst_addr_lock) |lock| self.register_manager.unlockReg(lock);8763 .undef,
8764 .immediate,
8765 .eflags,
8766 .register,
8767 .register_offset,
8768 .register_overflow,
8769 .indirect,
8770 .lea_direct,
8771 .lea_got,
8772 .lea_tlv,
8773 .lea_frame,
8774 .reserved_frame,
8775 .air_ref,
8776 => unreachable,
8777 .register_pair, .load_frame => null,
8778 .memory, .load_got, .load_direct, .load_tlv => dst: {
8779 switch (resolved_dst_mcv) {
8780 .memory => |addr| if (math.cast(
8781 i32,
8782 @as(i64, @bitCast(addr)),
8783 ) != null and math.cast(
8784 i32,
8785 @as(i64, @bitCast(addr)) + abi_size - 8,
8786 ) != null) break :dst null,
8787 .load_got, .load_direct, .load_tlv => {},
8788 else => unreachable,
8789 }
8790
8791 const dst_addr_reg =
8792 (try self.register_manager.allocReg(null, gp)).to64();
8793 const dst_addr_lock =
8794 self.register_manager.lockRegAssumeUnused(dst_addr_reg);
8795 errdefer self.register_manager.unlockReg(dst_addr_lock);
8796
8797 try self.genSetReg(
8798 dst_addr_reg,
8799 Type.usize,
8800 resolved_dst_mcv.address(),
8801 );
8802 break :dst .{
8803 .addr_reg = dst_addr_reg,
8804 .addr_lock = dst_addr_lock,
8805 };
8806 },
8807 };
8808 defer if (dst_info) |info|
8809 self.register_manager.unlockReg(info.addr_lock);
87658810
8766 const src_addr_mcv: MCValue = switch (src_mcv) {8811 const resolved_src_mcv = switch (src_mcv) {
8767 .memory, .indirect, .load_frame => src_mcv.address(),8812 else => src_mcv,
8768 else => .{ .register = try self.copyToTmpRegister(8813 .air_ref => |src_ref| try self.resolveInst(src_ref),
8769 Type.usize,
8770 src_mcv.address(),
8771 ) },
8772 };8814 };
8773 const src_addr_lock = if (src_addr_mcv.getReg()) |reg|8815 const src_info: OpInfo = switch (resolved_src_mcv) {
8774 self.register_manager.lockReg(reg)8816 .none,
8775 else8817 .unreach,
8776 null;8818 .dead,
8777 defer if (src_addr_lock) |lock| self.register_manager.unlockReg(lock);8819 .undef,
8820 .immediate,
8821 .eflags,
8822 .register,
8823 .register_offset,
8824 .register_overflow,
8825 .indirect,
8826 .lea_direct,
8827 .lea_got,
8828 .lea_tlv,
8829 .lea_frame,
8830 .reserved_frame,
8831 .air_ref,
8832 => unreachable,
8833 .register_pair, .load_frame => null,
8834 .memory, .load_got, .load_direct, .load_tlv => src: {
8835 switch (resolved_src_mcv) {
8836 .memory => |addr| if (math.cast(
8837 i32,
8838 @as(i64, @bitCast(addr)),
8839 ) != null and math.cast(
8840 i32,
8841 @as(i64, @bitCast(addr)) + abi_size - 8,
8842 ) != null) break :src null,
8843 .load_got, .load_direct, .load_tlv => {},
8844 else => unreachable,
8845 }
8846
8847 const src_addr_reg =
8848 (try self.register_manager.allocReg(null, gp)).to64();
8849 const src_addr_lock =
8850 self.register_manager.lockRegAssumeUnused(src_addr_reg);
8851 errdefer self.register_manager.unlockReg(src_addr_lock);
8852
8853 try self.genSetReg(
8854 src_addr_reg,
8855 Type.usize,
8856 resolved_src_mcv.address(),
8857 );
8858 break :src .{
8859 .addr_reg = src_addr_reg,
8860 .addr_lock = src_addr_lock,
8861 };
8862 },
8863 };
8864 defer if (src_info) |info|
8865 self.register_manager.unlockReg(info.addr_lock);
87788866
8779 const regs = try self.register_manager.allocRegs(2, .{ null, null }, gp);8867 const regs =
8868 try self.register_manager.allocRegs(2, .{ null, null }, gp);
8780 const acc_reg = regs[0].to64();8869 const acc_reg = regs[0].to64();
8781 const locks = self.register_manager.lockRegsAssumeUnused(2, regs);8870 const locks = self.register_manager.lockRegsAssumeUnused(2, regs);
8782 defer for (locks) |lock| self.register_manager.unlockReg(lock);8871 defer for (locks) |lock| self.register_manager.unlockReg(lock);
...@@ -8784,18 +8873,52 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8784,18 +8873,52 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8784 const limbs_len = std.math.divCeil(u16, abi_size, 8) catch unreachable;8873 const limbs_len = std.math.divCeil(u16, abi_size, 8) catch unreachable;
8785 var limb_i: u16 = 0;8874 var limb_i: u16 = 0;
8786 while (limb_i < limbs_len) : (limb_i += 1) {8875 while (limb_i < limbs_len) : (limb_i += 1) {
8876 const off = limb_i * 8;
8787 const tmp_reg = regs[@min(limb_i, 1)].to64();8877 const tmp_reg = regs[@min(limb_i, 1)].to64();
8788 try self.genSetReg(8878
8789 tmp_reg,8879 try self.genSetReg(tmp_reg, Type.usize, if (dst_info) |info| .{
8790 Type.usize,8880 .indirect = .{ .reg = info.addr_reg, .off = off },
8791 dst_addr_mcv.offset(limb_i * 8).deref(),8881 } else switch (resolved_dst_mcv) {
8792 );8882 .register_pair => |dst_regs| .{ .register = dst_regs[limb_i] },
8883 .memory => |dst_addr| .{
8884 .memory = @bitCast(@as(i64, @bitCast(dst_addr)) + off),
8885 },
8886 .indirect => |reg_off| .{ .indirect = .{
8887 .reg = reg_off.reg,
8888 .off = reg_off.off + off,
8889 } },
8890 .load_frame => |frame_addr| .{ .load_frame = .{
8891 .index = frame_addr.index,
8892 .off = frame_addr.off + off,
8893 } },
8894 else => unreachable,
8895 });
8896
8793 try self.genBinOpMir(8897 try self.genBinOpMir(
8794 .{ ._, .xor },8898 .{ ._, .xor },
8795 Type.usize,8899 Type.usize,
8796 .{ .register = tmp_reg },8900 .{ .register = tmp_reg },
8797 src_addr_mcv.offset(limb_i * 8).deref(),8901 if (src_info) |info| .{
8902 .indirect = .{ .reg = info.addr_reg, .off = off },
8903 } else switch (resolved_src_mcv) {
8904 .register_pair => |src_regs| .{
8905 .register = src_regs[limb_i],
8906 },
8907 .memory => |src_addr| .{
8908 .memory = @bitCast(@as(i64, @bitCast(src_addr)) + off),
8909 },
8910 .indirect => |reg_off| .{ .indirect = .{
8911 .reg = reg_off.reg,
8912 .off = reg_off.off + off,
8913 } },
8914 .load_frame => |frame_addr| .{ .load_frame = .{
8915 .index = frame_addr.index,
8916 .off = frame_addr.off + off,
8917 } },
8918 else => unreachable,
8919 },
8798 );8920 );
8921
8799 if (limb_i > 0) try self.asmRegisterRegister(8922 if (limb_i > 0) try self.asmRegisterRegister(
8800 .{ ._, .@"or" },8923 .{ ._, .@"or" },
8801 acc_reg,8924 acc_reg,
test/behavior/packed-struct.zig-1
...@@ -258,7 +258,6 @@ test "nested packed struct unaligned" {...@@ -258,7 +258,6 @@ test "nested packed struct unaligned" {
258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;260 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
262 if (native_endian != .Little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet261 if (native_endian != .Little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet
263262
264 const S1 = packed struct {263 const S1 = packed struct {