/// for this safepoint
DenseSet<llvm::Value *> NewInsertedDefs;
- /// The bounds of the inserted code for the safepoint
- std::pair<Instruction *, Instruction *> SafepointBounds;
+ /// The *new* gc.statepoint instruction itself. This produces the token
+ /// that normal path gc.relocates and the gc.result are tied to.
+ Instruction *StatepointToken;
/// Instruction to which exceptional gc relocates are attached
/// Makes it easier to iterate through them during relocationViaAlloca.
return ret;
}
-static void
-VerifySafepointBounds(const std::pair<Instruction *, Instruction *> &bounds) {
- assert(bounds.first->getParent() && bounds.second->getParent() &&
- "both must belong to basic blocks");
- if (bounds.first->getParent() == bounds.second->getParent()) {
- // This is a call safepoint
- // TODO: scan the range to find the statepoint
- // TODO: check that the following instruction is not a gc_relocate or
- // gc_result
- } else {
- // This is an invoke safepoint
- InvokeInst *invoke = dyn_cast<InvokeInst>(bounds.first);
- (void)invoke;
- assert(invoke && "only continues over invokes!");
- assert(invoke->getNormalDest() == bounds.second->getParent() &&
- "safepoint should continue into normal exit block");
- }
-}
-
static int find_index(const SmallVectorImpl<Value *> &livevec, Value *val) {
auto itr = std::find(livevec.begin(), livevec.end(), val);
assert(livevec.end() != itr);
token->takeName(CS.getInstruction());
// The GCResult is already inserted, we just need to find it
- Instruction *gc_result = nullptr;
/* scope */ {
Instruction *toReplace = CS.getInstruction();
assert((toReplace->hasNUses(0) || toReplace->hasNUses(1)) &&
if (toReplace->hasOneUse()) {
Instruction *GCResult = cast<Instruction>(*toReplace->user_begin());
assert(isGCResult(GCResult));
- gc_result = GCResult;
}
}
// considered a live reference.
CS.getInstruction()->replaceAllUsesWith(token);
- // Second, create a gc.relocate for every live variable
- std::vector<llvm::Instruction *> newDefs =
- CreateGCRelocates(liveVariables, live_start, basePtrs, token, Builder);
-
- // Need to pass through the last part of the safepoint block so that we
- // don't accidentally update uses in a following gc.relocate which is
- // still conceptually part of the same safepoint. Gah.
- Instruction *last = nullptr;
- if (!newDefs.empty()) {
- last = newDefs.back();
- } else if (gc_result) {
- last = gc_result;
- } else {
- last = token;
- }
- assert(last && "can't be null");
- const auto bounds = std::make_pair(token, last);
+ result.StatepointToken = token;
- // Sanity check our results - this is slightly non-trivial due to invokes
- VerifySafepointBounds(bounds);
+ // Second, create a gc.relocate for every live variable
+ CreateGCRelocates(liveVariables, live_start, basePtrs, token, Builder);
- result.SafepointBounds = bounds;
}
namespace {
// otherwise we lose the link between statepoint and old def
for (size_t i = 0; i < records.size(); i++) {
const struct PartiallyConstructedSafepointRecord &info = records[i];
- Value *statepoint = info.SafepointBounds.first;
+ Value *Statepoint = info.StatepointToken;
// This will be used for consistency check
DenseSet<Value *> visitedLiveValues;
// Insert stores for normal statepoint gc relocates
- insertRelocationStores(statepoint->users(), allocaMap, visitedLiveValues);
+ insertRelocationStores(Statepoint->users(), allocaMap, visitedLiveValues);
// In case if it was invoke statepoint
// we will insert stores for exceptional path gc relocates.
- if (isa<InvokeInst>(statepoint)) {
+ if (isa<InvokeInst>(Statepoint)) {
insertRelocationStores(info.UnwindToken->users(),
allocaMap, visitedLiveValues);
}
ToClobber.push_back(Alloca);
}
- Instruction *Statepoint = info.SafepointBounds.first;
auto InsertClobbersAt = [&](Instruction *IP) {
for (auto *AI : ToClobber) {
auto AIType = cast<PointerType>(AI->getType());
// nodes have single entry (because of normalizeBBForInvokeSafepoint).
// Just remove them all here.
for (size_t i = 0; i < records.size(); i++) {
- Instruction *I = records[i].SafepointBounds.first;
+ Instruction *I = records[i].StatepointToken;
if (InvokeInst *invoke = dyn_cast<InvokeInst>(I)) {
FoldSingleEntryPHINodes(invoke->getNormalDest());
// That Value* no longer exists and we need to use the new gc_result.
// Thankfully, the liveset is embedded in the statepoint (and updated), so
// we just grab that.
- Statepoint statepoint(info.SafepointBounds.first);
+ Statepoint statepoint(info.StatepointToken);
live.insert(live.end(), statepoint.gc_args_begin(),
statepoint.gc_args_end());
}