| author | |
| committer | |
| log | 4c36a403a895bd3e7dc7b4dd308f2b82a3dab60a |
| tree | 50763d16076bdc4d5c636f0aa39654fb8b631e39 |
| parent | d4ca9804f8a546c45451a58c8bde20bc2299d4a6 |
| signature |
3 files changed, 29 insertions(+), 18 deletions(-)
src/Air.zig+4-1| ... | ... | @@ -1889,7 +1889,10 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { |
| 1889 | 1889 | }, |
| 1890 | 1890 | .load => air.typeOf(data.ty_op.operand, ip).isVolatilePtrIp(ip), |
| 1891 | 1891 | .slice_elem_val, .ptr_elem_val => air.typeOf(data.bin_op.lhs, ip).isVolatilePtrIp(ip), |
| 1892 | .atomic_load => air.typeOf(data.atomic_load.ptr, ip).isVolatilePtrIp(ip), | |
| 1892 | .atomic_load => switch (data.atomic_load.order) { | |
| 1893 | .unordered, .monotonic => air.typeOf(data.atomic_load.ptr, ip).isVolatilePtrIp(ip), | |
| 1894 | else => true, // Stronger memory orderings have inter-thread side effects. | |
| 1895 | }, | |
| 1893 | 1896 | }; |
| 1894 | 1897 | } |
| 1895 | 1898 |
src/arch/riscv64/CodeGen.zig+8-6| ... | ... | @@ -7738,7 +7738,10 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 7738 | 7738 | const bit_size = elem_ty.bitSize(zcu); |
| 7739 | 7739 | if (bit_size > 64) return func.fail("TODO: airAtomicLoad > 64 bits", .{}); |
| 7740 | 7740 | |
| 7741 | const result_mcv = try func.allocRegOrMem(elem_ty, inst, true); | |
| 7741 | const result_mcv: MCValue = if (func.liveness.isUnused(inst)) | |
| 7742 | .{ .register = .zero } | |
| 7743 | else | |
| 7744 | try func.allocRegOrMem(elem_ty, inst, true); | |
| 7742 | 7745 | assert(result_mcv == .register); // should be less than 8 bytes |
| 7743 | 7746 | |
| 7744 | 7747 | if (order == .seq_cst) { |
| ... | ... | @@ -7754,11 +7757,10 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 7754 | 7757 | try func.load(result_mcv, ptr_mcv, ptr_ty); |
| 7755 | 7758 | |
| 7756 | 7759 | switch (order) { |
| 7757 | // Don't guarnetee other memory operations to be ordered after the load. | |
| 7758 | .unordered => {}, | |
| 7759 | .monotonic => {}, | |
| 7760 | // Make sure all previous reads happen before any reading or writing accurs. | |
| 7761 | .seq_cst, .acquire => { | |
| 7760 | // Don't guarantee other memory operations to be ordered after the load. | |
| 7761 | .unordered, .monotonic => {}, | |
| 7762 | // Make sure all previous reads happen before any reading or writing occurs. | |
| 7763 | .acquire, .seq_cst => { | |
| 7762 | 7764 | _ = try func.addInst(.{ |
| 7763 | 7765 | .tag = .fence, |
| 7764 | 7766 | .data = .{ .fence = .{ |
src/arch/x86_64/CodeGen.zig+17-11| ... | ... | @@ -106219,23 +106219,29 @@ fn airAtomicRmw(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 106219 | 106219 | |
| 106220 | 106220 | fn airAtomicLoad(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 106221 | 106221 | const atomic_load = self.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; |
| 106222 | const result: MCValue = result: { | |
| 106223 | const ptr_ty = self.typeOf(atomic_load.ptr); | |
| 106224 | const ptr_mcv = try self.resolveInst(atomic_load.ptr); | |
| 106225 | const ptr_lock = switch (ptr_mcv) { | |
| 106226 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), | |
| 106227 | else => null, | |
| 106228 | }; | |
| 106229 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); | |
| 106222 | 106230 | |
| 106223 | const ptr_ty = self.typeOf(atomic_load.ptr); | |
| 106224 | const ptr_mcv = try self.resolveInst(atomic_load.ptr); | |
| 106225 | const ptr_lock = switch (ptr_mcv) { | |
| 106226 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), | |
| 106227 | else => null, | |
| 106228 | }; | |
| 106229 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); | |
| 106231 | const unused = self.liveness.isUnused(inst); | |
| 106230 | 106232 | |
| 106231 | const dst_mcv = | |
| 106232 | if (self.reuseOperand(inst, atomic_load.ptr, 0, ptr_mcv)) | |
| 106233 | const dst_mcv: MCValue = if (unused) | |
| 106234 | .{ .register = try self.register_manager.allocReg(null, self.regSetForType(ptr_ty.childType(self.pt.zcu))) } | |
| 106235 | else if (self.reuseOperand(inst, atomic_load.ptr, 0, ptr_mcv)) | |
| 106233 | 106236 | ptr_mcv |
| 106234 | 106237 | else |
| 106235 | 106238 | try self.allocRegOrMem(inst, true); |
| 106236 | 106239 | |
| 106237 | try self.load(dst_mcv, ptr_ty, ptr_mcv); | |
| 106238 | return self.finishAir(inst, dst_mcv, .{ atomic_load.ptr, .none, .none }); | |
| 106240 | try self.load(dst_mcv, ptr_ty, ptr_mcv); | |
| 106241 | ||
| 106242 | break :result if (unused) .unreach else dst_mcv; | |
| 106243 | }; | |
| 106244 | return self.finishAir(inst, result, .{ atomic_load.ptr, .none, .none }); | |
| 106239 | 106245 | } |
| 106240 | 106246 | |
| 106241 | 106247 | fn airAtomicStore(self: *CodeGen, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void { |