Skip to content

Commit

Permalink
late-gc-lowering: Prevent infinite recursion (JuliaLang#42445)
Browse files Browse the repository at this point in the history
Phi nodes are allowed to recursively depend on themselves, so
we need to keep track of which ones we have seen to avoid an
infinite recursion here. Apparently this doesn't usually come
up, but I did see if with tsan enabled.
  • Loading branch information
Keno authored and LilithHafner committed Feb 22, 2022
1 parent f9fadd3 commit f49671b
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
3 changes: 2 additions & 1 deletion src/llvm-final-gc-lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,11 @@ bool FinalLowerGC::doInitialization(Module &M) {

bool FinalLowerGC::doFinalization(Module &M)
{
GlobalValue *functionList[] = {queueRootFunc, poolAllocFunc, bigAllocFunc};
queueRootFunc = poolAllocFunc = bigAllocFunc = nullptr;
auto used = M.getGlobalVariable("llvm.compiler.used");
if (!used)
return false;
GlobalValue *functionList[] = {queueRootFunc, poolAllocFunc, bigAllocFunc};
SmallPtrSet<Constant*, 16> InitAsSet(
functionList,
functionList + sizeof(functionList) / sizeof(void*));
Expand Down
25 changes: 17 additions & 8 deletions src/llvm-late-gc-lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1153,12 +1153,14 @@ static bool isConstGV(GlobalVariable *gv)
return gv->isConstant() || gv->getMetadata("julia.constgv");
}

static bool isLoadFromConstGV(LoadInst *LI, bool &task_local);
static bool isLoadFromConstGV(Value *v, bool &task_local)
typedef llvm::SmallPtrSet<PHINode*, 1> PhiSet;

static bool isLoadFromConstGV(LoadInst *LI, bool &task_local, PhiSet *seen = nullptr);
static bool isLoadFromConstGV(Value *v, bool &task_local, PhiSet *seen = nullptr)
{
v = v->stripInBoundsOffsets();
if (auto LI = dyn_cast<LoadInst>(v))
return isLoadFromConstGV(LI, task_local);
return isLoadFromConstGV(LI, task_local, seen);
if (auto gv = dyn_cast<GlobalVariable>(v))
return isConstGV(gv);
// null pointer
Expand All @@ -1169,12 +1171,19 @@ static bool isLoadFromConstGV(Value *v, bool &task_local)
return (CE->getOpcode() == Instruction::IntToPtr &&
isa<ConstantData>(CE->getOperand(0)));
if (auto SL = dyn_cast<SelectInst>(v))
return (isLoadFromConstGV(SL->getTrueValue(), task_local) &&
isLoadFromConstGV(SL->getFalseValue(), task_local));
return (isLoadFromConstGV(SL->getTrueValue(), task_local, seen) &&
isLoadFromConstGV(SL->getFalseValue(), task_local, seen));
if (auto Phi = dyn_cast<PHINode>(v)) {
PhiSet ThisSet(&Phi, &Phi);
if (!seen)
seen = &ThisSet;
else if (seen->count(Phi))
return true;
else
seen->insert(Phi);
auto n = Phi->getNumIncomingValues();
for (unsigned i = 0; i < n; ++i) {
if (!isLoadFromConstGV(Phi->getIncomingValue(i), task_local)) {
if (!isLoadFromConstGV(Phi->getIncomingValue(i), task_local, seen)) {
return false;
}
}
Expand Down Expand Up @@ -1206,7 +1215,7 @@ static bool isLoadFromConstGV(Value *v, bool &task_local)
//
// The white list implemented here and above in `isLoadFromConstGV(Value*)` should
// cover all the cases we and LLVM generates.
static bool isLoadFromConstGV(LoadInst *LI, bool &task_local)
static bool isLoadFromConstGV(LoadInst *LI, bool &task_local, PhiSet *seen)
{
// We only emit single slot GV in codegen
// but LLVM global merging can change the pointer operands to GEPs/bitcasts
Expand All @@ -1216,7 +1225,7 @@ static bool isLoadFromConstGV(LoadInst *LI, bool &task_local)
{"jtbaa_immut", "jtbaa_const", "jtbaa_datatype"})) {
if (gv)
return true;
return isLoadFromConstGV(load_base, task_local);
return isLoadFromConstGV(load_base, task_local, seen);
}
if (gv)
return isConstGV(gv);
Expand Down

0 comments on commit f49671b

Please sign in to comment.