//===--- SILSSAUpdater.cpp - Unstructured SSA Update Tool -----------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/SSAUpdaterImpl.h" #include "swift/Basic/Malloc.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILUndef.h" #include "swift/SILOptimizer/Utils/CFG.h" #include "swift/SILOptimizer/Utils/SILSSAUpdater.h" using namespace swift; using AvailableValsTy = llvm::DenseMap; static AvailableValsTy &getAvailVals(void *AV) { return *static_cast(AV); } void *SILSSAUpdater::allocate(unsigned Size, unsigned Align) const { return AlignedAlloc(Size, Align); } void SILSSAUpdater::deallocateSentinel(SILUndef *D) { AlignedFree(D); } SILSSAUpdater::SILSSAUpdater(SmallVectorImpl *PHIs) : AV(nullptr), PHISentinel(nullptr, deallocateSentinel), InsertedPHIs(PHIs) {} SILSSAUpdater::~SILSSAUpdater() { delete static_cast(AV); } void SILSSAUpdater::Initialize(SILType Ty) { ValType = Ty; PHISentinel = std::unique_ptr( SILUndef::getSentinelValue(Ty, this), SILSSAUpdater::deallocateSentinel); if (!AV) AV = new AvailableValsTy(); else getAvailVals(AV).clear(); } bool SILSSAUpdater::HasValueForBlock(SILBasicBlock *BB) const { return getAvailVals(AV).count(BB); } /// Indicate that a rewritten value is available in the specified block with the /// specified value. void SILSSAUpdater::AddAvailableValue(SILBasicBlock *BB, SILValue V) { getAvailVals(AV)[BB] = V; } /// Construct SSA form, materializing a value that is live at the end of the /// specified block. SILValue SILSSAUpdater::GetValueAtEndOfBlock(SILBasicBlock *BB) { return GetValueAtEndOfBlockInternal(BB); } /// Are all available values identicalTo each other. bool areIdentical(AvailableValsTy &Avails) { auto *First = dyn_cast(Avails.begin()->second); if (!First) return false; for (auto Avail : Avails) { auto *Inst = dyn_cast(Avail.second); if (!Inst) return false; if (!Inst->isIdenticalTo(First)) return false; } return true; } /// This should be called in top-down order of each def that needs its uses /// rewrited. The order that we visit uses for a given def is irrelevant. void SILSSAUpdater::RewriteUse(Operand &Op) { // Replicate function_refs to their uses. SILGen can't build phi nodes for // them and it would not make much sense anyways. if (auto *FR = dyn_cast(Op.get())) { assert(areIdentical(getAvailVals(AV)) && "The function_refs need to have the same value"); SILInstruction *User = Op.getUser(); auto *NewFR = FR->clone(User); Op.set(NewFR); return; } else if (auto *IL = dyn_cast(Op.get())) if (areIdentical(getAvailVals(AV))) { // Some llvm intrinsics don't like phi nodes as their constant inputs (e.g // ctlz). SILInstruction *User = Op.getUser(); auto *NewIL = IL->clone(User); Op.set(NewIL); return; } // Again we need to be careful here, because ssa construction (with the // existing representation) can change the operand from under us. UseWrapper UW(&Op); SILInstruction *User = Op.getUser(); SILValue NewVal = GetValueInMiddleOfBlock(User->getParent()); assert(NewVal && "Need a valid value"); ((Operand *)UW)->set((SILValue)NewVal); } /// Get the edge values from the terminator to the destination basic block. static OperandValueArrayRef getEdgeValuesForTerminator(TermInst *TI, SILBasicBlock *ToBB) { if (auto *BrInst = dyn_cast(TI)) { assert(BrInst->getDestBB() == ToBB && "Incoming edge block and phi block mismatch"); return BrInst->getArgs(); } if (auto *CondBrInst = dyn_cast(TI)) { bool IsTrueEdge = CondBrInst->getTrueBB() == ToBB; assert(((IsTrueEdge && CondBrInst->getTrueBB() == ToBB) || CondBrInst->getFalseBB() == ToBB) && "Incoming edge block and phi block mismatch"); return IsTrueEdge ? CondBrInst->getTrueArgs() : CondBrInst->getFalseArgs(); } // We need a predecessor who is capable of holding outgoing branch // arguments. llvm_unreachable("Unrecognized terminator leading to phi block"); } /// Check that the argument has the same incoming edge values as the value /// map. static bool isEquivalentPHI(SILArgument *PHI, llvm::SmallDenseMap &ValueMap) { SILBasicBlock *PhiBB = PHI->getParent(); size_t Idx = PHI->getIndex(); for (auto *PredBB : PhiBB->getPreds()) { auto DesiredVal = ValueMap[PredBB]; OperandValueArrayRef EdgeValues = getEdgeValuesForTerminator(PredBB->getTerminator(), PhiBB); if (EdgeValues[Idx] != DesiredVal) return false; } return true; } SILValue SILSSAUpdater::GetValueInMiddleOfBlock(SILBasicBlock *BB) { // If this basic block does not define a value we can just use the value // live at the end of the block. if (!HasValueForBlock(BB)) return GetValueAtEndOfBlock(BB); /// Otherwise, we have to build SSA for the value defined in this block and /// this block's predecessors. SILValue SingularValue; SmallVector, 4> PredVals; bool FirstPred = true; // SSAUpdater can modify TerminatorInst and therefore invalidate the // predecessor iterator. Find all the predecessors before the SSA update. SmallVector Preds; for (auto *PredBB: BB->getPreds()) { Preds.push_back(PredBB); } for (auto *PredBB : Preds) { SILValue PredVal = GetValueAtEndOfBlock(PredBB); PredVals.push_back(std::make_pair(PredBB, PredVal)); if (FirstPred) { SingularValue = PredVal; FirstPred = false; } else if (SingularValue != PredVal) SingularValue = SILValue(); } // Return undef for blocks with predecessor. if (PredVals.empty()) return SILUndef::get(ValType, BB->getModule()); if (SingularValue) return SingularValue; // Check if we already have an equivalent phi. if (!BB->getBBArgs().empty()) { llvm::SmallDenseMap ValueMap(PredVals.begin(), PredVals.end()); for (auto *Arg : BB->getBBArgs()) if (isEquivalentPHI(Arg, ValueMap)) return Arg; } // Create a new phi node. SILArgument *PHI(new (BB->getModule()) SILArgument(BB, ValType)); for (auto &EV : PredVals) addNewEdgeValueToBranch(EV.first->getTerminator(), BB, EV.second); if (InsertedPHIs) InsertedPHIs->push_back(PHI); return PHI; } /// SSAUpdaterTraits - Traits for the SSAUpdaterImpl /// template, specialized for MachineSSAUpdater. namespace llvm { template<> class SSAUpdaterTraits { public: typedef SILBasicBlock BlkT; typedef SILValue ValT; typedef SILArgument PhiT; typedef SILBasicBlock::succ_iterator BlkSucc_iterator; static BlkSucc_iterator BlkSucc_begin(BlkT *BB) { return BB->succ_begin(); } static BlkSucc_iterator BlkSucc_end(BlkT *BB) { return BB->succ_end(); } /// Iterator over the arguments (phis) of a basic block. /// Defines an implicit cast operator on the iterator. So that this iterator /// can be used in the SSAUpdaterImpl. class PhiIt { private: SILBasicBlock::bbarg_iterator It; public: explicit PhiIt(SILBasicBlock *B) // begin iterator : It(B->bbarg_begin()) {} PhiIt(SILBasicBlock *B, bool) // end iterator : It(B->bbarg_end()) {} PhiIt &operator++() { ++It; return *this; } operator SILArgument *() { return *It; } bool operator==(const PhiIt& x) const { return It == x.It; } bool operator!=(const PhiIt& x) const { return !operator==(x); } }; typedef PhiIt PhiItT; static PhiItT PhiItT_begin(BlkT *BB) { return PhiIt(BB); } static PhiItT PhiItT_end(BlkT *BB) { return PhiIt(BB, true); } /// Iterator for PHI operands. class PHI_iterator { private: SILBasicBlock::pred_iterator PredIt; SILBasicBlock *BB; size_t Idx; public: explicit PHI_iterator(SILArgument *P) // begin iterator : PredIt(P->getParent()->pred_begin()), BB(P->getParent()), Idx(P->getIndex()) {} PHI_iterator(SILArgument *P, bool) // end iterator : PredIt(P->getParent()->pred_end()), BB(P->getParent()), Idx(P->getIndex()) {} PHI_iterator &operator++() { ++PredIt; return *this; } bool operator==(const PHI_iterator& x) const { return PredIt == x.PredIt; } bool operator!=(const PHI_iterator& x) const { return !operator==(x); } SILValue getValueForBlock(size_t Idx, SILBasicBlock *BB, TermInst *TI) { OperandValueArrayRef Args = getEdgeValuesForTerminator(TI, BB); assert(Idx < Args.size() && "Not enough values on incoming edge"); return Args[Idx]; } SILValue getIncomingValue() { return getValueForBlock(Idx, BB, (*PredIt)->getTerminator()); } SILBasicBlock *getIncomingBlock() { return *PredIt; } }; static inline PHI_iterator PHI_begin(PhiT *PHI) { return PHI_iterator(PHI); } static inline PHI_iterator PHI_end(PhiT *PHI) { return PHI_iterator(PHI, true); } /// Put the predecessors of BB into the Preds vector. static void FindPredecessorBlocks(SILBasicBlock *BB, SmallVectorImpl *Preds){ for (SILBasicBlock::pred_iterator PI = BB->pred_begin(), E = BB->pred_end(); PI != E; ++PI) Preds->push_back(*PI); } static SILValue GetUndefVal(SILBasicBlock *BB, SILSSAUpdater *Updater) { return SILUndef::get(Updater->ValType, &BB->getModule()); } /// Add an Argument to the basic block. static SILValue CreateEmptyPHI(SILBasicBlock *BB, unsigned NumPreds, SILSSAUpdater *Updater) { // Add the argument to the block. SILValue PHI(new (BB->getModule()) SILArgument(BB, Updater->ValType)); // Mark all predecessor blocks with the sentinel undef value. SmallVector Preds(BB->pred_begin(), BB->pred_end()); for (auto *PredBB: Preds) { TermInst *TI = PredBB->getTerminator(); addNewEdgeValueToBranch(TI, BB, Updater->PHISentinel.get()); } return PHI; } /// Add the specified value as an operand of the PHI for the specified /// predecessor block. static void AddPHIOperand(SILArgument *PHI, SILValue Val, SILBasicBlock *Pred) { auto *PHIBB = PHI->getParent(); size_t PhiIdx = PHI->getIndex(); auto *TI = Pred->getTerminator(); changeEdgeValue(TI, PHIBB, PhiIdx, Val); } /// InstrIsPHI - Check if an instruction is a PHI. /// static SILArgument *InstrIsPHI(ValueBase *I) { SILArgument *Res = dyn_cast(I); return Res; } /// ValueIsPHI - Check if the instruction that defines the specified register /// is a PHI instruction. static SILArgument *ValueIsPHI(SILValue V, SILSSAUpdater *Updater) { return InstrIsPHI(V); } /// Like ValueIsPHI but also check if the PHI has no source /// operands, i.e., it was just added. static SILArgument *ValueIsNewPHI(SILValue Val, SILSSAUpdater *Updater) { SILArgument *PHI = ValueIsPHI(Val, Updater); if (PHI) { auto *PhiBB = PHI->getParent(); size_t PhiIdx = PHI->getIndex(); // If all predecessor edges are 'not set' this is a new phi. for (auto *PredBB : PhiBB->getPreds()) { OperandValueArrayRef Edges = getEdgeValuesForTerminator(PredBB->getTerminator(), PhiBB); assert(PhiIdx < Edges.size() && "Not enough edges!"); SILValue V = Edges[PhiIdx]; // Check for the 'not set' sentinel. if (V != Updater->PHISentinel.get()) return nullptr; } return PHI; } return nullptr; } static SILValue GetPHIValue(SILArgument *PHI) { return PHI; } }; } // End llvm namespace /// Check to see if AvailableVals has an entry for the specified BB and if so, /// return it. If not, construct SSA form by first calculating the required /// placement of PHIs and then inserting new PHIs where needed. SILValue SILSSAUpdater::GetValueAtEndOfBlockInternal(SILBasicBlock *BB){ AvailableValsTy &AvailableVals = getAvailVals(AV); auto AI = AvailableVals.find(BB); if (AI != AvailableVals.end()) return AI->second; llvm::SSAUpdaterImpl Impl(this, &AvailableVals, InsertedPHIs); return Impl.GetValue(BB); } /// \brief Construct a use wrapper. For branches we store information so that we /// can reconstruct the use after the branch has been modified. /// /// When a branch is modified existing pointers to the operand /// (ValueUseIterator) become invalid as they point to freed operands. Instead /// we store the branch's parent and the idx so that we can reconstruct the use. UseWrapper::UseWrapper(Operand *Use) { U = nullptr; Type = kRegularUse; SILInstruction *User = Use->getUser(); // Direct branch user. if (auto *Br = dyn_cast(User)) { auto Opds = User->getAllOperands(); for (unsigned i = 0, e = Opds.size(); i != e; ++i) { if (Use == &Opds[i]) { Idx = i; Type = kBranchUse; Parent = Br->getParent(); return; } } } // Conditional branch user. if (auto *Br = dyn_cast(User)) { auto Opds = User->getAllOperands(); auto NumTrueArgs = Br->getTrueArgs().size(); for (unsigned i = 0, e = Opds.size(); i != e; ++i) { if (Use == &Opds[i]) { // We treat the condition as part of the true args. if (i < NumTrueArgs + 1) { Idx = i; Type = kCondBranchUseTrue; } else { Idx = i - NumTrueArgs - 1; Type = kCondBranchUseFalse; } Parent = Br->getParent(); return; } } } U = Use; } /// Return the operand we wrap. Reconstructing branch operands. UseWrapper::operator Operand *() { switch (Type) { case kRegularUse: return U; case kBranchUse: { auto *Br = cast(Parent->getTerminator()); assert(Idx < Br->getNumArgs()); return &Br->getAllOperands()[Idx]; } case kCondBranchUseTrue: case kCondBranchUseFalse: { auto *Br = cast(Parent->getTerminator()); unsigned IdxToUse = Type == kCondBranchUseTrue ? Idx : Br->getTrueArgs().size() + 1 + Idx; assert(IdxToUse < Br->getAllOperands().size()); return &Br->getAllOperands()[IdxToUse]; } } llvm_unreachable("uninitialize use type"); } /// At least one value feeding the specified SILArgument is a Struct. Attempt to /// replace the Argument with a new Struct in the same block. /// /// When we handle more types of casts, this can become a template. /// /// ArgValues are the values feeding the specified Argument from each /// predecessor. They must be listed in order of Arg->getParent()->getPreds(). static StructInst *replaceBBArgWithStruct( SILArgument *Arg, SmallVectorImpl &ArgValues) { SILBasicBlock *PhiBB = Arg->getParent(); auto *FirstSI = dyn_cast(ArgValues[0]); if (!FirstSI) return nullptr; // Collect the BBArg index of each struct oper. // e.g. // struct(A, B) // br (B, A) // : ArgIdxForOper => {1, 0} SmallVector ArgIdxForOper; for (unsigned OperIdx : indices(FirstSI->getElements())) { bool FoundMatchingArgIdx = false; for (unsigned ArgIdx : indices(PhiBB->getBBArgs())) { SmallVectorImpl::const_iterator AVIter = ArgValues.begin(); bool TryNextArgIdx = false; for (SILBasicBlock *PredBB : PhiBB->getPreds()) { // All argument values must be StructInst. auto *PredSI = dyn_cast(*AVIter++); if (!PredSI) return nullptr; OperandValueArrayRef EdgeValues = getEdgeValuesForTerminator(PredBB->getTerminator(), PhiBB); if (EdgeValues[ArgIdx] != PredSI->getElements()[OperIdx]) { TryNextArgIdx = true; break; } } if (!TryNextArgIdx) { assert(AVIter == ArgValues.end() && "# ArgValues does not match # BB preds"); FoundMatchingArgIdx = true; ArgIdxForOper.push_back(ArgIdx); break; } } if (!FoundMatchingArgIdx) return nullptr; } SmallVector StructArgs; for (auto ArgIdx : ArgIdxForOper) StructArgs.push_back(PhiBB->getBBArg(ArgIdx)); SILBuilder Builder(PhiBB, PhiBB->begin()); return Builder.createStruct(cast(ArgValues[0])->getLoc(), Arg->getType(), StructArgs); } /// Canonicalize BB arguments, replacing argument-of-casts with /// cast-of-arguments. This only eliminates existing arguments, replacing them /// with casts. No new arguments are created. This allows downstream pattern /// detection like induction variable analysis to succeed. /// /// If Arg is replaced, return the cast instruction. Otherwise return nullptr. SILInstruction *swift::replaceBBArgWithCast(SILArgument *Arg) { SmallVector ArgValues; Arg->getIncomingValues(ArgValues); if (isa(ArgValues[0])) return replaceBBArgWithStruct(Arg, ArgValues); return nullptr; }