/// AggregateAvailableValues - Given a bunch of primitive subelement values, /// build out the right aggregate type (LoadTy) by emitting tuple and struct /// instructions as necessary. static SILValue AggregateAvailableValues(SILInstruction *Inst, SILType LoadTy, SILValue Address, ArrayRef<std::pair<SILValue, unsigned>> AvailableValues, unsigned FirstElt) { assert(LoadTy.isObject()); SILModule &M = Inst->getModule(); // Check to see if the requested value is fully available, as an aggregate. // This is a super-common case for single-element structs, but is also a // general answer for arbitrary structs and tuples as well. if (FirstElt < AvailableValues.size()) { // #Elements may be zero. SILValue FirstVal = AvailableValues[FirstElt].first; if (FirstVal.isValid() && AvailableValues[FirstElt].second == 0 && FirstVal.getType() == LoadTy) { // If the first element of this value is available, check any extra ones // before declaring success. bool AllMatch = true; for (unsigned i = 0, e = getNumSubElements(LoadTy, M); i != e; ++i) if (AvailableValues[FirstElt+i].first != FirstVal || AvailableValues[FirstElt+i].second != i) { AllMatch = false; break; } if (AllMatch) return FirstVal; } } SILBuilderWithScope B(Inst); if (TupleType *TT = LoadTy.getAs<TupleType>()) { SmallVector<SILValue, 4> ResultElts; for (unsigned EltNo : indices(TT->getElements())) { SILType EltTy = LoadTy.getTupleElementType(EltNo); unsigned NumSubElt = getNumSubElements(EltTy, M); // If we are missing any of the available values in this struct element, // compute an address to load from. SILValue EltAddr; if (anyMissing(FirstElt, NumSubElt, AvailableValues)) EltAddr = B.createTupleElementAddr(Inst->getLoc(), Address, EltNo, EltTy.getAddressType()); ResultElts.push_back(AggregateAvailableValues(Inst, EltTy, EltAddr, AvailableValues, FirstElt)); FirstElt += NumSubElt; } return B.createTuple(Inst->getLoc(), LoadTy, ResultElts); } // Extract struct elements from fully referenceable structs. if (auto *SD = getFullyReferenceableStruct(LoadTy)) { SmallVector<SILValue, 4> ResultElts; for (auto *FD : SD->getStoredProperties()) { SILType EltTy = LoadTy.getFieldType(FD, M); unsigned NumSubElt = getNumSubElements(EltTy, M); // If we are missing any of the available values in this struct element, // compute an address to load from. SILValue EltAddr; if (anyMissing(FirstElt, NumSubElt, AvailableValues)) EltAddr = B.createStructElementAddr(Inst->getLoc(), Address, FD, EltTy.getAddressType()); ResultElts.push_back(AggregateAvailableValues(Inst, EltTy, EltAddr, AvailableValues, FirstElt)); FirstElt += NumSubElt; } return B.createStruct(Inst->getLoc(), LoadTy, ResultElts); } // Otherwise, we have a simple primitive. If the value is available, use it, // otherwise emit a load of the value. auto Val = AvailableValues[FirstElt]; if (!Val.first.isValid()) return B.createLoad(Inst->getLoc(), Address); SILValue EltVal = ExtractSubElement(Val.first, Val.second, B, Inst->getLoc()); // It must be the same type as LoadTy if available. assert(EltVal.getType() == LoadTy && "Subelement types mismatch"); return EltVal; }
/// \brief Removes instructions that create the callee value if they are no /// longer necessary after inlining. static void cleanupCalleeValue(SILValue CalleeValue, ArrayRef<SILValue> CaptureArgs, ArrayRef<SILValue> FullArgs) { SmallVector<SILInstruction*, 16> InstsToDelete; for (SILValue V : FullArgs) { if (SILInstruction *I = dyn_cast<SILInstruction>(V)) if (I != CalleeValue.getDef() && isInstructionTriviallyDead(I)) InstsToDelete.push_back(I); } recursivelyDeleteTriviallyDeadInstructions(InstsToDelete, true); // Handle the case where the callee of the apply is a load instruction. if (LoadInst *LI = dyn_cast<LoadInst>(CalleeValue)) { assert(CalleeValue.getResultNumber() == 0); SILInstruction *ABI = dyn_cast<AllocBoxInst>(LI->getOperand()); assert(ABI && LI->getOperand().getResultNumber() == 1); // The load instruction must have no more uses left to erase it. if (!LI->use_empty()) return; LI->eraseFromParent(); // Look through uses of the alloc box the load is loading from to find up to // one store and up to one strong release. StoreInst *SI = nullptr; StrongReleaseInst *SRI = nullptr; for (auto UI = ABI->use_begin(), UE = ABI->use_end(); UI != UE; ++UI) { if (SI == nullptr && isa<StoreInst>(UI.getUser())) { SI = cast<StoreInst>(UI.getUser()); assert(SI->getDest() == SILValue(ABI, 1)); } else if (SRI == nullptr && isa<StrongReleaseInst>(UI.getUser())) { SRI = cast<StrongReleaseInst>(UI.getUser()); assert(SRI->getOperand() == SILValue(ABI, 0)); } else return; } // If we found a store, record its source and erase it. if (SI) { CalleeValue = SI->getSrc(); SI->eraseFromParent(); } else { CalleeValue = SILValue(); } // If we found a strong release, replace it with a strong release of the // source of the store and erase it. if (SRI) { if (CalleeValue.isValid()) SILBuilderWithScope(SRI) .emitStrongReleaseAndFold(SRI->getLoc(), CalleeValue); SRI->eraseFromParent(); } assert(ABI->use_empty()); ABI->eraseFromParent(); if (!CalleeValue.isValid()) return; } if (auto *PAI = dyn_cast<PartialApplyInst>(CalleeValue)) { assert(CalleeValue.getResultNumber() == 0); SILValue Callee = PAI->getCallee(); if (!tryDeleteDeadClosure(PAI)) return; CalleeValue = Callee; } if (auto *TTTFI = dyn_cast<ThinToThickFunctionInst>(CalleeValue)) { assert(CalleeValue.getResultNumber() == 0); SILValue Callee = TTTFI->getCallee(); if (!tryDeleteDeadClosure(TTTFI)) return; CalleeValue = Callee; } if (FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(CalleeValue)) { assert(CalleeValue.getResultNumber() == 0); if (!FRI->use_empty()) return; FRI->eraseFromParent(); } }