Skip to content

Commit aa421ff

Browse files
committed
threads: fix semantic error in old Threads.Atomic
1 parent 4598966 commit aa421ff

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

base/atomics.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -356,13 +356,13 @@ for typ in atomictypes
356356
rt = "$lt, $lt*"
357357
irt = "$ilt, $ilt*"
358358
@eval getindex(x::Atomic{$typ}) =
359-
llvmcall($"""
359+
GC.@preserve x llvmcall($"""
360360
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
361361
%rv = load atomic $rt %ptr acquire, align $(gc_alignment(typ))
362362
ret $lt %rv
363363
""", $typ, Tuple{Ptr{$typ}}, unsafe_convert(Ptr{$typ}, x))
364364
@eval setindex!(x::Atomic{$typ}, v::$typ) =
365-
llvmcall($"""
365+
GC.@preserve x llvmcall($"""
366366
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
367367
store atomic $lt %1, $lt* %ptr release, align $(gc_alignment(typ))
368368
ret void
@@ -371,7 +371,7 @@ for typ in atomictypes
371371
# Note: atomic_cas! succeeded (i.e. it stored "new") if and only if the result is "cmp"
372372
if typ <: Integer
373373
@eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) =
374-
llvmcall($"""
374+
GC.@preserve x llvmcall($"""
375375
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
376376
%rs = cmpxchg $lt* %ptr, $lt %1, $lt %2 acq_rel acquire
377377
%rv = extractvalue { $lt, i1 } %rs, 0
@@ -380,7 +380,7 @@ for typ in atomictypes
380380
unsafe_convert(Ptr{$typ}, x), cmp, new)
381381
else
382382
@eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) =
383-
llvmcall($"""
383+
GC.@preserve x llvmcall($"""
384384
%iptr = inttoptr i$WORD_SIZE %0 to $ilt*
385385
%icmp = bitcast $lt %1 to $ilt
386386
%inew = bitcast $lt %2 to $ilt
@@ -403,15 +403,15 @@ for typ in atomictypes
403403
if rmwop in arithmetic_ops && !(typ <: ArithmeticTypes) continue end
404404
if typ <: Integer
405405
@eval $fn(x::Atomic{$typ}, v::$typ) =
406-
llvmcall($"""
406+
GC.@preserve x llvmcall($"""
407407
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
408408
%rv = atomicrmw $rmw $lt* %ptr, $lt %1 acq_rel
409409
ret $lt %rv
410410
""", $typ, Tuple{Ptr{$typ}, $typ}, unsafe_convert(Ptr{$typ}, x), v)
411411
else
412412
rmwop === :xchg || continue
413413
@eval $fn(x::Atomic{$typ}, v::$typ) =
414-
llvmcall($"""
414+
GC.@preserve x llvmcall($"""
415415
%iptr = inttoptr i$WORD_SIZE %0 to $ilt*
416416
%ival = bitcast $lt %1 to $ilt
417417
%irv = atomicrmw $rmw $ilt* %iptr, $ilt %ival acq_rel

src/llvm-alloc-opt.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,21 @@ void Optimizer::checkInst(Instruction *I)
628628
use_info.hasunknownmem = true;
629629
return true;
630630
}
631+
if (isa<AtomicCmpXchgInst>(inst) || isa<AtomicRMWInst>(inst)) {
632+
// Only store value count
633+
if (use->getOperandNo() != isa<AtomicCmpXchgInst>(inst) ? AtomicCmpXchgInst::getPointerOperandIndex() : AtomicRMWInst::getPointerOperandIndex()) {
634+
use_info.escaped = true;
635+
return false;
636+
}
637+
use_info.hasload = true;
638+
auto storev = isa<AtomicCmpXchgInst>(inst) ? cast<AtomicCmpXchgInst>(inst)->getNewValOperand() : cast<AtomicRMWInst>(inst)->getValOperand();
639+
if (cur.offset == UINT32_MAX || !use_info.addMemOp(inst, use->getOperandNo(),
640+
cur.offset, storev->getType(),
641+
true, *pass.DL))
642+
use_info.hasunknownmem = true;
643+
use_info.refload = true;
644+
return true;
645+
}
631646
if (isa<AddrSpaceCastInst>(inst) || isa<BitCastInst>(inst)) {
632647
push_inst(inst);
633648
return true;
@@ -1331,6 +1346,22 @@ void Optimizer::splitOnStack(CallInst *orig_inst)
13311346
store->eraseFromParent();
13321347
return;
13331348
}
1349+
else if (isa<AtomicCmpXchgInst>(user) || isa<AtomicRMWInst>(user)) {
1350+
auto slot_idx = find_slot(offset);
1351+
auto &slot = slots[slot_idx];
1352+
assert(slot.offset <= offset && slot.offset + slot.size >= offset);
1353+
IRBuilder<> builder(user);
1354+
Value *newptr;
1355+
if (slot.isref) {
1356+
assert(slot.offset == offset);
1357+
newptr = slot.slot;
1358+
}
1359+
else {
1360+
Value *Val = isa<AtomicCmpXchgInst>(user) ? cast<AtomicCmpXchgInst>(user)->getNewValOperand() : cast<AtomicRMWInst>(user)->getValOperand();
1361+
newptr = slot_gep(slot, offset, Val->getType(), builder);
1362+
}
1363+
*use = newptr;
1364+
}
13341365
else if (auto call = dyn_cast<CallInst>(user)) {
13351366
auto callee = call->getCalledOperand();
13361367
assert(callee); // makes it clear for clang analyser that `callee` is not NULL

0 commit comments

Comments
 (0)