/// 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; }