void MemorySSAUpdater::wireOldPredecessorsToNewImmediatePredecessor( BasicBlock *Old, BasicBlock *New, ArrayRef<BasicBlock *> Preds) { assert(!MSSA->getWritableBlockAccesses(New) && "Access list should be null for a new block."); MemoryPhi *Phi = MSSA->getMemoryAccess(Old); if (!Phi) return; if (pred_size(Old) == 1) { assert(pred_size(New) == Preds.size() && "Should have moved all predecessors."); MSSA->moveTo(Phi, New, MemorySSA::Beginning); } else { assert(!Preds.empty() && "Must be moving at least one predecessor to the " "new immediate predecessor."); MemoryPhi *NewPhi = MSSA->createMemoryPhi(New); SmallPtrSet<BasicBlock *, 16> PredsSet(Preds.begin(), Preds.end()); Phi->unorderedDeleteIncomingIf([&](MemoryAccess *MA, BasicBlock *B) { if (PredsSet.count(B)) { NewPhi->addIncoming(MA, B); return true; } return false; }); Phi->addIncoming(NewPhi, New); if (onlySingleValue(NewPhi)) removeMemoryAccess(NewPhi); } }
// This is the marker algorithm from "Simple and Efficient Construction of // Static Single Assignment Form" // The simple, non-marker algorithm places phi nodes at any join // Here, we place markers, and only place phi nodes if they end up necessary. // They are only necessary if they break a cycle (IE we recursively visit // ourselves again), or we discover, while getting the value of the operands, // that there are two or more definitions needing to be merged. // This still will leave non-minimal form in the case of irreducible control // flow, where phi nodes may be in cycles with themselves, but unnecessary. MemoryAccess *MemorySSAUpdater::getPreviousDefRecursive(BasicBlock *BB) { // Single predecessor case, just recurse, we can only have one definition. if (BasicBlock *Pred = BB->getSinglePredecessor()) { return getPreviousDefFromEnd(Pred); } else if (VisitedBlocks.count(BB)) { // We hit our node again, meaning we had a cycle, we must insert a phi // node to break it so we have an operand. The only case this will // insert useless phis is if we have irreducible control flow. return MSSA->createMemoryPhi(BB); } else if (VisitedBlocks.insert(BB).second) { // Mark us visited so we can detect a cycle SmallVector<MemoryAccess *, 8> PhiOps; // Recurse to get the values in our predecessors for placement of a // potential phi node. This will insert phi nodes if we cycle in order to // break the cycle and have an operand. for (auto *Pred : predecessors(BB)) PhiOps.push_back(getPreviousDefFromEnd(Pred)); // Now try to simplify the ops to avoid placing a phi. // This may return null if we never created a phi yet, that's okay MemoryPhi *Phi = dyn_cast_or_null<MemoryPhi>(MSSA->getMemoryAccess(BB)); bool PHIExistsButNeedsUpdate = false; // See if the existing phi operands match what we need. // Unlike normal SSA, we only allow one phi node per block, so we can't just // create a new one. if (Phi && Phi->getNumOperands() != 0) if (!std::equal(Phi->op_begin(), Phi->op_end(), PhiOps.begin())) { PHIExistsButNeedsUpdate = true; } // See if we can avoid the phi by simplifying it. auto *Result = tryRemoveTrivialPhi(Phi, PhiOps); // If we couldn't simplify, we may have to create a phi if (Result == Phi) { if (!Phi) Phi = MSSA->createMemoryPhi(BB); // These will have been filled in by the recursive read we did above. if (PHIExistsButNeedsUpdate) { std::copy(PhiOps.begin(), PhiOps.end(), Phi->op_begin()); std::copy(pred_begin(BB), pred_end(BB), Phi->block_begin()); } else { unsigned i = 0; for (auto *Pred : predecessors(BB)) Phi->addIncoming(PhiOps[i++], Pred); } Result = Phi; } if (MemoryPhi *MP = dyn_cast<MemoryPhi>(Result)) InsertedPHIs.push_back(MP); // Set ourselves up for the next variable by resetting visited state. VisitedBlocks.erase(BB); return Result; } llvm_unreachable("Should have hit one of the three cases above"); }
// This is the marker algorithm from "Simple and Efficient Construction of // Static Single Assignment Form" // The simple, non-marker algorithm places phi nodes at any join // Here, we place markers, and only place phi nodes if they end up necessary. // They are only necessary if they break a cycle (IE we recursively visit // ourselves again), or we discover, while getting the value of the operands, // that there are two or more definitions needing to be merged. // This still will leave non-minimal form in the case of irreducible control // flow, where phi nodes may be in cycles with themselves, but unnecessary. MemoryAccess *MemorySSAUpdater::getPreviousDefRecursive( BasicBlock *BB, DenseMap<BasicBlock *, TrackingVH<MemoryAccess>> &CachedPreviousDef) { // First, do a cache lookup. Without this cache, certain CFG structures // (like a series of if statements) take exponential time to visit. auto Cached = CachedPreviousDef.find(BB); if (Cached != CachedPreviousDef.end()) { return Cached->second; } if (BasicBlock *Pred = BB->getSinglePredecessor()) { // Single predecessor case, just recurse, we can only have one definition. MemoryAccess *Result = getPreviousDefFromEnd(Pred, CachedPreviousDef); CachedPreviousDef.insert({BB, Result}); return Result; } if (VisitedBlocks.count(BB)) { // We hit our node again, meaning we had a cycle, we must insert a phi // node to break it so we have an operand. The only case this will // insert useless phis is if we have irreducible control flow. MemoryAccess *Result = MSSA->createMemoryPhi(BB); CachedPreviousDef.insert({BB, Result}); return Result; } if (VisitedBlocks.insert(BB).second) { // Mark us visited so we can detect a cycle SmallVector<TrackingVH<MemoryAccess>, 8> PhiOps; // Recurse to get the values in our predecessors for placement of a // potential phi node. This will insert phi nodes if we cycle in order to // break the cycle and have an operand. for (auto *Pred : predecessors(BB)) PhiOps.push_back(getPreviousDefFromEnd(Pred, CachedPreviousDef)); // Now try to simplify the ops to avoid placing a phi. // This may return null if we never created a phi yet, that's okay MemoryPhi *Phi = dyn_cast_or_null<MemoryPhi>(MSSA->getMemoryAccess(BB)); // See if we can avoid the phi by simplifying it. auto *Result = tryRemoveTrivialPhi(Phi, PhiOps); // If we couldn't simplify, we may have to create a phi if (Result == Phi) { if (!Phi) Phi = MSSA->createMemoryPhi(BB); // See if the existing phi operands match what we need. // Unlike normal SSA, we only allow one phi node per block, so we can't just // create a new one. if (Phi->getNumOperands() != 0) { // FIXME: Figure out whether this is dead code and if so remove it. if (!std::equal(Phi->op_begin(), Phi->op_end(), PhiOps.begin())) { // These will have been filled in by the recursive read we did above. std::copy(PhiOps.begin(), PhiOps.end(), Phi->op_begin()); std::copy(pred_begin(BB), pred_end(BB), Phi->block_begin()); } } else { unsigned i = 0; for (auto *Pred : predecessors(BB)) Phi->addIncoming(&*PhiOps[i++], Pred); InsertedPHIs.push_back(Phi); } Result = Phi; } // Set ourselves up for the next variable by resetting visited state. VisitedBlocks.erase(BB); CachedPreviousDef.insert({BB, Result}); return Result; } llvm_unreachable("Should have hit one of the three cases above"); }