Skip to content

Commit dd6b125

Browse files
committed
codegen: simplify GEP emission calls
Rewrite our complex GEP emission to use a simple emit_ptrgep call since it should be equivalent now that opaque pointers are required.
1 parent 527fa1c commit dd6b125

9 files changed

+123
-286
lines changed

src/ccall.cpp

+4-7
Original file line numberDiff line numberDiff line change
@@ -1822,8 +1822,8 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
18221822
ctx.builder.SetInsertPoint(checkBB);
18231823
auto signal_page_load = ctx.builder.CreateLoad(
18241824
ctx.types().T_size,
1825-
ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_size,
1826-
get_current_signal_page_from_ptls(ctx.builder, ctx.types().T_size, get_current_ptls(ctx), ctx.tbaa().tbaa_const), -1),
1825+
emit_ptrgep(ctx, get_current_signal_page_from_ptls(ctx.builder, get_current_ptls(ctx), ctx.tbaa().tbaa_const),
1826+
-sizeof(size_t)),
18271827
true);
18281828
setName(ctx.emission_context, signal_page_load, "signal_page_load");
18291829
ctx.builder.CreateBr(contBB);
@@ -1838,8 +1838,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
18381838
auto obj = emit_pointer_from_objref(ctx, boxed(ctx, argv[0])); // T_pprjlvalue
18391839
// The inbounds gep makes it more clear to LLVM that the resulting value is not
18401840
// a null pointer.
1841-
auto strp = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, obj, 1);
1842-
setName(ctx.emission_context, strp, "string_ptr");
1841+
auto strp = emit_ptrgep(ctx, obj, ctx.types().sizeof_ptr, "string_ptr");
18431842
JL_GC_POP();
18441843
return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
18451844
}
@@ -1850,9 +1849,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
18501849
auto obj = emit_pointer_from_objref(ctx, boxed(ctx, argv[0])); // T_pprjlvalue
18511850
// The inbounds gep makes it more clear to LLVM that the resulting value is not
18521851
// a null pointer.
1853-
auto strp = ctx.builder.CreateConstInBoundsGEP1_32(
1854-
ctx.types().T_prjlvalue, obj, (sizeof(jl_sym_t) + sizeof(void*) - 1) / sizeof(void*));
1855-
setName(ctx.emission_context, strp, "symbol_name");
1852+
auto strp = emit_ptrgep(ctx, obj, sizeof(jl_sym_t), "symbol_name");
18561853
JL_GC_POP();
18571854
return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
18581855
}

src/cgutils.cpp

+36-90
Large diffs are not rendered by default.

src/codegen.cpp

+53-70
Large diffs are not rendered by default.

src/intrinsics.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, ArrayRef<jl_cgval_t> argv)
767767
LLT_ALIGN(size, jl_datatype_align(ety))));
768768
setName(ctx.emission_context, im1, "pointerref_offset");
769769
Value *thePtr = emit_unbox(ctx, getPointerTy(ctx.builder.getContext()), e, e.typ);
770-
thePtr = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), thePtr, im1);
770+
thePtr = emit_ptrgep(ctx, thePtr, im1);
771771
setName(ctx.emission_context, thePtr, "pointerref_src");
772772
MDNode *tbaa = best_tbaa(ctx.tbaa(), ety);
773773
emit_memcpy(ctx, strct, jl_aliasinfo_t::fromTBAA(ctx, tbaa), thePtr, jl_aliasinfo_t::fromTBAA(ctx, nullptr), size, Align(sizeof(jl_value_t*)), Align(align_nb));
@@ -848,7 +848,7 @@ static jl_cgval_t emit_pointerset(jl_codectx_t &ctx, ArrayRef<jl_cgval_t> argv)
848848
im1 = ctx.builder.CreateMul(im1, ConstantInt::get(ctx.types().T_size,
849849
LLT_ALIGN(size, jl_datatype_align(ety))));
850850
setName(ctx.emission_context, im1, "pointerset_offset");
851-
auto gep = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), thePtr, im1);
851+
auto gep = emit_ptrgep(ctx, thePtr, im1);
852852
setName(ctx.emission_context, gep, "pointerset_ptr");
853853
emit_memcpy(ctx, gep, jl_aliasinfo_t::fromTBAA(ctx, nullptr), x, size, Align(align_nb), Align(julia_alignment(ety)));
854854
}

