Air: Fix mustLower() for atomic_load with inter-thread ordering.

This commit is contained in:
Alex Rønne Petersen 2024-10-31 09:00:02 +01:00
parent d4ca9804f8
commit 4c36a403a8
No known key found for this signature in database
3 changed files with 29 additions and 18 deletions

View File

@ -1889,7 +1889,10 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
}, },
.load => air.typeOf(data.ty_op.operand, ip).isVolatilePtrIp(ip), .load => air.typeOf(data.ty_op.operand, ip).isVolatilePtrIp(ip),
.slice_elem_val, .ptr_elem_val => air.typeOf(data.bin_op.lhs, ip).isVolatilePtrIp(ip), .slice_elem_val, .ptr_elem_val => air.typeOf(data.bin_op.lhs, ip).isVolatilePtrIp(ip),
.atomic_load => air.typeOf(data.atomic_load.ptr, ip).isVolatilePtrIp(ip), .atomic_load => switch (data.atomic_load.order) {
.unordered, .monotonic => air.typeOf(data.atomic_load.ptr, ip).isVolatilePtrIp(ip),
else => true, // Stronger memory orderings have inter-thread side effects.
},
}; };
} }

View File

@ -7738,7 +7738,10 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void {
const bit_size = elem_ty.bitSize(zcu); const bit_size = elem_ty.bitSize(zcu);
if (bit_size > 64) return func.fail("TODO: airAtomicLoad > 64 bits", .{}); if (bit_size > 64) return func.fail("TODO: airAtomicLoad > 64 bits", .{});
const result_mcv = try func.allocRegOrMem(elem_ty, inst, true); const result_mcv: MCValue = if (func.liveness.isUnused(inst))
.{ .register = .zero }
else
try func.allocRegOrMem(elem_ty, inst, true);
assert(result_mcv == .register); // should be less than 8 bytes assert(result_mcv == .register); // should be less than 8 bytes
if (order == .seq_cst) { if (order == .seq_cst) {
@ -7754,11 +7757,10 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void {
try func.load(result_mcv, ptr_mcv, ptr_ty); try func.load(result_mcv, ptr_mcv, ptr_ty);
switch (order) { switch (order) {
// Don't guarnetee other memory operations to be ordered after the load. // Don't guarantee other memory operations to be ordered after the load.
.unordered => {}, .unordered, .monotonic => {},
.monotonic => {}, // Make sure all previous reads happen before any reading or writing occurs.
// Make sure all previous reads happen before any reading or writing accurs. .acquire, .seq_cst => {
.seq_cst, .acquire => {
_ = try func.addInst(.{ _ = try func.addInst(.{
.tag = .fence, .tag = .fence,
.data = .{ .fence = .{ .data = .{ .fence = .{

View File

@ -106219,7 +106219,7 @@ fn airAtomicRmw(self: *CodeGen, inst: Air.Inst.Index) !void {
fn airAtomicLoad(self: *CodeGen, inst: Air.Inst.Index) !void { fn airAtomicLoad(self: *CodeGen, inst: Air.Inst.Index) !void {
const atomic_load = self.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; const atomic_load = self.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load;
const result: MCValue = result: {
const ptr_ty = self.typeOf(atomic_load.ptr); const ptr_ty = self.typeOf(atomic_load.ptr);
const ptr_mcv = try self.resolveInst(atomic_load.ptr); const ptr_mcv = try self.resolveInst(atomic_load.ptr);
const ptr_lock = switch (ptr_mcv) { const ptr_lock = switch (ptr_mcv) {
@ -106228,14 +106228,20 @@ fn airAtomicLoad(self: *CodeGen, inst: Air.Inst.Index) !void {
}; };
defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
const dst_mcv = const unused = self.liveness.isUnused(inst);
if (self.reuseOperand(inst, atomic_load.ptr, 0, ptr_mcv))
const dst_mcv: MCValue = if (unused)
.{ .register = try self.register_manager.allocReg(null, self.regSetForType(ptr_ty.childType(self.pt.zcu))) }
else if (self.reuseOperand(inst, atomic_load.ptr, 0, ptr_mcv))
ptr_mcv ptr_mcv
else else
try self.allocRegOrMem(inst, true); try self.allocRegOrMem(inst, true);
try self.load(dst_mcv, ptr_ty, ptr_mcv); try self.load(dst_mcv, ptr_ty, ptr_mcv);
return self.finishAir(inst, dst_mcv, .{ atomic_load.ptr, .none, .none });
break :result if (unused) .unreach else dst_mcv;
};
return self.finishAir(inst, result, .{ atomic_load.ptr, .none, .none });
} }
fn airAtomicStore(self: *CodeGen, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void { fn airAtomicStore(self: *CodeGen, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void {