/// Hoists the necessary check for beginning and end of the induction /// encapsulated by this access function to the header. void hoistCheckToPreheader(ArraySemanticsCall CheckToHoist, SILBasicBlock *Preheader, DominanceInfo *DT) { ApplyInst *AI = CheckToHoist; SILLocation Loc = AI->getLoc(); SILBuilderWithScope Builder(Preheader->getTerminator(), AI); // Get the first induction value. auto FirstVal = Ind->getFirstValue(); // Clone the struct for the start index. auto Start = cast<SILInstruction>(CheckToHoist.getIndex()) ->clone(Preheader->getTerminator()); // Set the new start index to the first value of the induction. Start->setOperand(0, FirstVal); // Clone and fixup the load, retain sequence to the header. auto NewCheck = CheckToHoist.copyTo(Preheader->getTerminator(), DT); NewCheck->setOperand(1, Start); // Get the last induction value. auto LastVal = Ind->getLastValue(Loc, Builder); // Clone the struct for the end index. auto End = cast<SILInstruction>(CheckToHoist.getIndex()) ->clone(Preheader->getTerminator()); // Set the new end index to the last value of the induction. End->setOperand(0, LastVal); NewCheck = CheckToHoist.copyTo(Preheader->getTerminator(), DT); NewCheck->setOperand(1, End); }
/// Try to CSE the users of \p From to the users of \p To. /// The original users of \p To are passed in ToApplyWitnessUsers. /// Returns true on success. static bool tryToCSEOpenExtCall(OpenExistentialAddrInst *From, OpenExistentialAddrInst *To, ApplyWitnessPair ToApplyWitnessUsers, DominanceInfo *DA) { assert(From != To && "Can't replace instruction with itself"); ApplyInst *FromAI = nullptr; ApplyInst *ToAI = nullptr; WitnessMethodInst *FromWMI = nullptr; WitnessMethodInst *ToWMI = nullptr; std::tie(FromAI, FromWMI) = getOpenExistentialUsers(From); std::tie(ToAI, ToWMI) = ToApplyWitnessUsers; // Make sure that the OEA instruction has exactly two expected users. if (!FromAI || !ToAI || !FromWMI || !ToWMI) return false; // Make sure we are calling the same method. if (FromWMI->getMember() != ToWMI->getMember()) return false; // We are going to reuse the TO-WMI, so make sure it dominates the call site. if (!DA->properlyDominates(ToWMI, FromWMI)) return false; SILBuilder Builder(FromAI); // Make archetypes used by the ToAI available to the builder. SILOpenedArchetypesTracker OpenedArchetypesTracker(*FromAI->getFunction()); OpenedArchetypesTracker.registerUsedOpenedArchetypes(ToAI); Builder.setOpenedArchetypesTracker(&OpenedArchetypesTracker); assert(FromAI->getArguments().size() == ToAI->getArguments().size() && "Invalid number of arguments"); // Don't handle any apply instructions that involve substitutions. if (ToAI->getSubstitutions().size() != 1) return false; // Prepare the Apply args. SmallVector<SILValue, 8> Args; for (auto Op : FromAI->getArguments()) { Args.push_back(Op == From ? To : Op); } auto FnTy = ToAI->getSubstCalleeSILType(); auto ResTy = FnTy.castTo<SILFunctionType>()->getSILResult(); ApplyInst *NAI = Builder.createApply(ToAI->getLoc(), ToWMI, FnTy, ResTy, ToAI->getSubstitutions(), Args, ToAI->isNonThrowing()); FromAI->replaceAllUsesWith(NAI); FromAI->eraseFromParent(); NumOpenExtRemoved++; return true; }