Index: lib/Transforms/Scalar/PlaceSafepoints.cpp =================================================================== --- lib/Transforms/Scalar/PlaceSafepoints.cpp +++ lib/Transforms/Scalar/PlaceSafepoints.cpp @@ -521,6 +521,23 @@ static bool enableBackedgeSafepoints(Function &F) { return !NoBackedge; } static bool enableCallSafepoints(Function &F) { return !NoCall; } +// Normalize basic block to make it ready to be target of invoke statepoint. +// Ensure that 'BB' does not have phi nodes. It may require spliting it. +static BasicBlock *normalizeForInvokeSafepoint(BasicBlock *BB, + BasicBlock *InvokeParent) { + BasicBlock *ret = BB; + + if (!BB->getUniquePredecessor()) { + ret = SplitBlockPredecessors(BB, InvokeParent, ""); + } + + // Now that 'ret' has unique predecessor we can safely remove all phi nodes + // from it + FoldSingleEntryPHINodes(ret); + assert(!isa(ret->begin())); + + return ret; +} bool PlaceSafepoints::runOnFunction(Function &F) { if (F.isDeclaration() || F.empty()) { @@ -674,6 +691,17 @@ Results.reserve(ParsePointNeeded.size()); for (size_t i = 0; i < ParsePointNeeded.size(); i++) { CallSite &CS = ParsePointNeeded[i]; + + // For invoke statepoints we need to remove all phi nodes at the normal + // destination block. + // Reason for this is that we can place gc_relocate only after last phi node + // in basic block. We will get mallformed code after RAUW for the + // gc_relocate if one of this phi nodes uses result from the invoke. + if (InvokeInst *Invoke = dyn_cast(CS.getInstruction())) { + normalizeForInvokeSafepoint(Invoke->getNormalDest(), + Invoke->getParent()); + } + Value *GCResult = ReplaceWithStatepoint(CS, nullptr); Results.push_back(GCResult); } @@ -684,20 +712,8 @@ CallSite &CS = ParsePointNeeded[i]; Value *GCResult = Results[i]; if (GCResult) { - // In case if we inserted result in a different basic block than the - // original safepoint (this can happen for invokes). We need to be sure - // that - // original result value was not used in any of the phi nodes at the - // beginning of basic block with gc result. Because we know that all such - // blocks will have single predecessor we can safely assume that all phi - // nodes have single entry (because of normalizeBBForInvokeSafepoint). - // Just remove them all here. - if (CS.isInvoke()) { - FoldSingleEntryPHINodes(cast(GCResult)->getParent(), - nullptr); - assert( - !isa(cast(GCResult)->getParent()->begin())); - } + // Can not RAUW for the gc result in case of phi nodes preset. + assert(!isa(cast(GCResult)->getParent()->begin())); // Replace all uses with the new call CS.getInstruction()->replaceAllUsesWith(GCResult); @@ -842,28 +858,6 @@ assert(ParsePointsNeeded.size() <= calls.size()); } -// Normalize basic block to make it ready to be target of invoke statepoint. -// It means spliting it to have single predecessor. Return newly created BB -// ready to be successor of invoke statepoint. -static BasicBlock *normalizeBBForInvokeSafepoint(BasicBlock *BB, - BasicBlock *InvokeParent) { - BasicBlock *ret = BB; - - if (!BB->getUniquePredecessor()) { - ret = SplitBlockPredecessors(BB, InvokeParent, ""); - } - - // Another requirement for such basic blocks is to not have any phi nodes. - // Since we just ensured that new BB will have single predecessor, - // all phi nodes in it will have one value. Here it would be naturall place - // to - // remove them all. But we can not do this because we are risking to remove - // one of the values stored in liveset of another statepoint. We will do it - // later after placing all safepoints. - - return ret; -} - /// Replaces the given call site (Call or Invoke) with a gc.statepoint /// intrinsic with an empty deoptimization arguments list. This does /// NOT do explicit relocation for GC support. @@ -968,8 +962,10 @@ token = invoke; // We'll insert the gc.result into the normal block - BasicBlock *normalDest = normalizeBBForInvokeSafepoint( - toReplace->getNormalDest(), invoke->getParent()); + BasicBlock *normalDest = toReplace->getNormalDest(); + // Can not insert gc.result in case of phi nodes preset. + // Should have removed this cases prior to runnning this function + assert(!isa(normalDest->begin())); Instruction *IP = &*(normalDest->getFirstInsertionPt()); Builder.SetInsertPoint(IP); } else {