Skip to content

Commit c7d13de

Browse files
committed
update codegen to use atomic annotations also
1 parent 7fa640d commit c7d13de

12 files changed

+248
-177
lines changed

src/atomics.h

+8
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@
7575
// TODO: Maybe add jl_atomic_compare_exchange_weak for spin lock
7676
# define jl_atomic_store(obj, val) \
7777
__atomic_store_n(obj, val, __ATOMIC_SEQ_CST)
78+
# define jl_atomic_store_relaxed(obj, val) \
79+
__atomic_store_n(obj, val, __ATOMIC_RELAXED)
7880
# if defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) || \
7981
!(defined(_CPU_X86_) || defined(_CPU_X86_64_))
8082
// ICC and Clang doesn't have this bug...
@@ -269,6 +271,12 @@ static inline void jl_atomic_store_release(volatile T *obj, T2 val)
269271
jl_signal_fence();
270272
*obj = (T)val;
271273
}
274+
template<typename T, typename T2>
275+
static inline void jl_atomic_store_relaxed(volatile T *obj, T2 val)
276+
{
277+
jl_signal_fence();
278+
*obj = (T)val;
279+
}
272280
// atomic loads
273281
template<typename T>
274282
static inline T jl_atomic_load(volatile T *obj)

src/ccall.cpp

