Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experiment with a slighly adjusted pipeline #52850

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
34 changes: 32 additions & 2 deletions src/llvm-final-gc-lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,14 @@ bool FinalLowerGC::runOnFunction(Function &F)
initAll(*F.getParent());
if (!pgcstack_getter && !adoptthread_func) {
LLVM_DEBUG(dbgs() << "FINAL GC LOWERING: Skipping function " << F.getName() << "\n");
return false;
goto verify_skip;
}

// Look for a call to 'julia.get_pgcstack'.
pgcstack = getPGCstack(F);
if (!pgcstack) {
LLVM_DEBUG(dbgs() << "FINAL GC LOWERING: Skipping function " << F.getName() << " no pgcstack\n");
return false;
goto verify_skip;
}
LLVM_DEBUG(dbgs() << "FINAL GC LOWERING: Processing function " << F.getName() << "\n");
queueRootFunc = getOrDeclare(jl_well_known::GCQueueRoot);
Expand Down Expand Up @@ -214,6 +214,36 @@ bool FinalLowerGC::runOnFunction(Function &F)
}

return true;

verify_skip:
#ifdef JL_VERIFY_PASSES
for (auto &BB : F) {
for (auto &I : make_early_inc_range(BB)) {
auto *CI = dyn_cast<CallInst>(&I);
if (!CI)
continue;

Value *callee = CI->getCalledOperand();
assert(callee);
auto IS_INTRINSIC = [](auto intrinsic) {
auto intrinsic = getOrNull(intrinsic);
if (intrinsic == callee) {
errs() << "Final-GC-lowering didn't eliminate all intrinsics'" << F.getName() << "', dumping entire module!\n\n";
errs() << *F.getParent() << "\n";
abort();
}
};
IS_INTRINSIC(newGCFrame);
IS_INTRINSIC(pushGCFrame);
IS_INTRINSIC(popGCFrame);
IS_INTRINSIC(getGCFrameSlot);
IS_INTRINSIC(GCAllocBytes);
IS_INTRINSIC(queueGCRoot);
IS_INTRINSIC(safepoint);
}
}
#endif
return false;
}

