Skip to content

Commit e820951

Browse files
WIP: Support statepoints with funclet EH
TODO: tests
1 parent 4468ba5 commit e820951

File tree

2 files changed

+72
-44
lines changed

2 files changed

+72
-44
lines changed

include/llvm/IR/Statepoint.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ class GCRelocateInst : public IntrinsicInst {
418418
// This takes care both of relocates for call statepoints and relocates
419419
// on normal path of invoke statepoint.
420420
if (!isa<LandingPadInst>(Token)) {
421+
assert(!cast<Instruction>(Token)->isEHPad() &&
422+
"Funclet pads don't support 1:1 relocate:statepoint mapping");
421423
return cast<Instruction>(Token);
422424
}
423425

@@ -478,13 +480,23 @@ StatepointBase<FunTy, InstructionTy, ValueTy, CallSiteTy>::getRelocates()
478480
return Result;
479481

480482
// We need to scan thorough exceptional relocations if it is invoke statepoint
481-
LandingPadInst *LandingPad =
482-
cast<InvokeInst>(getInstruction())->getLandingPadInst();
483-
484-
// Search for gc relocates that are attached to this landingpad.
485-
for (const User *LandingPadUser : LandingPad->users()) {
486-
if (auto *Relocate = dyn_cast<GCRelocateInst>(LandingPadUser))
487-
Result.push_back(Relocate);
483+
const InvokeInst *Invoke = cast<InvokeInst>(getInstruction());
484+
if (Invoke->getUnwindDest()->isLandingPad()) {
485+
LandingPadInst *LandingPad =
486+
cast<InvokeInst>(getInstruction())->getLandingPadInst();
487+
488+
// Search for gc relocates that are attached to this landingpad.
489+
for (const User *LandingPadUser : LandingPad->users()) {
490+
if (auto *Relocate = dyn_cast<GCRelocateInst>(LandingPadUser))
491+
Result.push_back(Relocate);
492+
}
493+
#ifndef NDEBUG
494+
} else {
495+
for (auto *UnwindDest : Invoke->getTransitiveUnwindDests())
496+
for (auto *U : UnwindDest->getFirstNonPHI()->users())
497+
assert(!isa<GCRelocateInst>(U) &&
498+
"Relocates on funclet EH not supported");
499+
#endif // NDEBUG
488500
}
489501
return Result;
490502
}

lib/Transforms/Scalar/RewriteStatepointsForGC.cpp

Lines changed: 53 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,18 +1404,29 @@ static void generateSpills(SpillMapTy &SpillMap, FillMapTy &FillMap,
14041404
generateSpill(Var, Var);
14051405

14061406
// Spill any necessary incoming PHI values
1407-
SmallVector<PHINode *, 8> SpilledPHIs;
1407+
MapVector<Value *, Value *> IncomingPHIValueMap;
14081408
if (CS.isInvoke() && SpillOnExceptionPath) {
14091409
auto *Invoke = cast<InvokeInst>(CS.getInstruction());
14101410
BasicBlock *Pred = Invoke->getParent();
1411-
BasicBlock *Pad = Invoke->getUnwindDest();
1412-
for (auto I = Pad->begin(); auto *PHI = dyn_cast<PHINode>(&*I); ++I) {
1413-
// Find the value to store for this PHI
1414-
Value *IncomingValue = PHI->getIncomingValueForBlock(Pred);
1415-
// Record that we're spilling this PHI.
1416-
SpilledPHIs.push_back(PHI);
1417-
// Generate the spill
1418-
generateSpill(PHI, IncomingValue);
1411+
for (BasicBlock *Pad : Invoke->getTransitiveUnwindDests<false>()) {
1412+
for (auto I = Pad->begin(); auto *PHI = dyn_cast<PHINode>(&*I); ++I) {
1413+
// Find the value to store for this PHI
1414+
Value *IncomingValue = PHI->getIncomingValueForBlock(Pred);
1415+
// If the incoming value was itself a PHI we've walked over,
1416+
// recurse to that incoming value
1417+
auto MapIter = IncomingPHIValueMap.find(IncomingValue);
1418+
if (MapIter != IncomingPHIValueMap.end())
1419+
IncomingValue = MapIter->second;
1420+
// Record the incoming value in case we see a use of it in
1421+
// a subsequent PHI.
1422+
IncomingPHIValueMap[PHI] = IncomingValue;
1423+
// Generate the spill
1424+
generateSpill(PHI, IncomingValue);
1425+
}
1426+
// Update pred if we're going to visit this block's successors,
1427+
// which we'll do iff it's unsplittable.
1428+
if (isa<TerminatorInst>(Pad->getFirstNonPHI()))
1429+
Pred = Pad;
14191430
}
14201431
}
14211432

@@ -1452,11 +1463,12 @@ static void generateSpills(SpillMapTy &SpillMap, FillMapTy &FillMap,
14521463
generateFill(Var, &*Pad->getFirstInsertionPt());
14531464
};
14541465
auto *Invoke = cast<InvokeInst>(CS.getInstruction());
1455-
BasicBlock *Pad = Invoke->getUnwindDest();
1456-
for (Value *Var : LiveVec)
1457-
ensureFill(Var, Pad);
1458-
for (auto *PHI : SpilledPHIs)
1459-
ensureFill(PHI, Pad);
1466+
for (BasicBlock *Pad : Invoke->getTransitiveUnwindDests()) {
1467+
for (Value *Var : LiveVec)
1468+
ensureFill(Var, Pad);
1469+
for (const auto &IncomingValuePair : IncomingPHIValueMap)
1470+
ensureFill(IncomingValuePair.first, Pad);
1471+
}
14601472
}
14611473

14621474
// If we've spilled on all paths, we don't need to generate any relocates,
@@ -1562,21 +1574,24 @@ makeStatepointExplicitImpl(const CallSite CS, /* to replace */
15621574
if (SpillOnExceptionPath) {
15631575
Result.UnwindToken = nullptr;
15641576
} else {
1565-
BasicBlock *UnwindBlock = ToReplace->getUnwindDest();
1566-
assert(!isa<PHINode>(UnwindBlock->begin()) &&
1567-
UnwindBlock->getUniquePredecessor() &&
1568-
"can't safely insert in this block!");
1569-
1570-
Builder.SetInsertPoint(&*UnwindBlock->getFirstInsertionPt());
1571-
Builder.SetCurrentDebugLocation(ToReplace->getDebugLoc());
1572-
1573-
// Attach exceptional gc relocates to the landingpad.
1574-
Instruction *ExceptionalToken = UnwindBlock->getLandingPadInst();
1575-
Result.UnwindToken = ExceptionalToken;
1576-
1577-
const unsigned LiveStartIdx = Statepoint(Token).gcPtrsStartIdx();
1578-
CreateGCRelocates(LiveVariables, LiveStartIdx, BasePtrs, ExceptionalToken,
1579-
Builder);
1577+
for (BasicBlock *UnwindBlock : ToReplace->getTransitiveUnwindDests()) {
1578+
assert(!isa<PHINode>(UnwindBlock->begin()) &&
1579+
UnwindBlock->getUniquePredecessor() &&
1580+
"can't safely insert in this block!");
1581+
1582+
Builder.SetInsertPoint(&*UnwindBlock->getFirstInsertionPt());
1583+
Builder.SetCurrentDebugLocation(ToReplace->getDebugLoc());
1584+
1585+
// Attach exceptional gc relocates to the landingpad.
1586+
Instruction *ExceptionalToken = UnwindBlock->getLandingPadInst();
1587+
assert(Result.UnwindToken == nullptr &&
1588+
"Cannot report multiple unwind tokens");
1589+
Result.UnwindToken = ExceptionalToken;
1590+
1591+
const unsigned LiveStartIdx = Statepoint(Token).gcPtrsStartIdx();
1592+
CreateGCRelocates(LiveVariables, LiveStartIdx, BasePtrs,
1593+
ExceptionalToken, Builder);
1594+
}
15801595
}
15811596

15821597
// Generate gc relocates and returns for normal block
@@ -1868,7 +1883,8 @@ static void relocationViaAlloca(
18681883
// gc.results and gc.relocates, but that's fine.
18691884
if (auto II = dyn_cast<InvokeInst>(Statepoint)) {
18701885
InsertClobbersAt(&*II->getNormalDest()->getFirstInsertionPt());
1871-
InsertClobbersAt(&*II->getUnwindDest()->getFirstInsertionPt());
1886+
for (BasicBlock *UnwindDest : II->getTransitiveUnwindDests())
1887+
InsertClobbersAt(&*UnwindDest->getFirstInsertionPt());
18721888
} else {
18731889
InsertClobbersAt(cast<Instruction>(Statepoint)->getNextNode());
18741890
}
@@ -2149,16 +2165,16 @@ static void rematerializeLiveValues(CallSite CS,
21492165

21502166
Instruction *NormalInsertBefore =
21512167
&*Invoke->getNormalDest()->getFirstInsertionPt();
2152-
Instruction *UnwindInsertBefore =
2153-
&*Invoke->getUnwindDest()->getFirstInsertionPt();
2154-
21552168
Instruction *NormalRematerializedValue =
21562169
rematerializeChain(NormalInsertBefore);
2157-
Instruction *UnwindRematerializedValue =
2158-
rematerializeChain(UnwindInsertBefore);
2159-
21602170
Info.RematerializedValues[NormalRematerializedValue] = LiveValue;
2161-
Info.RematerializedValues[UnwindRematerializedValue] = LiveValue;
2171+
2172+
for (BasicBlock *UnwindDest : Invoke->getTransitiveUnwindDests()) {
2173+
Instruction *UnwindInsertBefore = &*UnwindDest->getFirstInsertionPt();
2174+
Instruction *UnwindRematerializedValue =
2175+
rematerializeChain(UnwindInsertBefore);
2176+
Info.RematerializedValues[UnwindRematerializedValue] = LiveValue;
2177+
}
21622178
}
21632179
}
21642180

0 commit comments

Comments
 (0)