Skip to content

Commit 0051c47

Browse files
committed
Create tbaa_gcframe and decorate all stores and loads from the GC frame with it
Close #13301
1 parent 4d5f00a commit 0051c47

File tree

2 files changed

+65
-13
lines changed

2 files changed

+65
-13
lines changed

src/codegen.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ static Type *T_pppint8;
262262
static Type *T_void;
263263

264264
// type-based alias analysis nodes. Indentation of comments indicates hierarchy.
265+
static MDNode *tbaa_gcframe; // GC frame
265266
static MDNode *tbaa_user; // User data that is mutable
266267
static MDNode *tbaa_immut; // User data inside a heap-allocated immutable
267268
static MDNode *tbaa_value; // Julia value
@@ -3503,7 +3504,8 @@ static void allocate_gc_frame(BasicBlock *b0, jl_codectx_t *ctx)
35033504
#endif
35043505
}
35053506

3506-
void jl_codegen_finalize_temp_arg(CallInst *ptlsStates, Type *T_pjlvalue);
3507+
void jl_codegen_finalize_temp_arg(CallInst *ptlsStates, Type *T_pjlvalue,
3508+
MDNode *tbaa_gcframe);
35073509
static void finalize_gc_frame(Function *F)
35083510
{
35093511
Module *M = F->getParent();
@@ -3525,7 +3527,7 @@ static void finalize_gc_frame(Function *F)
35253527
if (!ptlsStates)
35263528
return;
35273529

3528-
jl_codegen_finalize_temp_arg(ptlsStates, T_pjlvalue);
3530+
jl_codegen_finalize_temp_arg(ptlsStates, T_pjlvalue, tbaa_gcframe);
35293531

35303532
#ifdef JULIA_ENABLE_THREADING
35313533
if (imaging_mode) {
@@ -4891,6 +4893,7 @@ extern "C" void jl_fptr_to_llvm(jl_fptr_t fptr, jl_lambda_info_t *lam, int specs
48914893
static void init_julia_llvm_env(Module *m)
48924894
{
48934895
MDNode *tbaa_root = mbuilder->createTBAARoot("jtbaa");
4896+
tbaa_gcframe = tbaa_make_child("jtbaa_gcframe",tbaa_root);
48944897
tbaa_user = tbaa_make_child("jtbaa_user",tbaa_root);
48954898
tbaa_value = tbaa_make_child("jtbaa_value",tbaa_root);
48964899
tbaa_immut = tbaa_make_child("jtbaa_immut",tbaa_root);

src/llvm-gcroot.cpp

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <vector>
1717
#include <queue>
18+
#include <set>
1819

1920
#include "julia.h"
2021

@@ -36,7 +37,7 @@ static struct {
3637

3738
class JuliaGCAllocator {
3839
public:
39-
JuliaGCAllocator(CallInst *ptlsStates, Type *T_pjlvalue) :
40+
JuliaGCAllocator(CallInst *ptlsStates, Type *T_pjlvalue, MDNode *tbaa) :
4041
F(*ptlsStates->getParent()->getParent()),
4142
M(*F.getParent()),
4243
T_int32(Type::getInt32Ty(F.getContext())),
@@ -47,7 +48,8 @@ class JuliaGCAllocator {
4748
gcroot_func(M.getFunction("julia.gc_root_decl")),
4849
gckill_func(M.getFunction("julia.gc_root_kill")),
4950
gc_store_func(M.getFunction("julia.gc_store")),
50-
jlcall_frame_func(M.getFunction("julia.jlcall_frame_decl"))
51+
jlcall_frame_func(M.getFunction("julia.jlcall_frame_decl")),
52+
tbaa_gcframe(tbaa)
5153
{
5254
/* Algorithm sketch:
5355
* Compute liveness for each basic block
@@ -74,6 +76,7 @@ Function *const gcroot_func;
7476
Function *const gckill_func;
7577
Function *const gc_store_func;
7678
Function *const jlcall_frame_func;
79+
MDNode *tbaa_gcframe;
7780

7881
typedef std::pair<CallInst*, unsigned> frame_register;
7982
class liveness {
@@ -90,6 +93,42 @@ class liveness {
9093
};
9194
};
9295

96+
void tbaa_decorate_gcframe(Instruction *inst, std::set<Instruction*> &visited)
97+
{
98+
if (visited.find(inst) != visited.end())
99+
return;
100+
visited.insert(inst);
101+
#ifdef LLVM35
102+
Value::user_iterator I = inst->user_begin(), E = inst->user_end();
103+
#else
104+
Value::use_iterator I = inst->use_begin(), E = inst->use_end();
105+
#endif
106+
for (;I != E;++I) {
107+
Instruction *user = dyn_cast<Instruction>(*I);
108+
if (!user) {
109+
continue;
110+
} else if (isa<GetElementPtrInst>(user)) {
111+
if (__likely(user->getOperand(0) == inst)) {
112+
tbaa_decorate_gcframe(user, visited);
113+
}
114+
} else if (isa<StoreInst>(user)) {
115+
if (user->getOperand(1) == inst) {
116+
user->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe);
117+
}
118+
} else if (isa<LoadInst>(user)) {
119+
user->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe);
120+
} else if (isa<BitCastInst>(user)) {
121+
tbaa_decorate_gcframe(user, visited);
122+
}
123+
}
124+
}
125+
126+
void tbaa_decorate_gcframe(Instruction *inst)
127+
{
128+
std::set<Instruction*> visited;
129+
tbaa_decorate_gcframe(inst, visited);
130+
}
131+
93132
#ifndef NDEBUG // llvm assertions build
94133
// gdb debugging code for inspecting the bb_uses map
95134
void jl_dump_bb_uses(std::map<BasicBlock*, std::map<frame_register, liveness::id> > &bb_uses)
@@ -655,6 +694,7 @@ void allocate_frame()
655694
// finalize all of the jlcall frames by replacing all of the frames with the appropriate gep(tempslot)
656695
for (std::map<CallInst*, unsigned>::iterator frame = frame_offsets.begin(), framee = frame_offsets.end(); frame != framee; ++frame) {
657696
CallInst *gcroot = frame->first;
697+
tbaa_decorate_gcframe(gcroot);
658698
Value* offset[1] = {ConstantInt::get(T_int32, frame->second)};
659699
GetElementPtrInst *gep = GetElementPtrInst::Create(LLVM37_param(NULL) tempSlot, makeArrayRef(offset));
660700
gep->insertAfter(last_gcframe_inst);
@@ -714,11 +754,13 @@ void allocate_frame()
714754
}
715755
}
716756
#endif
757+
tbaa_decorate_gcframe(callInst);
717758
callInst->replaceAllUsesWith(argTempi);
718759
argTempi->takeName(callInst);
719760
callInst->eraseFromParent();
720761
// Initialize the slots for function variables to NULL
721762
StoreInst *store = new StoreInst(V_null, argTempi);
763+
store->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe);
722764
store->insertAfter(argTempi);
723765
last_gcframe_inst = store;
724766
}
@@ -744,6 +786,7 @@ void allocate_frame()
744786
Instruction *argTempi = GetElementPtrInst::Create(LLVM37_param(NULL) tempSlot, ArrayRef<Value*>(ConstantInt::get(T_int32, i)));
745787
argTempi->insertAfter(last_gcframe_inst);
746788
StoreInst *store = new StoreInst(V_null, argTempi);
789+
store->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe);
747790
store->insertAfter(argTempi);
748791
last_gcframe_inst = store;
749792
}
@@ -763,10 +806,13 @@ void allocate_frame()
763806
DebugLoc noDbg;
764807
builder.SetCurrentDebugLocation(noDbg);
765808

766-
builder.CreateStore(ConstantInt::get(T_size, (argSpaceSize + maxDepth) << 1),
767-
builder.CreateBitCast(builder.CreateConstGEP1_32(gcframe, 0), T_size->getPointerTo()));
768-
builder.CreateStore(builder.CreateLoad(builder.Insert(get_pgcstack(ptlsStates))),
769-
builder.CreatePointerCast(builder.CreateConstGEP1_32(gcframe, 1), PointerType::get(T_ppjlvalue,0)));
809+
Instruction *inst =
810+
builder.CreateStore(ConstantInt::get(T_size, (argSpaceSize + maxDepth) << 1),
811+
builder.CreateBitCast(builder.CreateConstGEP1_32(gcframe, 0), T_size->getPointerTo()));
812+
inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe);
813+
inst = builder.CreateStore(builder.CreateLoad(builder.Insert(get_pgcstack(ptlsStates))),
814+
builder.CreatePointerCast(builder.CreateConstGEP1_32(gcframe, 1), PointerType::get(T_ppjlvalue,0)));
815+
inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe);
770816
builder.CreateStore(gcframe, builder.Insert(get_pgcstack(ptlsStates)));
771817

772818
// Finish by emitting the gc pops before any return
@@ -775,9 +821,11 @@ void allocate_frame()
775821
builder.SetInsertPoint(I->getTerminator()); // set insert *before* Ret
776822
Instruction *gcpop =
777823
(Instruction*)builder.CreateConstGEP1_32(gcframe, 1);
778-
builder.CreateStore(builder.CreatePointerCast(builder.CreateLoad(gcpop),
779-
T_ppjlvalue),
780-
builder.Insert(get_pgcstack(ptlsStates)));
824+
inst = builder.CreateLoad(gcpop);
825+
inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe);
826+
inst = builder.CreateStore(builder.CreatePointerCast(inst, T_ppjlvalue),
827+
builder.Insert(get_pgcstack(ptlsStates)));
828+
inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe);
781829
}
782830
}
783831
}
@@ -791,8 +839,9 @@ void allocate_frame()
791839

792840
};
793841

794-
void jl_codegen_finalize_temp_arg(CallInst *ptlsStates, Type *T_pjlvalue)
842+
void jl_codegen_finalize_temp_arg(CallInst *ptlsStates, Type *T_pjlvalue,
843+
MDNode *tbaa)
795844
{
796-
JuliaGCAllocator allocator(ptlsStates, T_pjlvalue);
845+
JuliaGCAllocator allocator(ptlsStates, T_pjlvalue, tbaa);
797846
allocator.allocate_frame();
798847
}

0 commit comments

Comments
 (0)