PreservedAnalyses FinalLowerGCPass::run(Function &F, FunctionAnalysisManager &AM)
Expand Down
90 changes: 62 additions & 28 deletions src/llvm-late-gc-lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,45 +1168,79 @@ State LateLowerGCFrame::LocalScan(Function &F) {
#endif
auto tracked = CountTrackedPointers(ElT, true);
if (tracked.count) {
AllocaInst *SRet = dyn_cast<AllocaInst>((CI->arg_begin()[0])->stripInBoundsOffsets());
assert(SRet);
{
SmallVector<AllocaInst *> allocas;
gbaraldi marked this conversation as resolved.
Show resolved Hide resolved
Value *SRetArg = (CI->arg_begin()[0])->stripInBoundsOffsets();
if (AllocaInst *OneSRet = dyn_cast<AllocaInst>(SRetArg)) {
allocas.push_back(OneSRet);
} else {
SmallVector<Value *> worklist;
worklist.push_back(SRetArg);
while (!worklist.empty()) {
Value *V = worklist.pop_back_val();
if (AllocaInst *Alloca = dyn_cast<AllocaInst>(V->stripInBoundsOffsets())) {
allocas.push_back(Alloca);
} else if (PHINode *Phi = dyn_cast<PHINode>(V)) {
for (Value *Incoming : Phi->incoming_values()) {
worklist.push_back(Incoming);
}
} else if (SelectInst *SI = dyn_cast<SelectInst>(SRetArg)) {
AllocaInst *TrueSRet = dyn_cast<AllocaInst>(SI->getTrueValue());
AllocaInst *FalseSRet = dyn_cast<AllocaInst>(SI->getFalseValue());
if (TrueSRet && FalseSRet) {
worklist.push_back(TrueSRet);
worklist.push_back(FalseSRet);
} else {
llvm_dump(SI);
assert(false && "Malformed Select");
}
} else {
llvm_dump(V);
assert(false && "Unexpected SRet argument");
}
}
}
assert(allocas.size() > 0);
assert(std::all_of(allocas.begin(), allocas.end(), [&] (AllocaInst* SRetAlloca) {return (SRetAlloca->getArraySize() == allocas[0]->getArraySize() && SRetAlloca->getAllocatedType() == allocas[0]->getAllocatedType());}));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting?

for (AllocaInst *SRet : allocas) {
if (!(SRet->isStaticAlloca() && isa<PointerType>(ElT) && ElT->getPointerAddressSpace() == AddressSpace::Tracked)) {
assert(!tracked.derived);
if (tracked.all) {
S.ArrayAllocas[SRet] = tracked.count * cast<ConstantInt>(SRet->getArraySize())->getZExtValue();
}
else {
Value *arg1 = (CI->arg_begin()[1])->stripInBoundsOffsets();
AllocaInst *SRet_gc = nullptr;
if (PHINode *Phi = dyn_cast<PHINode>(arg1)) {
for (Value *V : Phi->incoming_values()) {
if (AllocaInst *Alloca = dyn_cast<AllocaInst>(V->stripInBoundsOffsets())) {
if (SRet_gc == nullptr) {
SRet_gc = Alloca;
} else if (SRet_gc == Alloca) {
continue;
} else {
llvm_dump(Alloca);
llvm_dump(SRet_gc);
assert(false && "Allocas in Phi node should match");
}
SmallVector<AllocaInst *> gc_allocas;
SmallVector<Value*> worklist;
worklist.push_back(arg1);
while (!worklist.empty()) {
Value *V = worklist.pop_back_val();
if (AllocaInst *Alloca = dyn_cast<AllocaInst>(V->stripInBoundsOffsets())) {
gc_allocas.push_back(Alloca);
} else if (PHINode *Phi = dyn_cast<PHINode>(V)) {
for (Value *Incoming : Phi->incoming_values()) {
worklist.push_back(Incoming);
}
} else if (SelectInst *SI = dyn_cast<SelectInst>(arg1)) {
AllocaInst *TrueSRet = dyn_cast<AllocaInst>(SI->getTrueValue());
AllocaInst *FalseSRet = dyn_cast<AllocaInst>(SI->getFalseValue());
if (TrueSRet && FalseSRet) {
worklist.push_back(TrueSRet);
worklist.push_back(FalseSRet);
Comment on lines +1230 to +1232
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if TrueSRet == FalseSRet but it hasn't been eliminated yet?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the solution is to make gc_allocas a set instead of a smallvector. So if we end up pushing the same thing twice that's still fine

} else {
llvm_dump(V->stripInBoundsOffsets());
assert(false && "Expected alloca");
llvm_dump(SI);
assert(false && "Malformed Select");
}
} else {
llvm_dump(V);
assert(false && "Unexpected SRet argument");
}
} else {
SRet_gc = dyn_cast<AllocaInst>(arg1);
}
if (!SRet_gc) {
llvm_dump(CI);
llvm_dump(arg1);
assert(false && "Expected alloca");
}
Type *ElT = SRet_gc->getAllocatedType();
if (!(SRet_gc->isStaticAlloca() && isa<PointerType>(ElT) && ElT->getPointerAddressSpace() == AddressSpace::Tracked)) {
S.ArrayAllocas[SRet_gc] = tracked.count * cast<ConstantInt>(SRet_gc->getArraySize())->getZExtValue();

assert(gc_allocas.size() > 0);
assert(std::all_of(gc_allocas.begin(), gc_allocas.end(), [&] (AllocaInst* SRetAlloca) {return (SRetAlloca->getArraySize() == gc_allocas[0]->getArraySize() && SRetAlloca->getAllocatedType() == gc_allocas[0]->getAllocatedType());}));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting

for (AllocaInst *SRet_gc : gc_allocas) {
if (!(SRet_gc->isStaticAlloca() && isa<PointerType>(ElT) && ElT->getPointerAddressSpace() == AddressSpace::Tracked))
S.ArrayAllocas[SRet_gc] = tracked.count * cast<ConstantInt>(SRet_gc->getArraySize())->getZExtValue();
}
}
}
Expand Down
Loading