ApplySite SILPerformanceInliner::specializeGeneric( ApplySite Apply, llvm::SmallVectorImpl<ApplySite> &NewApplies) { assert(NewApplies.empty() && "Expected out parameter for new applies!"); if (!Apply.hasSubstitutions()) return ApplySite(); auto *Callee = Apply.getCalleeFunction(); if (!Callee || Callee->isExternalDeclaration()) return ApplySite(); auto Filter = [](SILInstruction *I) -> bool { return ApplySite::isa(I) != ApplySite(); }; CloneCollector Collector(Filter); SILFunction *SpecializedFunction; auto Specialized = trySpecializeApplyOfGeneric(Apply, SpecializedFunction, Collector); if (!Specialized) return ApplySite(); // Track the new applies from the specialization. for (auto NewCallSite : Collector.getInstructionPairs()) NewApplies.push_back(ApplySite(NewCallSite.first)); auto FullApply = FullApplySite::isa(Apply.getInstruction()); if (!FullApply) { assert(!FullApplySite::isa(Specialized.getInstruction()) && "Unexpected full apply generated!"); // Replace the old apply with the new and delete the old. replaceDeadApply(Apply, Specialized.getInstruction()); return ApplySite(Specialized); } // Replace the old apply with the new and delete the old. replaceDeadApply(Apply, Specialized.getInstruction()); return Specialized; }
bool GenericSpecializer::specializeAppliesInFunction(SILFunction &F) { bool Changed = false; llvm::SmallVector<SILInstruction *, 8> DeadApplies; for (auto &BB : F) { for (auto It = BB.begin(), End = BB.end(); It != End;) { auto &I = *It++; // Skip non-apply instructions, apply instructions with no // substitutions, apply instructions where we do not statically // know the called function, and apply instructions where we do // not have the body of the called function. ApplySite Apply = ApplySite::isa(&I); if (!Apply || !Apply.hasSubstitutions()) continue; auto *Callee = Apply.getCalleeFunction(); if (!Callee || !Callee->isDefinition()) continue; // We have a call that can potentially be specialized, so // attempt to do so. // The specializer helper function currently expects a collector // argument, but we aren't going to make use of the results so // we'll have our filter always return false; auto Filter = [](SILInstruction *I) -> bool { return false; }; CloneCollector Collector(Filter); SILFunction *SpecializedFunction; auto Specialized = trySpecializeApplyOfGeneric(Apply, SpecializedFunction, Collector); if (Specialized) { Changed = true; // If calling the specialization utility resulted in a new // function (as opposed to returning a previous // specialization), we need to notify the pass manager so that // the new function gets optimized. if (SpecializedFunction) notifyPassManagerOfFunction(SpecializedFunction); auto *AI = Apply.getInstruction(); if (!isa<TryApplyInst>(AI)) AI->replaceAllUsesWith(Specialized.getInstruction()); DeadApplies.push_back(AI); } } } // Remove all the now-dead applies. while (!DeadApplies.empty()) { auto *AI = DeadApplies.pop_back_val(); recursivelyDeleteTriviallyDeadInstructions(AI, true); } return Changed; }
bool GenericSpecializer::specializeAppliesInFunction(SILFunction &F) { DeadInstructionSet DeadApplies; llvm::SmallSetVector<SILInstruction *, 8> Applies; bool Changed = false; for (auto &BB : F) { // Collect the applies for this block in reverse order so that we // can pop them off the end of our vector and process them in // forward order. for (auto It = BB.rbegin(), End = BB.rend(); It != End; ++It) { auto *I = &*It; // Skip non-apply instructions, apply instructions with no // substitutions, apply instructions where we do not statically // know the called function, and apply instructions where we do // not have the body of the called function. ApplySite Apply = ApplySite::isa(I); if (!Apply || !Apply.hasSubstitutions()) continue; auto *Callee = Apply.getReferencedFunction(); if (!Callee || !Callee->isDefinition()) continue; Applies.insert(Apply.getInstruction()); } // Attempt to specialize each apply we collected, deleting any // that we do specialize (along with other instructions we clone // in the process of doing so). We pop from the end of the list to // avoid tricky iterator invalidation issues. while (!Applies.empty()) { auto *I = Applies.pop_back_val(); auto Apply = ApplySite::isa(I); assert(Apply && "Expected an apply!"); SILFunction *Callee = Apply.getReferencedFunction(); assert(Callee && "Expected to have a known callee"); // We have a call that can potentially be specialized, so // attempt to do so. llvm::SmallVector<SILFunction *, 2> NewFunctions; trySpecializeApplyOfGeneric(Apply, DeadApplies, NewFunctions); // Remove all the now-dead applies. We must do this immediately // rather than defer it in order to avoid problems with cloning // dead instructions when doing recursive specialization. while (!DeadApplies.empty()) { auto *AI = DeadApplies.pop_back_val(); // Remove any applies we are deleting so that we don't attempt // to specialize them. Applies.remove(AI); recursivelyDeleteTriviallyDeadInstructions(AI, true); Changed = true; } // If calling the specialization utility resulted in new functions // (as opposed to returning a previous specialization), we need to notify // the pass manager so that the new functions get optimized. for (SILFunction *NewF : reverse(NewFunctions)) { notifyPassManagerOfFunction(NewF, Callee); } } } return Changed; }