+20-17
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,15 @@ static Value *runtime_sym_lookup(
135135
BasicBlock *dlsym_lookup = BasicBlock::Create(jl_LLVMContext, "dlsym");
136136
BasicBlock *ccall_bb = BasicBlock::Create(jl_LLVMContext, "ccall");
137137
Constant *initnul = ConstantPointerNull::get((PointerType*)T_pvoidfunc);
138-
LoadInst *llvmf_orig = irbuilder.CreateAlignedLoad(llvmgv, sizeof(void*));
138+
LoadInst *llvmf_orig = irbuilder.CreateAlignedLoad(T_pvoidfunc, llvmgv, sizeof(void*));
139139
// This in principle needs a consume ordering so that load from
140140
// this pointer sees a valid value. However, this is not supported by
141141
// LLVM (or agreed on in the C/C++ standard FWIW) and should be
142142
// almost impossible to happen on every platform we support since this
143143
// ordering is enforced by the hardware and LLVM has to speculate an
144144
// invalid load from the `cglobal` but doesn't depend on the `cglobal`
145145
// value for this to happen.
146-
// llvmf_orig->setAtomic(AtomicOrdering::Consume);
146+
llvmf_orig->setAtomic(AtomicOrdering::Unordered);
147147
irbuilder.CreateCondBr(
148148
irbuilder.CreateICmpNE(llvmf_orig, initnul),
149149
ccall_bb,
@@ -162,7 +162,7 @@ static Value *runtime_sym_lookup(
162162
}
163163
Value *llvmf = irbuilder.CreateCall(prepare_call_in(jl_builderModule(irbuilder), jldlsym_func),
164164
{ libname, stringConstPtr(irbuilder, f_name), libptrgv });
165-
auto store = irbuilder.CreateAlignedStore(llvmf, llvmgv, sizeof(void*));
165+
StoreInst *store = irbuilder.CreateAlignedStore(llvmf, llvmgv, sizeof(void*));
166166
store->setAtomic(AtomicOrdering::Release);
167167
irbuilder.CreateBr(ccall_bb);
168168

@@ -231,7 +231,7 @@ static GlobalVariable *emit_plt_thunk(
231231
IRBuilder<> irbuilder(b0);
232232
Value *ptr = runtime_sym_lookup(irbuilder, funcptype, f_lib, f_name, plt, libptrgv,
233233
llvmgv, runtime_lib);
234-
auto store = irbuilder.CreateAlignedStore(irbuilder.CreateBitCast(ptr, T_pvoidfunc), got, sizeof(void*));
234+
StoreInst *store = irbuilder.CreateAlignedStore(irbuilder.CreateBitCast(ptr, T_pvoidfunc), got, sizeof(void*));
235235
store->setAtomic(AtomicOrdering::Release);
236236
SmallVector<Value*, 16> args;
237237
for (Function::arg_iterator arg = plt->arg_begin(), arg_e = plt->arg_end(); arg != arg_e; ++arg)
@@ -314,7 +314,7 @@ static Value *emit_plt(
314314
// consume ordering too. This is even less likely to cause issues though
315315
// since the only thing we do to this loaded pointer is to call it
316316
// immediately.
317-
// got_val->setAtomic(AtomicOrdering::Consume);
317+
got_val->setAtomic(AtomicOrdering::Unordered);
318318
return ctx.builder.CreateBitCast(got_val, funcptype);
319319
}
320320

@@ -429,17 +429,19 @@ static Value *llvm_type_rewrite(
429429
Value *from;
430430
Value *to;
431431
const DataLayout &DL = jl_data_layout;
432+
unsigned align = std::max(DL.getPrefTypeAlignment(target_type), DL.getPrefTypeAlignment(from_type));
432433
if (DL.getTypeAllocSize(target_type) >= DL.getTypeAllocSize(from_type)) {
433434
to = emit_static_alloca(ctx, target_type);
435+
cast<AllocaInst>(to)->setAlignment(Align(align));
434436
from = emit_bitcast(ctx, to, from_type->getPointerTo());
435437
}
436438
else {
437439
from = emit_static_alloca(ctx, from_type);
440+
cast<AllocaInst>(from)->setAlignment(Align(align));
438441
to = emit_bitcast(ctx, from, target_type->getPointerTo());
439442
}
440-
// XXX: deal with possible alignment issues
441-
ctx.builder.CreateStore(v, from);
442-
return ctx.builder.CreateLoad(to);
443+
ctx.builder.CreateAlignedStore(v, from, align);
444+
return ctx.builder.CreateAlignedLoad(to, align);
443445
}
444446

445447
// --- argument passing and scratch space utilities ---
@@ -1604,9 +1606,9 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16041606
Value *ptls_i16 = emit_bitcast(ctx, ctx.ptlsStates, T_pint16);
16051607
const int tid_offset = offsetof(jl_tls_states_t, tid);
16061608
Value *ptid = ctx.builder.CreateGEP(ptls_i16, ConstantInt::get(T_size, tid_offset / 2));
1607-
return mark_or_box_ccall_result(ctx,
1608-
tbaa_decorate(tbaa_const, ctx.builder.CreateLoad(ptid)),
1609-
retboxed, rt, unionall, static_rt);
1609+
LoadInst *tid = ctx.builder.CreateAlignedLoad(ptid, sizeof(int16_t));
1610+
tbaa_decorate(tbaa_const, tid);
1611+
return mark_or_box_ccall_result(ctx, tid, retboxed, rt, unionall, static_rt);
16101612
}
16111613
else if (is_libjulia_func(jl_get_current_task)) {
16121614
assert(lrt == T_prjlvalue);
@@ -1615,9 +1617,9 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16151617
Value *ptls_pv = emit_bitcast(ctx, ctx.ptlsStates, T_pprjlvalue);
16161618
const int ct_offset = offsetof(jl_tls_states_t, current_task);
16171619
Value *pct = ctx.builder.CreateGEP(ptls_pv, ConstantInt::get(T_size, ct_offset / sizeof(void*)));
1618-
return mark_or_box_ccall_result(ctx,
1619-
tbaa_decorate(tbaa_const, ctx.builder.CreateLoad(pct)),
1620-
retboxed, rt, unionall, static_rt);
1620+
LoadInst *ct = ctx.builder.CreateAlignedLoad(pct, sizeof(void*));
1621+
tbaa_decorate(tbaa_const, ct);
1622+
return mark_or_box_ccall_result(ctx, ct, retboxed, rt, unionall, static_rt);
16211623
}
16221624
else if (is_libjulia_func(jl_set_next_task)) {
16231625
assert(lrt == T_void);
@@ -1636,8 +1638,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16361638
ctx.builder.CreateCall(prepare_call(gcroot_flush_func));
16371639
Value *pdefer_sig = emit_defer_signal(ctx);
16381640
Value *defer_sig = ctx.builder.CreateLoad(pdefer_sig);
1639-
defer_sig = ctx.builder.CreateAdd(defer_sig,
1640-
ConstantInt::get(T_sigatomic, 1));
1641+
defer_sig = ctx.builder.CreateAdd(defer_sig, ConstantInt::get(T_sigatomic, 1));
16411642
ctx.builder.CreateStore(defer_sig, pdefer_sig);
16421643
emit_signal_fence(ctx);
16431644
return ghostValue(jl_nothing_type);
@@ -1699,7 +1700,9 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16991700
idx = ctx.builder.CreateAdd(idx, ConstantInt::get(T_size, ((jl_datatype_t*)ety)->layout->first_ptr));
17001701
}
17011702
Value *slot_addr = ctx.builder.CreateInBoundsGEP(T_prjlvalue, arrayptr, idx);
1702-
Value *load = tbaa_decorate(tbaa_ptrarraybuf, ctx.builder.CreateLoad(T_prjlvalue, slot_addr));
1703+
LoadInst *load = ctx.builder.CreateAlignedLoad(T_prjlvalue, slot_addr, sizeof(void*));
1704+
load->setAtomic(AtomicOrdering::Unordered);
1705+
tbaa_decorate(tbaa_ptrarraybuf, load);
17031706
Value *res = ctx.builder.CreateZExt(ctx.builder.CreateICmpNE(load, Constant::getNullValue(T_prjlvalue)), T_int32);
17041707
JL_GC_POP();
17051708
return mark_or_box_ccall_result(ctx, res, retboxed, rt, unionall, static_rt);

0 commit comments

Comments
 (0)