src/llvm-alloc-opt.cpp

+1-20
Original file line numberDiff line numberDiff line change
@@ -770,26 +770,7 @@ void Optimizer::moveToStack(CallInst *orig_inst, size_t sz, bool has_ref, AllocF
770770
user->replaceUsesOfWith(orig_i, replace);
771771
}
772772
else if (isa<AddrSpaceCastInst>(user) || isa<BitCastInst>(user)) {
773-
#if JL_LLVM_VERSION >= 170000
774-
#ifndef JL_NDEBUG
775-
auto cast_t = PointerType::get(user->getType(), new_i->getType()->getPointerAddressSpace());
776-
Type *new_t = new_i->getType();
777-
assert(cast_t == new_t);
778-
#endif
779-
auto replace_i = new_i;
780-
#else
781-
auto cast_t = PointerType::getWithSamePointeeType(cast<PointerType>(user->getType()), new_i->getType()->getPointerAddressSpace());
782-
auto replace_i = new_i;
783-
Type *new_t = new_i->getType();
784-
if (cast_t != new_t) {
785-
// Shouldn't get here when using opaque pointers, so the new BitCastInst is fine
786-
assert(cast_t->getContext().supportsTypedPointers());
787-
replace_i = new BitCastInst(replace_i, cast_t, "", user);
788-
replace_i->setDebugLoc(user->getDebugLoc());
789-
replace_i->takeName(user);
790-
}
791-
#endif
792-
push_frame(user, replace_i);
773+
push_frame(user, new_i);
793774
}
794775
else if (auto gep = dyn_cast<GetElementPtrInst>(user)) {
795776
SmallVector<Value *, 4> IdxOperands(gep->idx_begin(), gep->idx_end());

src/llvm-codegen-shared.h

+19-26
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ struct CountTrackedPointers {
125125
CountTrackedPointers(llvm::Type *T, bool ignore_loaded=false);
126126
};
127127

128-
unsigned TrackWithShadow(llvm::Value *Src, llvm::Type *T, bool isptr, llvm::Value *Dst, llvm::Type *DTy, llvm::IRBuilder<> &irbuilder);
128+
unsigned TrackWithShadow(llvm::Value *Src, llvm::Type *T, bool isptr, llvm::Value *Dst, llvm::IRBuilder<> &irbuilder);
129129
llvm::SmallVector<llvm::Value*, 0> ExtractTrackedValues(llvm::Value *Src, llvm::Type *STy, bool isptr, llvm::IRBuilder<> &irbuilder, llvm::ArrayRef<unsigned> perm_offsets={});
130130

131131
static inline void llvm_dump(llvm::Value *v)
@@ -187,45 +187,39 @@ static inline llvm::Instruction *tbaa_decorate(llvm::MDNode *md, llvm::Instructi
187187
}
188188

189189
// Get PTLS through current task.
190-
static inline llvm::Value *get_current_task_from_pgcstack(llvm::IRBuilder<> &builder, llvm::Type *T_size, llvm::Value *pgcstack)
190+
static inline llvm::Value *get_current_task_from_pgcstack(llvm::IRBuilder<> &builder, llvm::Value *pgcstack)
191191
{
192192
using namespace llvm;
193-
auto T_pjlvalue = JuliaType::get_pjlvalue_ty(builder.getContext());
193+
auto i8 = builder.getInt8Ty();
194194
const int pgcstack_offset = offsetof(jl_task_t, gcstack);
195-
return builder.CreateInBoundsGEP(
196-
T_pjlvalue, pgcstack,
197-
ConstantInt::get(T_size, -(pgcstack_offset / sizeof(void *))),
198-
"current_task");
195+
return builder.CreateConstInBoundsGEP1_32(i8, pgcstack, -pgcstack_offset, "current_task");
199196
}
200197

201198
// Get PTLS through current task.
202-
static inline llvm::Value *get_current_ptls_from_task(llvm::IRBuilder<> &builder, llvm::Type *T_size, llvm::Value *current_task, llvm::MDNode *tbaa)
199+
static inline llvm::Value *get_current_ptls_from_task(llvm::IRBuilder<> &builder, llvm::Value *current_task, llvm::MDNode *tbaa)
203200
{
204201
using namespace llvm;
205-
auto T_pjlvalue = JuliaType::get_pjlvalue_ty(builder.getContext());
202+
auto i8 = builder.getInt8Ty();
203+
auto T_ptr = builder.getPtrTy();
206204
const int ptls_offset = offsetof(jl_task_t, ptls);
207-
llvm::Value *pptls = builder.CreateInBoundsGEP(
208-
T_pjlvalue, current_task,
209-
ConstantInt::get(T_size, ptls_offset / sizeof(void *)),
210-
"ptls_field");
211-
LoadInst *ptls_load = builder.CreateAlignedLoad(T_pjlvalue,
212-
pptls, Align(sizeof(void *)), "ptls_load");
205+
llvm::Value *pptls = builder.CreateConstInBoundsGEP1_32(i8, current_task, ptls_offset, "ptls_field");
206+
LoadInst *ptls_load = builder.CreateAlignedLoad(T_ptr, pptls, Align(sizeof(void *)), "ptls_load");
213207
// Note: Corresponding store (`t->ptls = ptls`) happens in `ctx_switch` of tasks.c.
214208
tbaa_decorate(tbaa, ptls_load);
215209
return ptls_load;
216210
}
217211

218212
// Get signal page through current task.
219-
static inline llvm::Value *get_current_signal_page_from_ptls(llvm::IRBuilder<> &builder, llvm::Type *T_size, llvm::Value *ptls, llvm::MDNode *tbaa)
213+
static inline llvm::Value *get_current_signal_page_from_ptls(llvm::IRBuilder<> &builder, llvm::Value *ptls, llvm::MDNode *tbaa)
220214
{
221215
using namespace llvm;
222216
// return builder.CreateCall(prepare_call(reuse_signal_page_func));
223-
auto T_psize = T_size->getPointerTo();
224-
int nthfield = offsetof(jl_tls_states_t, safepoint) / sizeof(void *);
225-
llvm::Value *psafepoint = builder.CreateInBoundsGEP(
226-
T_psize, ptls, ConstantInt::get(T_size, nthfield));
217+
auto T_ptr = builder.getPtrTy();
218+
auto i8 = builder.getInt8Ty();
219+
int nthfield = offsetof(jl_tls_states_t, safepoint);
220+
llvm::Value *psafepoint = builder.CreateConstInBoundsGEP1_32(i8, ptls, nthfield);
227221
LoadInst *ptls_load = builder.CreateAlignedLoad(
228-
T_psize, psafepoint, Align(sizeof(void *)), "safepoint");
222+
T_ptr, psafepoint, Align(sizeof(void *)), "safepoint");
229223
tbaa_decorate(tbaa, ptls_load);
230224
return ptls_load;
231225
}
@@ -239,7 +233,7 @@ static inline void emit_signal_fence(llvm::IRBuilder<> &builder)
239233
static inline void emit_gc_safepoint(llvm::IRBuilder<> &builder, llvm::Type *T_size, llvm::Value *ptls, llvm::MDNode *tbaa, bool final = false)
240234
{
241235
using namespace llvm;
242-
llvm::Value *signal_page = get_current_signal_page_from_ptls(builder, T_size, ptls, tbaa);
236+
llvm::Value *signal_page = get_current_signal_page_from_ptls(builder, ptls, tbaa);
243237
emit_signal_fence(builder);
244238
Module *M = builder.GetInsertBlock()->getModule();
245239
LLVMContext &C = builder.getContext();
@@ -250,8 +244,7 @@ static inline void emit_gc_safepoint(llvm::IRBuilder<> &builder, llvm::Type *T_s
250244
else {
251245
Function *F = M->getFunction("julia.safepoint");
252246
if (!F) {
253-
auto T_psize = T_size->getPointerTo();
254-
FunctionType *FT = FunctionType::get(Type::getVoidTy(C), {T_psize}, false);
247+
FunctionType *FT = FunctionType::get(Type::getVoidTy(C), {T_size->getPointerTo()}, false);
255248
F = Function::Create(FT, Function::ExternalLinkage, "julia.safepoint", M);
256249
#if JL_LLVM_VERSION >= 160000
257250
F->setMemoryEffects(MemoryEffects::inaccessibleOrArgMemOnly());
@@ -268,8 +261,8 @@ static inline llvm::Value *emit_gc_state_set(llvm::IRBuilder<> &builder, llvm::T
268261
{
269262
using namespace llvm;
270263
Type *T_int8 = state->getType();
271-
Constant *offset = ConstantInt::getSigned(builder.getInt32Ty(), offsetof(jl_tls_states_t, gc_state));
272-
Value *gc_state = builder.CreateInBoundsGEP(T_int8, ptls, ArrayRef<Value*>(offset), "gc_state");
264+
unsigned offset = offsetof(jl_tls_states_t, gc_state);
265+
Value *gc_state = builder.CreateConstInBoundsGEP1_32(T_int8, ptls, offset, "gc_state");
273266
if (old_state == nullptr) {
274267
old_state = builder.CreateLoad(T_int8, gc_state);
275268
cast<LoadInst>(old_state)->setOrdering(AtomicOrdering::Monotonic);

src/llvm-late-gc-lowering.cpp

+4-68
Original file line numberDiff line numberDiff line change
@@ -350,15 +350,7 @@ void LateLowerGCFrame::LiftSelect(State &S, SelectInst *SI) {
350350
ConstantInt::get(Type::getInt32Ty(Cond->getContext()), i),
351351
"", SI);
352352
}
353-
#if JL_LLVM_VERSION >= 170000
354353
assert(FalseElem->getType() == TrueElem->getType());
355-
#else
356-
if (FalseElem->getType() != TrueElem->getType()) {
357-
// Shouldn't get here when using opaque pointers, so the new BitCastInst is fine
358-
assert(FalseElem->getContext().supportsTypedPointers());
359-
FalseElem = new BitCastInst(FalseElem, TrueElem->getType(), "", SI);
360-
}
361-
#endif
362354
SelectInst *SelectBase = SelectInst::Create(Cond, TrueElem, FalseElem, "gclift", SI);
363355
int Number = ++S.MaxPtrNumber;
364356
S.AllPtrNumbering[SelectBase] = Number;
@@ -427,33 +419,7 @@ void LateLowerGCFrame::LiftPhi(State &S, PHINode *Phi) {
427419
BaseElem = Base;
428420
else
429421
BaseElem = IncomingBases[i];
430-
#if JL_LLVM_VERSION >= 170000
431422
assert(BaseElem->getType() == T_prjlvalue);
432-
#else
433-
if (BaseElem->getType() != T_prjlvalue) {
434-
// Shouldn't get here when using opaque pointers, so the new BitCastInst is fine
435-
assert(BaseElem->getContext().supportsTypedPointers());
436-
auto &remap = CastedRoots[i][BaseElem];
437-
if (!remap) {
438-
if (auto constant = dyn_cast<Constant>(BaseElem)) {
439-
remap = ConstantExpr::getBitCast(constant, T_prjlvalue, "");
440-
} else {
441-
Instruction *InsertBefore;
442-
if (auto arg = dyn_cast<Argument>(BaseElem)) {
443-
InsertBefore = &*arg->getParent()->getEntryBlock().getFirstInsertionPt();
444-
} else {
445-
assert(isa<Instruction>(BaseElem) && "Unknown value type detected!");
446-
InsertBefore = cast<Instruction>(BaseElem)->getNextNonDebugInstruction();
447-
}
448-
while (isa<PHINode>(InsertBefore)) {
449-
InsertBefore = InsertBefore->getNextNonDebugInstruction();
450-
}
451-
remap = new BitCastInst(BaseElem, T_prjlvalue, "", InsertBefore);
452-
}
453-
}
454-
BaseElem = remap;
455-
}
456-
#endif
457423
lift->addIncoming(BaseElem, IncomingBB);
458424
}
459425
}
@@ -1528,14 +1494,11 @@ SmallVector<Value*, 0> ExtractTrackedValues(Value *Src, Type *STy, bool isptr, I
15281494
return Ptrs;
15291495
}
15301496

1531-
unsigned TrackWithShadow(Value *Src, Type *STy, bool isptr, Value *Dst, Type *DTy, IRBuilder<> &irbuilder) {
1497+
unsigned TrackWithShadow(Value *Src, Type *STy, bool isptr, Value *Dst, IRBuilder<> &irbuilder) {
15321498
auto Ptrs = ExtractTrackedValues(Src, STy, isptr, irbuilder);
15331499
for (unsigned i = 0; i < Ptrs.size(); ++i) {
1534-
Value *Elem = Ptrs[i];// Dst has type `[n x {}*]*`
1535-
Value *Slot = irbuilder.CreateConstInBoundsGEP2_32(DTy, Dst, 0, i);
1536-
#if JL_LLVM_VERSION < 170000
1537-
assert(cast<PointerType>(Dst->getType())->isOpaqueOrPointeeTypeMatches(DTy));
1538-
#endif
1500+
Value *Elem = Ptrs[i];
1501+
Value *Slot = irbuilder.CreateConstInBoundsGEP1_32(irbuilder.getInt8Ty(), Dst, i * sizeof(void*));
15391502
StoreInst *shadowStore = irbuilder.CreateAlignedStore(Elem, Slot, Align(sizeof(void*)));
15401503
shadowStore->setOrdering(AtomicOrdering::NotAtomic);
15411504
// TODO: shadowStore->setMetadata(LLVMContext::MD_tbaa, tbaa_gcframe);
@@ -2133,7 +2096,7 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S, bool *CFGModified) {
21332096
// the type tag. (Note that if the size is not a constant, it will call
21342097
// gc_alloc_obj, and will redundantly set the tag.)
21352098
auto allocBytesIntrinsic = getOrDeclare(jl_intrinsics::GCAllocBytes);
2136-
auto ptls = get_current_ptls_from_task(builder, T_size, CI->getArgOperand(0), tbaa_gcframe);
2099+
auto ptls = get_current_ptls_from_task(builder, CI->getArgOperand(0), tbaa_gcframe);
21372100
auto newI = builder.CreateCall(
21382101
allocBytesIntrinsic,
21392102
{
@@ -2319,15 +2282,7 @@ void LateLowerGCFrame::PlaceGCFrameStore(State &S, unsigned R, unsigned MinColor
23192282
// Pointee types don't have semantics, so the optimizer is
23202283
// free to rewrite them if convenient. We need to change
23212284
// it back here for the store.
2322-
#if JL_LLVM_VERSION >= 170000
23232285
assert(Val->getType() == T_prjlvalue);
2324-
#else
2325-
if (Val->getType() != T_prjlvalue) {
2326-
// Shouldn't get here when using opaque pointers, so the new BitCastInst is fine
2327-
assert(Val->getContext().supportsTypedPointers());
2328-
Val = new BitCastInst(Val, T_prjlvalue, "", InsertBefore);
2329-
}
2330-
#endif
23312286
new StoreInst(Val, slotAddress, InsertBefore);
23322287
}
23332288

@@ -2407,18 +2362,7 @@ void LateLowerGCFrame::PlaceRootsAndUpdateCalls(SmallVectorImpl<int> &Colors, St
24072362
for (CallInst *II : ToDelete) {
24082363
II->eraseFromParent();
24092364
}
2410-
#if JL_LLVM_VERSION >= 170000
24112365
assert(slotAddress->getType() == AI->getType());
2412-
#else
2413-
if (slotAddress->getType() != AI->getType()) {
2414-
// If we're replacing an ArrayAlloca, the pointer element type may need to be fixed up
2415-
// Shouldn't get here when using opaque pointers, so the new BitCastInst is fine
2416-
assert(slotAddress->getContext().supportsTypedPointers());
2417-
auto BCI = new BitCastInst(slotAddress, AI->getType());
2418-
BCI->insertAfter(slotAddress);
2419-
slotAddress = BCI;
2420-
}
2421-
#endif
24222366
AI->replaceAllUsesWith(slotAddress);
24232367
AI->eraseFromParent();
24242368
AI = NULL;
@@ -2443,15 +2387,7 @@ void LateLowerGCFrame::PlaceRootsAndUpdateCalls(SmallVectorImpl<int> &Colors, St
24432387
slotAddress->insertAfter(gcframe);
24442388
auto ValExpr = std::make_pair(Base, isa<PointerType>(Base->getType()) ? -1 : i);
24452389
auto Elem = MaybeExtractScalar(S, ValExpr, SI);
2446-
#if JL_LLVM_VERSION >= 170000
24472390
assert(Elem->getType() == T_prjlvalue);
2448-
#else
2449-
if (Elem->getType() != T_prjlvalue) {
2450-
// Shouldn't get here when using opaque pointers, so the new BitCastInst is fine
2451-
assert(Elem->getContext().supportsTypedPointers());
2452-
Elem = new BitCastInst(Elem, T_prjlvalue, "", SI);
2453-
}
2454-
#endif
24552391
//auto Idxs = ArrayRef<unsigned>(Tracked[i]);
24562392
//Value *Elem = ExtractScalar(Base, true, Idxs, SI);
24572393
Value *shadowStore = new StoreInst(Elem, slotAddress, SI);

src/llvm-ptls.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ void LowerPTLS::fix_pgcstack_use(CallInst *pgcstack, Function *pgcstack_getter,
191191
builder.SetInsertPoint(fastTerm->getParent());
192192
fastTerm->removeFromParent();
193193
MDNode *tbaa = tbaa_gcframe;
194-
Value *prior = emit_gc_unsafe_enter(builder, T_size, get_current_ptls_from_task(builder, T_size, get_current_task_from_pgcstack(builder, T_size, pgcstack), tbaa), true);
194+
Value *prior = emit_gc_unsafe_enter(builder, T_size, get_current_ptls_from_task(builder, get_current_task_from_pgcstack(builder, pgcstack), tbaa), true);
195195
builder.Insert(fastTerm);
196196
phi->addIncoming(pgcstack, fastTerm->getParent());
197197
// emit pre-return cleanup
@@ -203,7 +203,7 @@ void LowerPTLS::fix_pgcstack_use(CallInst *pgcstack, Function *pgcstack_getter,
203203
for (auto &BB : *pgcstack->getParent()->getParent()) {
204204
if (isa<ReturnInst>(BB.getTerminator())) {
205205
builder.SetInsertPoint(BB.getTerminator());
206-
emit_gc_unsafe_leave(builder, T_size, get_current_ptls_from_task(builder, T_size, get_current_task_from_pgcstack(builder, T_size, phi), tbaa), last_gc_state, true);
206+
emit_gc_unsafe_leave(builder, T_size, get_current_ptls_from_task(builder, get_current_task_from_pgcstack(builder, phi), tbaa), last_gc_state, true);
207207
}
208208
}
209209
}

test/llvmpasses/names.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ emit(f2, Float64, Float64, Float64, Float64, Float64, Float64, Float64)
135135

136136
# CHECK: define {{(swiftcc )?}}nonnull ptr @julia_f5
137137
# CHECK-SAME: %"a::A"
138-
# CHECK: %"a::A.b_ptr.c_ptr.d
138+
# CHECK: %"a::A.d
139+
# COM: this text check relies on our LLVM code emission being relatively poor, which is not always the case
139140
emit(f5, A)
140141

141142
# CHECK: define {{(swiftcc )?}}nonnull ptr @julia_f6

0 commit comments

Comments
 (0)