31#define DEBUG_TYPE "iroutliner"
58 cl::desc(
"Enable the IR outliner on linkonceodr functions"),
65 cl::desc(
"Debug option to outline greedily, without restriction that "
66 "calculated benefit outweighs cost"));
158 TargetBB.
splice(TargetBB.
end(), &SourceBB);
168 for (
auto &VtoBB : Map)
169 SortedKeys.push_back(VtoBB.first);
173 if (SortedKeys.size() == 1) {
174 assert(!SortedKeys[0] &&
"Expected a single void value.");
189 std::optional<unsigned> GVN =
Candidate->getGVN(V);
190 assert(GVN &&
"No GVN for incoming value");
191 std::optional<unsigned> CanonNum =
Candidate->getCanonicalNum(*GVN);
192 std::optional<unsigned> FirstGVN =
193 Other.Candidate->fromCanonicalNum(*CanonNum);
194 std::optional<Value *> FoundValueOpt =
Other.Candidate->fromGVN(*FirstGVN);
195 return FoundValueOpt.value_or(
nullptr);
202 assert(FirstNonPHI &&
"block is empty?");
204 if (!CorrespondingVal)
208 return CorrespondingBlock;
225 for (
unsigned Idx = 0, PNEnd = PN.getNumIncomingValues(); Idx != PNEnd;
234 assert(BI &&
"Not a branch instruction?");
263 assert(EndInst &&
"Expected an end instruction?");
274 assert(StartInst &&
"Expected a start instruction?");
292 bool EndBBTermAndBackInstDifferent =
EndBB->getTerminator() != BackInst;
294 unsigned NumPredsOutsideRegion = 0;
295 for (
unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
296 if (!BBSet.
contains(PN->getIncomingBlock(i))) {
297 PHIPredBlock = PN->getIncomingBlock(i);
298 ++NumPredsOutsideRegion;
305 IBlock = PN->getIncomingBlock(i);
306 if (IBlock ==
EndBB && EndBBTermAndBackInstDifferent) {
307 PHIPredBlock = PN->getIncomingBlock(i);
308 ++NumPredsOutsideRegion;
312 if (NumPredsOutsideRegion > 1)
326 BackInst != &*std::prev(
EndBB->getFirstInsertionPt()))
344 std::string OriginalName =
PrevBB->getName().str();
346 StartBB =
PrevBB->splitBasicBlock(StartInst, OriginalName +
"_to_outline");
351 PrevBB->replaceSuccessorsPhiUsesWith(PHIPredBlock,
PrevBB);
356 FollowBB =
EndBB->splitBasicBlock(EndInst, OriginalName +
"_after_outline");
392 assert(
StartBB !=
nullptr &&
"StartBB for Candidate is not defined!");
394 assert(
PrevBB->getTerminator() &&
"Terminator removed from PrevBB!");
410 "PrevBB has more than one predecessor. Should be 0 or 1.");
412 PrevBB->replaceSuccessorsPhiUsesWith(
PrevBB, BeforePrevBB);
414 PrevBB->getTerminator()->eraseFromParent();
434 assert(
FollowBB !=
nullptr &&
"FollowBB for Candidate is not defined!");
462static std::optional<bool>
476 std::tie(GVNToConstantIt, Inserted) =
477 GVNToConstant.
insert(std::make_pair(GVN, CST));
480 if (Inserted || (GVNToConstantIt->second == CST))
503 switch (
I->getOpcode()) {
504 case Instruction::FDiv:
505 case Instruction::FRem:
506 case Instruction::SDiv:
507 case Instruction::SRem:
508 case Instruction::UDiv:
509 case Instruction::URem:
534 if (OutputMapping != OutputMappings.
end())
535 return OutputMapping->second;
552 bool ConstantsTheSame =
true;
561 std::optional<unsigned> GVNOpt =
C.getGVN(V);
562 assert(GVNOpt &&
"Expected a GVN for operand?");
563 unsigned GVN = *GVNOpt;
568 ConstantsTheSame =
false;
576 std::optional<bool> ConstantMatches =
578 if (ConstantMatches) {
579 if (*ConstantMatches)
582 ConstantsTheSame =
false;
589 ConstantsTheSame =
false;
595 return ConstantsTheSame;
629Function *IROutliner::createFunction(
Module &M, OutlinableGroup &Group,
630 unsigned FunctionNameSuffix) {
642 for (OutlinableRegion *R : Group.
Regions) {
643 Type *ExtractedFuncType =
R->ExtractedFunction->getReturnType();
646 RetTy = ExtractedFuncType;
656 "outlined_ir_func_" + std::to_string(FunctionNameSuffix), M);
661 Attribute::SwiftError);
671 DICompileUnit *CU =
SP->getUnit();
672 DIBuilder
DB(M,
true, CU);
673 DIFile *
Unit =
SP->getFile();
677 llvm::raw_string_ostream MangledNameStream(Dummy);
680 DISubprogram *OutlinedSP =
DB.createFunction(
681 Unit ,
F->getName(), Dummy, Unit ,
683 DB.createSubroutineType(
DB.getOrCreateTypeArray({})),
685 DINode::DIFlags::FlagArtificial ,
687 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
690 F->setSubprogram(OutlinedSP);
706 CurrBB.removeFromParent();
707 CurrBB.insertInto(&New);
714 NewEnds.
insert(std::make_pair(RI->getReturnValue(), &CurrBB));
721 Val.dropDbgRecords();
736 Loc->getColumn(), SP,
nullptr);
762 std::vector<unsigned> &Inputs) {
766 for (IRInstructionDataList::iterator IDIt =
C.begin(), EndIDIt =
C.end();
767 IDIt != EndIDIt; IDIt++) {
768 for (
Value *V : (*IDIt).OperVals) {
771 unsigned GVN = *
C.getGVN(V);
774 Inputs.push_back(GVN);
792 std::vector<unsigned> &EndInputNumbers) {
799 if (It != OutputMappings.
end())
801 assert(
C.getGVN(
Input) &&
"Could not find a numbering for the given input");
802 EndInputNumbers.push_back(*
C.getGVN(
Input));
822 if (It != OutputMappings.
end())
867 CE->findInputsOutputs(OverallInputs, DummyOutputs, SinkCands);
868 assert(
Region.StartBB &&
"Region must have a start BasicBlock!");
875 if (!CE->isEligible()) {
876 Region.IgnoreRegion =
true;
881 CE->findAllocas(CEAC, SinkCands, HoistCands, Dummy);
882 CE->findInputsOutputs(PremappedInputs, Outputs, SinkCands);
889 if (OverallInputs.
size() != PremappedInputs.
size()) {
890 Region.IgnoreRegion =
true;
918 std::vector<unsigned> &InputGVNs,
925 unsigned TypeIndex = 0;
928 unsigned OriginalIndex = 0;
939 for (
unsigned InputVal : InputGVNs) {
940 std::optional<unsigned> CanonicalNumberOpt =
C.getCanonicalNum(InputVal);
941 assert(CanonicalNumberOpt &&
"Canonical number not found?");
942 unsigned CanonicalNumber = *CanonicalNumberOpt;
944 std::optional<Value *> InputOpt =
C.fromGVN(InputVal);
945 assert(InputOpt &&
"Global value number not found?");
955 if (
Input->isSwiftError()) {
958 "Argument already marked with swifterr for this OutlinableGroup!");
967 Region.AggArgToConstant.insert(std::make_pair(AggArgIt->second, CST));
970 std::make_pair(CanonicalNumber, TypeIndex));
971 Region.AggArgToConstant.insert(std::make_pair(TypeIndex, CST));
982 if (OriginalIndex != AggArgIt->second)
983 Region.ChangedArgOrder =
true;
984 Region.ExtractedArgToAgg.insert(
985 std::make_pair(OriginalIndex, AggArgIt->second));
986 Region.AggArgToExtracted.insert(
987 std::make_pair(AggArgIt->second, OriginalIndex));
990 std::make_pair(CanonicalNumber, TypeIndex));
991 Region.ExtractedArgToAgg.insert(std::make_pair(OriginalIndex, TypeIndex));
992 Region.AggArgToExtracted.insert(std::make_pair(TypeIndex, OriginalIndex));
1007 Region.NumExtractedInputs = OriginalIndex;
1026 [PHILoc, &PN, V, &BlocksInRegion](
unsigned Idx) {
1027 return (Idx != PHILoc && V == PN.getIncomingValue(Idx) &&
1028 !BlocksInRegion.contains(PN.getIncomingBlock(Idx)));
1033 return any_of(V->users(), [&Exits, &BlocksInRegion](
User *U) {
1034 Instruction *I = dyn_cast<Instruction>(U);
1041 BasicBlock *Parent = I->getParent();
1042 if (BlocksInRegion.contains(Parent))
1048 if (!isa<PHINode>(I))
1055 if (!Exits.contains(Parent))
1082 for (
PHINode &PN : CurrentExitFromRegion->
phis()) {
1085 for (
unsigned I = 0,
E = PN.getNumIncomingValues();
I <
E; ++
I)
1086 if (RegionBlocks.
contains(PN.getIncomingBlock(
I)))
1090 unsigned NumIncomingVals = IncomingVals.
size();
1091 if (NumIncomingVals == 0)
1096 if (NumIncomingVals == 1) {
1097 Value *V = PN.getIncomingValue(*IncomingVals.
begin());
1098 OutputsWithNonPhiUses.
insert(V);
1099 OutputsReplacedByPHINode.
erase(V);
1109 for (
unsigned Idx : IncomingVals) {
1110 Value *V = PN.getIncomingValue(Idx);
1112 outputHasNonPHI(V, Idx, PN, PotentialExitsFromRegion, RegionBlocks)) {
1113 OutputsWithNonPhiUses.
insert(V);
1114 OutputsReplacedByPHINode.
erase(V);
1117 if (!OutputsWithNonPhiUses.
contains(V))
1118 OutputsReplacedByPHINode.
insert(V);
1161 unsigned AggArgIdx) {
1173 if (!Blocks.
contains(IncomingBlock))
1183 Region.IgnoreRegion =
true;
1184 return std::nullopt;
1188 unsigned GVN = *OGVN;
1190 assert(OGVN &&
"No GVN found for incoming value?");
1195 OGVN = Cand.
getGVN(IncomingBlock);
1202 "Unknown basic block used in exit path PHINode.");
1214 assert(PrevBlock &&
"Expected a predecessor not in the reigon!");
1215 OGVN = Cand.
getGVN(PrevBlock);
1219 assert(OGVN &&
"No GVN found for incoming block?");
1228 std::optional<unsigned> BBGVN = Cand.
getGVN(PHIBB);
1229 assert(BBGVN &&
"Could not find GVN for the incoming block!");
1232 assert(BBGVN &&
"Could not find canonical number for the incoming block!");
1237 std::make_pair(std::make_pair(*BBGVN, AggArgIdx), PHIGVNs);
1244 bool Inserted =
false;
1251 return GVNToPHIIt->second;
1267 C.getBasicBlocks(BlocksInRegion, BE);
1273 if (!BlocksInRegion.
contains(Succ))
1283 OutputsReplacedByPHINode,
1284 OutputsWithNonPhiUses);
1287 unsigned OriginalIndex =
Region.NumExtractedInputs;
1300 for (
Value *Output : Outputs) {
1310 if (OutputsReplacedByPHINode.
contains(Output))
1313 unsigned AggArgIdx = 0;
1314 for (
unsigned Jdx = TypeIndex; Jdx < ArgumentSize; Jdx++) {
1318 if (!AggArgsUsed.
insert(Jdx).second)
1322 Region.ExtractedArgToAgg.insert(std::make_pair(OriginalIndex, Jdx));
1323 Region.AggArgToExtracted.insert(std::make_pair(Jdx, OriginalIndex));
1333 M.getDataLayout().getAllocaAddrSpace()));
1337 AggArgsUsed.
insert(ArgTypeIdx);
1338 Region.ExtractedArgToAgg.insert(
1339 std::make_pair(OriginalIndex, ArgTypeIdx));
1340 Region.AggArgToExtracted.insert(
1341 std::make_pair(ArgTypeIdx, OriginalIndex));
1342 AggArgIdx = ArgTypeIdx;
1348 std::optional<unsigned> GVN;
1366 GVN =
C.getGVN(Output);
1367 GVN =
C.getCanonicalNum(*GVN);
1373 Region.GVNStores.push_back(*GVN);
1386 std::vector<unsigned> Inputs;
1387 SetVector<Value *> ArgInputs, Outputs;
1414 std::vector<Value *> NewCallArgs;
1419 assert(
Call &&
"Call to replace is nullptr?");
1421 assert(AggFunc &&
"Function to replace with is nullptr?");
1429 << *AggFunc <<
" with same number of arguments\n");
1430 Call->setCalledFunction(AggFunc);
1438 for (
unsigned AggArgIdx = 0; AggArgIdx < AggFunc->
arg_size(); AggArgIdx++) {
1440 if (AggArgIdx == AggFunc->
arg_size() - 1 &&
1446 <<
Region.OutputBlockNum <<
"\n");
1452 ArgPair =
Region.AggArgToExtracted.find(AggArgIdx);
1453 if (ArgPair !=
Region.AggArgToExtracted.
end()) {
1454 Value *ArgumentValue =
Call->getArgOperand(ArgPair->second);
1458 LLVM_DEBUG(
dbgs() <<
"Setting argument " << AggArgIdx <<
" to value "
1459 << *ArgumentValue <<
"\n");
1460 NewCallArgs.push_back(ArgumentValue);
1465 if (
auto It =
Region.AggArgToConstant.find(AggArgIdx);
1468 LLVM_DEBUG(
dbgs() <<
"Setting argument " << AggArgIdx <<
" to value "
1470 NewCallArgs.push_back(CST);
1477 LLVM_DEBUG(
dbgs() <<
"Setting argument " << AggArgIdx <<
" to nullptr\n");
1483 << *AggFunc <<
" with new set of arguments\n");
1486 Call->getIterator());
1493 if (
Region.NewFront->Inst == OldCall)
1495 if (
Region.NewBack->Inst == OldCall)
1499 Call->setDebugLoc(
Region.Call->getDebugLoc());
1528 auto [PhiBlockForRetVal, Inserted] = Group.
PHIBlocks.try_emplace(RetVal);
1530 return PhiBlockForRetVal->second;
1532 auto ReturnBlockForRetVal = Group.
EndBBs.find(RetVal);
1534 "Could not find output value!");
1535 BasicBlock *ReturnBB = ReturnBlockForRetVal->second;
1541 PhiBlockForRetVal->second = PHIBlock;
1553 for (
unsigned Succ = 0, End = BI->getNumSuccessors(); Succ < End; Succ++) {
1554 if (BI->getSuccessor(Succ) != ReturnBB)
1556 BI->setSuccessor(Succ, PHIBlock);
1561 return PhiBlockForRetVal->second;
1578 return Region.Call->getArgOperand(
A->getArgNo());
1591 unsigned ArgNum =
A->getArgNo();
1595 if (
auto It =
Region.AggArgToConstant.find(ArgNum);
1601 ArgNum =
Region.AggArgToExtracted.find(ArgNum)->second;
1602 return Region.Call->getArgOperand(ArgNum);
1618 SmallVector<std::pair<unsigned, BasicBlock *>> &CanonNums,
1619 bool ReplacedWithOutlinedCall =
true) {
1627 if (ReplacedWithOutlinedCall)
1637 std::optional<unsigned> GVN =
Region.Candidate->getGVN(IVal);
1638 assert(GVN &&
"No GVN for incoming value");
1639 std::optional<unsigned> CanonNum =
Region.Candidate->getCanonicalNum(*GVN);
1640 assert(CanonNum &&
"No Canonical Number for GVN");
1641 CanonNums.push_back(std::make_pair(*CanonNum, IBlock));
1692 CurrentCanonNums.
clear();
1698 if (PNCanonNums.
size() != CurrentCanonNums.
size())
1701 bool FoundMatch =
true;
1710 for (
unsigned Idx = 0, Edx = PNCanonNums.
size(); Idx < Edx; ++Idx) {
1711 std::pair<unsigned, BasicBlock *> ToCompareTo = CurrentCanonNums[Idx];
1712 std::pair<unsigned, BasicBlock *> ToAdd = PNCanonNums[Idx];
1713 if (ToCompareTo.first != ToAdd.first) {
1719 Region.findCorrespondingBlockIn(*FirstRegion, ToAdd.second);
1720 assert(CorrespondingBlock &&
"Found block is nullptr");
1721 if (CorrespondingBlock != ToCompareTo.second) {
1730 UsedPHIs.
insert(&CurrPN);
1747 Region.findCorrespondingBlockIn(*FirstRegion, IncomingBlock);
1760 Value *Val =
Region.findCorrespondingValueIn(*FirstRegion, IncomingVal);
1761 assert(Val &&
"Value is nullptr?");
1765 Val = RemappedIt->second;
1784 bool FirstFunction =
false) {
1786 assert(
Region.ExtractedFunction &&
"Region has no extracted function?");
1794 for (
unsigned ArgIdx = 0; ArgIdx <
Region.ExtractedFunction->arg_size();
1797 "No mapping from extracted to outlined?");
1798 unsigned AggArgIdx =
Region.ExtractedArgToAgg.find(ArgIdx)->second;
1803 if (ArgIdx <
Region.NumExtractedInputs) {
1804 LLVM_DEBUG(
dbgs() <<
"Replacing uses of input " << *Arg <<
" in function "
1805 << *
Region.ExtractedFunction <<
" with " << *AggArg
1809 Region.RemappedArguments.insert(std::make_pair(V, AggArg));
1818 assert(InstAsUser &&
"User is nullptr!");
1824 bool EdgeAdded =
false;
1825 if (Descendants.
size() == 0) {
1839 auto VBBIt = OutputBBs.
find(RetVal);
1840 assert(VBBIt != OutputBBs.
end() &&
"Could not find output value!");
1846 Value *ValueOperand =
SI->getValueOperand();
1853 << *OutputBB <<
"\n");
1858 Region.Candidate->getGVN(ValueOperand).has_value()) {
1862 Region.findCorrespondingValueIn(*Group.
Regions[0], ValueOperand);
1863 assert(CorrVal &&
"Value is nullptr?");
1870 if (
Region.Candidate->getGVN(PN))
1880 if (FirstFunction) {
1882 Group.
PHIBlocks.insert(std::make_pair(RetVal, PHIBlock));
1894 OutputMappings, UsedPHIs);
1902 I->eraseFromParent();
1904 LLVM_DEBUG(
dbgs() <<
"Replacing uses of output " << *Arg <<
" in function "
1905 << *
Region.ExtractedFunction <<
" with " << *AggArg
1921 for (std::pair<unsigned, Constant *> &Const :
Region.AggArgToConstant) {
1922 unsigned AggArgIdx = Const.first;
1923 assert(OutlinedFunction &&
"Overall Function is not defined?");
1930 <<
" in function " << *OutlinedFunction <<
" with "
1948 bool Mismatch =
false;
1949 unsigned MatchingNum = 0;
1955 for (std::pair<Value *, BasicBlock *> &VToB : CompBBs) {
1957 OutputBBs.
find(VToB.first);
1958 if (OutputBBIt == OutputBBs.
end()) {
1965 if (CompBB->
size() - 1 != OutputBB->
size()) {
1975 if (!
I.isIdenticalTo(&(*NIt))) {
1990 return std::nullopt;
2001 bool AllRemoved =
true;
2002 Value *RetValueForBB;
2006 for (std::pair<Value *, BasicBlock *> &VtoBB : BlocksToPrune) {
2007 RetValueForBB = VtoBB.first;
2008 NewBB = VtoBB.second;
2012 if (NewBB->
size() == 0) {
2025 BlocksToPrune.
erase(V);
2029 Region.OutputBlockNum = -1;
2059 std::optional<unsigned> MatchingBB =
2066 <<
Region.ExtractedFunction <<
" to " << *MatchingBB);
2068 Region.OutputBlockNum = *MatchingBB;
2069 for (std::pair<Value *, BasicBlock *> &VtoBB : OutputBBs)
2070 VtoBB.second->eraseFromParent();
2074 Region.OutputBlockNum = OutputStoreBBs.size();
2076 Value *RetValueForBB;
2079 for (std::pair<Value *, BasicBlock *> &VtoBB : OutputBBs) {
2080 RetValueForBB = VtoBB.first;
2081 NewBB = VtoBB.second;
2083 EndBBs.
find(RetValueForBB);
2085 <<
Region.ExtractedFunction <<
" to "
2088 OutputStoreBBs.back().insert(std::make_pair(RetValueForBB, NewBB));
2105 std::vector<Value *> SortedKeys;
2109 for (
Value *RetVal : SortedKeys) {
2113 NewMap.
insert(std::make_pair(RetVal, NewBB));
2142 for (std::pair<Value *, BasicBlock *> &RetBlockPair : ReturnBBs) {
2143 std::pair<Value *, BasicBlock *> &OutputBlock =
2144 *OG.
EndBBs.find(RetBlockPair.first);
2145 BasicBlock *ReturnBlock = RetBlockPair.second;
2150 Term->moveBefore(*ReturnBlock, ReturnBlock->
end());
2153 LLVM_DEBUG(
dbgs() <<
"Create switch statement in " << *AggFunc <<
" for "
2154 << OutputStoreBBs.
size() <<
"\n");
2157 ReturnBlock, OutputStoreBBs.
size(), EndBB);
2162 OutputStoreBB.
find(OutputBlock.first);
2164 if (OSBBIt == OutputStoreBB.
end())
2171 Term->setSuccessor(0, ReturnBlock);
2178 assert(OutputStoreBBs.size() < 2 &&
"Different store sets not handled!");
2186 if (OutputStoreBBs.size() == 1) {
2187 LLVM_DEBUG(
dbgs() <<
"Move store instructions to the end block in "
2190 for (std::pair<Value *, BasicBlock *> &VBPair : OutputBlocks) {
2192 EndBBs.
find(VBPair.first);
2193 assert(EndBBIt != EndBBs.
end() &&
"Could not find end block");
2197 Term->eraseFromParent();
2200 Term->moveBefore(*EndBB, EndBB->
end());
2222 std::vector<Function *> &FuncsToRemove,
2251 for (std::pair<Value *, BasicBlock *> &VToBB : NewBBs) {
2253 CurrentGroup.
EndBBs.find(VToBB.first);
2256 OutputStoreBBs.back().insert(VToBB);
2268void IROutliner::deduplicateExtractedSections(
2269 Module &M, OutlinableGroup &CurrentGroup,
2270 std::vector<Function *> &FuncsToRemove,
unsigned &OutlinedFunctionNum) {
2271 createFunction(M, CurrentGroup, OutlinedFunctionNum);
2273 std::vector<DenseMap<Value *, BasicBlock *>> OutputStoreBBs;
2275 OutlinableRegion *CurrentOS;
2280 for (
unsigned Idx = 1; Idx < CurrentGroup.
Regions.size(); Idx++) {
2281 CurrentOS = CurrentGroup.
Regions[Idx];
2282 AttributeFuncs::mergeAttributesForOutlining(*CurrentGroup.
OutlinedFunction,
2287 DenseMap<Value *, BasicBlock *> NewBBs;
2290 "output_block_" + Twine(Idx));
2293 CurrentGroup.
EndBBs, OutputMappings,
2303 OutlinedFunctionNum++;
2320 IRInstructionDataList::iterator NextIDIt = std::next(
ID.getIterator());
2323 if (!
ID.Inst->isTerminator())
2324 NextModuleInst =
ID.Inst->getNextNode();
2325 else if (NextIDLInst !=
nullptr)
2327 &*NextIDIt->Inst->
getParent()->instructionsWithoutDebug().begin();
2329 if (NextIDLInst && NextIDLInst != NextModuleInst)
2335bool IROutliner::isCompatibleWithAlreadyOutlinedCode(
2337 IRSimilarityCandidate *IRSC =
Region.Candidate;
2343 for (
unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
2344 if (Outlined.contains(Idx))
2349 if (!
Region.Candidate->backInstruction()->isTerminator()) {
2351 Region.Candidate->backInstruction()->getNextNode();
2352 assert(NewEndInst &&
"Next instruction is a nullptr?");
2353 if (
Region.Candidate->end()->Inst != NewEndInst) {
2354 IRInstructionDataList *IDL =
Region.Candidate->front()->IDL;
2355 IRInstructionData *NewEndIRID =
new (InstDataAllocator.Allocate())
2356 IRInstructionData(*NewEndInst,
2357 InstructionClassifier.visit(*NewEndInst), *IDL);
2365 return none_of(*IRSC, [
this](IRInstructionData &
ID) {
2369 return !this->InstructionClassifier.visit(
ID.Inst);
2373void IROutliner::pruneIncompatibleRegions(
2374 std::vector<IRSimilarityCandidate> &CandidateVec,
2375 OutlinableGroup &CurrentGroup) {
2376 bool PreviouslyOutlined;
2380 const IRSimilarityCandidate &
RHS) {
2381 return LHS.getStartIdx() <
RHS.getStartIdx();
2384 IRSimilarityCandidate &FirstCandidate = CandidateVec[0];
2387 if (FirstCandidate.getLength() == 2) {
2393 unsigned CurrentEndIdx = 0;
2394 for (IRSimilarityCandidate &IRSC : CandidateVec) {
2395 PreviouslyOutlined =
false;
2400 for (
unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
2401 if (Outlined.contains(Idx)) {
2402 PreviouslyOutlined =
true;
2406 if (PreviouslyOutlined)
2411 bool BBHasAddressTaken =
any_of(IRSC, [](IRInstructionData &
ID){
2412 return ID.Inst->getParent()->hasAddressTaken();
2415 if (BBHasAddressTaken)
2423 dbgs() <<
"... Skipping function with nooutline attribute: "
2424 << FnForCurrCand.
getName() <<
"\n";
2430 !OutlineFromLinkODRs)
2435 if (CurrentEndIdx != 0 && StartIdx <= CurrentEndIdx)
2438 bool BadInst =
any_of(IRSC, [
this](IRInstructionData &
ID) {
2442 return !this->InstructionClassifier.visit(
ID.Inst);
2448 OutlinableRegion *OS =
new (RegionAllocator.Allocate())
2449 OutlinableRegion(IRSC, CurrentGroup);
2450 CurrentGroup.
Regions.push_back(OS);
2452 CurrentEndIdx = EndIdx;
2457IROutliner::findBenefitFromAllRegions(OutlinableGroup &CurrentGroup) {
2459 for (OutlinableRegion *Region : CurrentGroup.
Regions) {
2460 TargetTransformInfo &
TTI = getTTI(*
Region->StartBB->getParent());
2463 RegionBenefit +=
Region->getBenefit(
TTI);
2465 <<
" saved instructions to overfall benefit.\n");
2468 return RegionBenefit;
2480 unsigned OutputCanon) {
2488 "Could not find GVN set for PHINode number!");
2489 assert(It->second.second.size() > 0 &&
"PHINode does not have any values!");
2490 OutputCanon = *It->second.second.begin();
2492 std::optional<unsigned> OGVN =
2493 Region.Candidate->fromCanonicalNum(OutputCanon);
2494 assert(OGVN &&
"Could not find GVN for Canonical Number?");
2495 std::optional<Value *> OV =
Region.Candidate->fromGVN(*OGVN);
2496 assert(OV &&
"Could not find value for GVN?");
2501IROutliner::findCostOutputReloads(OutlinableGroup &CurrentGroup) {
2503 for (OutlinableRegion *Region : CurrentGroup.
Regions) {
2504 TargetTransformInfo &
TTI = getTTI(*
Region->StartBB->getParent());
2507 for (
unsigned OutputCanon :
Region->GVNStores) {
2514 <<
" instructions to cost for output of type "
2515 << *
V->getType() <<
"\n");
2516 OverallCost += LoadCost;
2535 unsigned NumOutputBranches = 0;
2549 for (
Value *V :
ID.OperVals) {
2551 if (!CandidateBlocks.
contains(BB) && FoundBlocks.
insert(BB).second)
2552 NumOutputBranches++;
2560 for (
unsigned OutputCanon : OutputUse) {
2563 TTI.getMemoryOpCost(Instruction::Load, V->getType(),
Align(1), 0,
2570 <<
" instructions to cost for output of type "
2571 << *V->getType() <<
"\n");
2572 OutputCost += StoreCost * NumOutputBranches;
2577 LLVM_DEBUG(
dbgs() <<
"Adding " << BranchCost <<
" to the current cost for"
2578 <<
" a branch instruction\n");
2579 OutputCost += BranchCost * NumOutputBranches;
2593 InstructionCost TotalCost = ComparisonCost * BranchCost * DifferentBlocks;
2596 <<
" instructions for each switch case for each different"
2597 <<
" output path in a function\n");
2598 OutputCost += TotalCost * NumOutputBranches;
2604void IROutliner::findCostBenefit(
Module &M, OutlinableGroup &CurrentGroup) {
2605 InstructionCost RegionBenefit = findBenefitFromAllRegions(CurrentGroup);
2606 CurrentGroup.
Benefit += RegionBenefit;
2609 InstructionCost OutputReloadCost = findCostOutputReloads(CurrentGroup);
2610 CurrentGroup.
Cost += OutputReloadCost;
2614 RegionBenefit / CurrentGroup.
Regions.size();
2615 unsigned OverallArgumentNum = CurrentGroup.
ArgumentTypes.size();
2616 unsigned NumRegions = CurrentGroup.
Regions.size();
2617 TargetTransformInfo &
TTI =
2618 getTTI(*CurrentGroup.
Regions[0]->Candidate->getFunction());
2623 <<
" instructions to cost for body of new function.\n");
2624 CurrentGroup.
Cost += AverageRegionBenefit;
2630 <<
" instructions to cost for each argument in the new"
2632 CurrentGroup.
Cost +=
2640 <<
" instructions to cost for each argument in the new"
2641 <<
" function " << NumRegions <<
" times for the "
2642 <<
"needed argument handling at the call site.\n");
2643 CurrentGroup.
Cost +=
2656 std::optional<unsigned> OutputIdx;
2658 for (
unsigned ArgIdx =
Region.NumExtractedInputs;
2659 ArgIdx < Region.Call->arg_size(); ArgIdx++) {
2660 if (Operand ==
Region.Call->getArgOperand(ArgIdx)) {
2661 OutputIdx = ArgIdx -
Region.NumExtractedInputs;
2671 auto It = OutputMappings.find(Outputs[*OutputIdx]);
2672 if (It == OutputMappings.end()) {
2673 LLVM_DEBUG(
dbgs() <<
"Mapping extracted output " << *LI <<
" to "
2674 << *Outputs[*OutputIdx] <<
"\n");
2675 OutputMappings.insert(std::make_pair(LI, Outputs[*OutputIdx]));
2677 Value *Orig = It->second;
2678 LLVM_DEBUG(
dbgs() <<
"Mapping extracted output " << *Orig <<
" to "
2679 << *Outputs[*OutputIdx] <<
"\n");
2680 OutputMappings.insert(std::make_pair(LI, Orig));
2685 SetVector<Value *> ArgInputs, Outputs;
2686 assert(
Region.StartBB &&
"StartBB for the OutlinableRegion is nullptr!");
2689 CodeExtractorAnalysisCache CEAC(*OrigF);
2690 Region.ExtractedFunction =
2691 Region.CE->extractCodeRegion(CEAC, ArgInputs, Outputs);
2695 if (!
Region.ExtractedFunction) {
2698 Region.reattachCandidate();
2706 User *InstAsUser =
Region.ExtractedFunction->user_back();
2710 if (
Region.PrevBB == InitialStart) {
2719 Region.StartBB = RewrittenBB;
2720 Region.EndBB = RewrittenBB;
2727 IRInstructionDataList *IDL =
Region.Candidate->front()->IDL;
2730 Region.NewFront =
new (InstDataAllocator.Allocate()) IRInstructionData(
2731 *BeginRewritten, InstructionClassifier.visit(*BeginRewritten), *IDL);
2732 Region.NewBack =
new (InstDataAllocator.Allocate()) IRInstructionData(
2733 *EndRewritten, InstructionClassifier.visit(*EndRewritten), *IDL);
2744 assert(RewrittenBB !=
nullptr &&
2745 "Could not find a predecessor after extraction!");
2749 for (Instruction &
I : *RewrittenBB)
2751 if (
Region.ExtractedFunction == CI->getCalledFunction())
2754 updateOutputMapping(Region, Outputs.
getArrayRef(), LI);
2755 Region.reattachCandidate();
2759unsigned IROutliner::doOutline(
Module &M) {
2765 IRSimilarityIdentifier &
Identifier = getIRSI(M);
2769 unsigned OutlinedFunctionNum = 0;
2772 if (SimilarityCandidates.size() > 1)
2774 [](
const std::vector<IRSimilarityCandidate> &
LHS,
2775 const std::vector<IRSimilarityCandidate> &
RHS) {
2776 return LHS[0].getLength() *
LHS.size() >
2777 RHS[0].getLength() *
RHS.size();
2781 std::vector<OutlinableGroup> PotentialGroups(SimilarityCandidates.size());
2783 DenseSet<unsigned> NotSame;
2784 std::vector<OutlinableGroup *> NegativeCostGroups;
2785 std::vector<OutlinableRegion *> OutlinedRegions;
2787 unsigned PotentialGroupIdx = 0;
2789 OutlinableGroup &CurrentGroup = PotentialGroups[PotentialGroupIdx++];
2792 pruneIncompatibleRegions(CandidateVec, CurrentGroup);
2797 if (CurrentGroup.
Regions.size() < 2)
2811 OutlinedRegions.clear();
2812 for (OutlinableRegion *OS : CurrentGroup.
Regions) {
2824 DenseSet<BasicBlock *> BlocksInRegion;
2826 OS->
CE =
new (ExtractorAllocator.Allocate())
2827 CodeExtractor(BE,
nullptr,
false,
nullptr,
nullptr,
nullptr,
false,
2828 false,
nullptr,
"outlined");
2829 findAddInputsOutputs(M, *OS, NotSame);
2831 OutlinedRegions.push_back(OS);
2838 CurrentGroup.
Regions = std::move(OutlinedRegions);
2840 if (CurrentGroup.
Regions.empty())
2846 findCostBenefit(M, CurrentGroup);
2850 if (CurrentGroup.
Cost >= CurrentGroup.
Benefit && CostModel) {
2851 OptimizationRemarkEmitter &ORE =
2852 getORE(*CurrentGroup.
Regions[0]->Candidate->getFunction());
2854 IRSimilarityCandidate *
C = CurrentGroup.
Regions[0]->Candidate;
2855 OptimizationRemarkMissed
R(
DEBUG_TYPE,
"WouldNotDecreaseSize",
2856 C->frontInstruction());
2857 R <<
"did not outline "
2859 <<
" regions due to estimated increase of "
2860 <<
ore::NV(
"InstructionIncrease",
2862 <<
" instructions at locations ";
2865 [&R](OutlinableRegion *Region) {
2868 Region->Candidate->frontInstruction()->getDebugLoc());
2870 [&R]() { R <<
" "; });
2876 NegativeCostGroups.push_back(&CurrentGroup);
2879 ExtractorAllocator.DestroyAll();
2881 if (NegativeCostGroups.size() > 1)
2883 [](
const OutlinableGroup *
LHS,
const OutlinableGroup *
RHS) {
2884 return LHS->Benefit -
LHS->Cost >
RHS->Benefit -
RHS->Cost;
2887 std::vector<Function *> FuncsToRemove;
2888 for (OutlinableGroup *CG : NegativeCostGroups) {
2889 OutlinableGroup &CurrentGroup = *CG;
2891 OutlinedRegions.clear();
2892 for (OutlinableRegion *Region : CurrentGroup.
Regions) {
2895 if (!isCompatibleWithAlreadyOutlinedCode(*Region))
2897 OutlinedRegions.push_back(Region);
2900 if (OutlinedRegions.size() < 2)
2905 CurrentGroup.
Regions = std::move(OutlinedRegions);
2908 CurrentGroup.
Cost = 0;
2909 findCostBenefit(M, CurrentGroup);
2913 OutlinedRegions.clear();
2914 for (OutlinableRegion *Region : CurrentGroup.
Regions) {
2915 Region->splitCandidate();
2916 if (!
Region->CandidateSplit)
2918 OutlinedRegions.push_back(Region);
2921 CurrentGroup.
Regions = std::move(OutlinedRegions);
2922 if (CurrentGroup.
Regions.size() < 2) {
2923 for (OutlinableRegion *R : CurrentGroup.
Regions)
2924 R->reattachCandidate();
2929 <<
" and benefit " << CurrentGroup.
Benefit <<
"\n");
2932 OutlinedRegions.clear();
2933 for (OutlinableRegion *OS : CurrentGroup.
Regions) {
2935 DenseSet<BasicBlock *> BlocksInRegion;
2937 OS->
CE =
new (ExtractorAllocator.Allocate())
2938 CodeExtractor(BE,
nullptr,
false,
nullptr,
nullptr,
nullptr,
false,
2939 false,
nullptr,
"outlined");
2940 bool FunctionOutlined = extractSection(*OS);
2941 if (FunctionOutlined) {
2944 for (
unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
2945 Outlined.insert(Idx);
2947 OutlinedRegions.push_back(OS);
2952 <<
" with benefit " << CurrentGroup.
Benefit
2953 <<
" and cost " << CurrentGroup.
Cost <<
"\n");
2955 CurrentGroup.
Regions = std::move(OutlinedRegions);
2957 if (CurrentGroup.
Regions.empty())
2960 OptimizationRemarkEmitter &ORE =
2961 getORE(*CurrentGroup.
Regions[0]->Call->getFunction());
2963 IRSimilarityCandidate *
C = CurrentGroup.
Regions[0]->Candidate;
2964 OptimizationRemark
R(
DEBUG_TYPE,
"Outlined",
C->front()->Inst);
2965 R <<
"outlined " <<
ore::NV(std::to_string(CurrentGroup.
Regions.size()))
2966 <<
" regions with decrease of "
2968 <<
" instructions at locations ";
2971 [&R](OutlinableRegion *Region) {
2972 R << ore::NV(
"DebugLoc",
2973 Region->Candidate->frontInstruction()->getDebugLoc());
2975 [&R]() { R <<
" "; });
2979 deduplicateExtractedSections(M, CurrentGroup, FuncsToRemove,
2980 OutlinedFunctionNum);
2983 for (Function *
F : FuncsToRemove)
2984 F->eraseFromParent();
2986 return OutlinedFunctionNum;
2993 return doOutline(M) > 0;
3009 std::unique_ptr<OptimizationRemarkEmitter> ORE;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
std::pair< ArgLocWithBBCanon, CanonList > PHINodeData
static void remapExtractedInputs(const ArrayRef< Value * > ArgInputs, const DenseMap< Value *, Value * > &OutputMappings, SetVector< Value * > &RemappedArgInputs)
Find the original value for the ArgInput values if any one of them was replaced during a previous ext...
static std::optional< unsigned > getGVNForPHINode(OutlinableRegion &Region, PHINode *PN, DenseSet< BasicBlock * > &Blocks, unsigned AggArgIdx)
Create a special GVN for PHINodes that will be used outside of the region.
static Value * getPassedArgumentAndAdjustArgumentLocation(const Argument *A, const OutlinableRegion &Region)
For the function call now representing the Region, find the passed value to that call that represents...
static void findCanonNumsForPHI(PHINode *PN, OutlinableRegion &Region, const DenseMap< Value *, Value * > &OutputMappings, SmallVector< std::pair< unsigned, BasicBlock * > > &CanonNums, bool ReplacedWithOutlinedCall=true)
Find the canonical numbering for the incoming Values into the PHINode PN.
static cl::opt< bool > NoCostModel("ir-outlining-no-cost", cl::init(false), cl::ReallyHidden, cl::desc("Debug option to outline greedily, without restriction that " "calculated benefit outweighs cost"))
static void moveBBContents(BasicBlock &SourceBB, BasicBlock &TargetBB)
Move the contents of SourceBB to before the last instruction of TargetBB.
static bool nextIRInstructionDataMatchesNextInst(IRInstructionData &ID)
Checks that the next instruction in the InstructionDataList matches the next instruction in the modul...
static void moveFunctionData(Function &Old, Function &New, DenseMap< Value *, BasicBlock * > &NewEnds)
Move each BasicBlock in Old to New.
static cl::opt< bool > EnableLinkOnceODRIROutlining("enable-linkonceodr-ir-outlining", cl::Hidden, cl::desc("Enable the IR outliner on linkonceodr functions"), cl::init(false))
static void getCodeExtractorArguments(OutlinableRegion &Region, std::vector< unsigned > &InputGVNs, DenseSet< unsigned > &NotSame, DenseMap< Value *, Value * > &OutputMappings, SetVector< Value * > &ArgInputs, SetVector< Value * > &Outputs)
Find the input GVNs and the output values for a region of Instructions.
static void fillOverallFunction(Module &M, OutlinableGroup &CurrentGroup, std::vector< DenseMap< Value *, BasicBlock * > > &OutputStoreBBs, std::vector< Function * > &FuncsToRemove, const DenseMap< Value *, Value * > &OutputMappings)
Fill the new function that will serve as the replacement function for all of the extracted regions of...
static void findExtractedOutputToOverallOutputMapping(Module &M, OutlinableRegion &Region, SetVector< Value * > &Outputs)
Create a mapping of the output arguments for the Region to the output arguments of the overall outlin...
static void alignOutputBlockWithAggFunc(OutlinableGroup &OG, OutlinableRegion &Region, DenseMap< Value *, BasicBlock * > &OutputBBs, DenseMap< Value *, BasicBlock * > &EndBBs, const DenseMap< Value *, Value * > &OutputMappings, std::vector< DenseMap< Value *, BasicBlock * > > &OutputStoreBBs)
For the outlined section, move needed the StoreInsts for the output registers into their own block.
static bool collectRegionsConstants(OutlinableRegion &Region, DenseMap< unsigned, Constant * > &GVNToConstant, DenseSet< unsigned > &NotSame)
Find whether Region matches the global value numbering to Constant mapping found so far.
static PHINode * findOrCreatePHIInBlock(PHINode &PN, OutlinableRegion &Region, BasicBlock *OverallPhiBlock, const DenseMap< Value *, Value * > &OutputMappings, DenseSet< PHINode * > &UsedPHIs)
Find, or add PHINode PN to the combined PHINode Block OverallPHIBlock in order to condense the number...
static bool analyzeAndPruneOutputBlocks(DenseMap< Value *, BasicBlock * > &BlocksToPrune, OutlinableRegion &Region)
Remove empty output blocks from the outlined region.
static hash_code encodePHINodeData(PHINodeData &PND)
Encode PND as an integer for easy lookup based on the argument location, the parent BasicBlock canoni...
SmallVector< unsigned, 2 > CanonList
CallInst * replaceCalledFunction(Module &M, OutlinableRegion &Region)
Replace the extracted function in the Region with a call to the overall function constructed from the...
static void createAndInsertBasicBlocks(DenseMap< Value *, BasicBlock * > &OldMap, DenseMap< Value *, BasicBlock * > &NewMap, Function *ParentFunc, Twine BaseName)
Takes in a mapping, OldMap of ConstantValues to BasicBlocks, sorts keys, before creating a basic bloc...
static bool outputHasNonPHI(Value *V, unsigned PHILoc, PHINode &PN, SmallPtrSet< BasicBlock *, 1 > &Exits, DenseSet< BasicBlock * > &BlocksInRegion)
Check if the V has any uses outside of the region other than PN.
static void analyzeExitPHIsForOutputUses(BasicBlock *CurrentExitFromRegion, SmallPtrSet< BasicBlock *, 1 > &PotentialExitsFromRegion, DenseSet< BasicBlock * > &RegionBlocks, SetVector< Value * > &Outputs, DenseSet< Value * > &OutputsReplacedByPHINode, DenseSet< Value * > &OutputsWithNonPhiUses)
Test whether CurrentExitFromRegion contains any PhiNodes that should be considered outputs.
static void getSortedConstantKeys(std::vector< Value * > &SortedKeys, DenseMap< Value *, BasicBlock * > &Map)
A function to sort the keys of Map, which must be a mapping of constant values to basic blocks and re...
static InstructionCost findCostForOutputBlocks(Module &M, OutlinableGroup &CurrentGroup, TargetTransformInfo &TTI)
Find the extra instructions needed to handle any output values for the region.
static void replaceTargetsFromPHINode(BasicBlock *PHIBlock, BasicBlock *Find, BasicBlock *Replace, DenseSet< BasicBlock * > &Included)
Rewrite the BranchInsts in the incoming blocks to PHIBlock that are found in Included to branch to Ba...
static void findExtractedInputToOverallInputMapping(OutlinableRegion &Region, std::vector< unsigned > &InputGVNs, SetVector< Value * > &ArgInputs)
Look over the inputs and map each input argument to an argument in the overall function for the Outli...
static void mapInputsToGVNs(IRSimilarityCandidate &C, SetVector< Value * > &CurrentInputs, const DenseMap< Value *, Value * > &OutputMappings, std::vector< unsigned > &EndInputNumbers)
Find the GVN for the inputs that have been found by the CodeExtractor.
static void replaceArgumentUses(OutlinableRegion &Region, DenseMap< Value *, BasicBlock * > &OutputBBs, const DenseMap< Value *, Value * > &OutputMappings, bool FirstFunction=false)
static DISubprogram * getSubprogramOrNull(OutlinableGroup &Group)
Get the subprogram if it exists for one of the outlined regions.
static Value * findOutputMapping(const DenseMap< Value *, Value * > OutputMappings, Value *Input)
Check the OutputMappings structure for value Input, if it exists it has been used as an output for ou...
static Value * findOutputValueInRegion(OutlinableRegion &Region, unsigned OutputCanon)
For the OutputCanon number passed in find the value represented by this canonical number.
static std::optional< bool > constantMatches(Value *V, unsigned GVN, DenseMap< unsigned, Constant * > &GVNToConstant)
Find whether V matches the Constants previously found for the GVN.
static void findConstants(IRSimilarityCandidate &C, DenseSet< unsigned > &NotSame, std::vector< unsigned > &Inputs)
Find the constants that will need to be lifted into arguments as they are not the same in each instan...
void replaceConstants(OutlinableRegion &Region)
Within an extracted function, replace the constants that need to be lifted into arguments with the ac...
std::pair< unsigned, unsigned > ArgLocWithBBCanon
static Value * getPassedArgumentInAlreadyOutlinedFunction(const Argument *A, const OutlinableRegion &Region)
For the function call now representing the Region, find the passed value to that call that represents...
void createSwitchStatement(Module &M, OutlinableGroup &OG, DenseMap< Value *, BasicBlock * > &EndBBs, std::vector< DenseMap< Value *, BasicBlock * > > &OutputStoreBBs)
Create the switch statement for outlined function to differentiate between all the output blocks.
static BasicBlock * findOrCreatePHIBlock(OutlinableGroup &Group, Value *RetVal)
Find or create a BasicBlock in the outlined function containing PhiBlocks for RetVal.
std::optional< unsigned > findDuplicateOutputBlock(DenseMap< Value *, BasicBlock * > &OutputBBs, std::vector< DenseMap< Value *, BasicBlock * > > &OutputStoreBBs)
It is possible that there is a basic block that already performs the same stores.
This header defines various interfaces for pass management in LLVM.
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
FunctionAnalysisManager FAM
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Functions, function parameters, and return types can have attributes to indicate how they should be t...
LLVM Basic Block Representation.
LLVM_ABI void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)
Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...
iterator begin()
Instruction iterator methods.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
LLVM_ABI const BasicBlock * getUniqueSuccessor() const
Return the successor of this block if it has a unique successor.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
LLVM_ABI SymbolTableList< BasicBlock >::iterator eraseFromParent()
Unlink 'this' from the containing function and delete it.
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
void splice(BasicBlock::iterator ToIt, BasicBlock *FromBB)
Transfer all instructions from FromBB to this basic block at ToIt.
Conditional or Unconditional Branch instruction.
unsigned getNumSuccessors() const
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
BasicBlock * getSuccessor(unsigned i) const
void setSuccessor(unsigned idx, BasicBlock *NewSucc)
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
This is the shared class of boolean and integer constants.
uint64_t getLimitedValue(uint64_t Limit=~0ULL) const
getLimitedValue - If the value is smaller than the specified limit, return it, otherwise return the l...
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
This is an important base class in LLVM.
Subprogram description. Uses SubclassData1.
static DebugLoc getDropped()
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
void getDescendants(NodeT *R, SmallVectorImpl< NodeT * > &Result) const
Get all nodes dominated by R, including R itself.
void insertEdge(NodeT *From, NodeT *To)
Inform the dominator tree about a CFG edge insertion and update the tree.
void deleteEdge(NodeT *From, NodeT *To)
Inform the dominator tree about a CFG edge deletion and update the tree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
const BasicBlock & getEntryBlock() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
const BasicBlock & back() const
AttributeList getAttributes() const
Return the attribute list for this Function.
bool hasOptNone() const
Do not optimize this function (-O0).
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool hasLinkOnceODRLinkage() const
@ InternalLinkage
Rename collisions when linking (static functions).
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
This class is a pass that identifies similarity in a Module, extracts instances of the similarity,...
An analysis pass that runs and returns the IRSimilarityIdentifier run on the Module.
This is a class that wraps a range of IRInstructionData from one point to another in the vector of IR...
std::optional< unsigned > getGVN(Value *V)
Finds the positive number associated with V if it has been mapped.
unsigned getEndIdx() const
void getBasicBlocks(DenseSet< BasicBlock * > &BBSet) const
unsigned getStartIdx() const
BasicBlock * getStartBB()
std::optional< unsigned > getCanonicalNum(unsigned N)
Find the canonical number from the global value number N stored in the candidate.
IRInstructionData * front() const
This class puts all the pieces of the IRInstructionData, IRInstructionMapper, IRSimilarityCandidate t...
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
bool isTerminator() const
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
An instruction for reading from memory.
Value * getPointerOperand()
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVM_ABI void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const
Print the appropriate prefix and the specified global variable's name.
A Module instance is used to store all the information related to an LLVM module.
void setIncomingBlock(unsigned i, BasicBlock *BB)
void setIncomingValue(unsigned i, Value *V)
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
bool contains(const BlockT *BB) const
Check if the region contains a BasicBlock.
RegionT * getParent() const
Get the parent of the Region.
Return a value (possibly void), from a function.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
A vector that has set insertion semantics.
ArrayRef< value_type > getArrayRef() const
size_type size() const
Determine the number of elements in the SetVector.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
static SwitchInst * Create(Value *Value, BasicBlock *Default, unsigned NumCases, InsertPosition InsertBefore=nullptr)
LLVM_ABI void addCase(ConstantInt *OnVal, BasicBlock *Dest)
Add an entry to the switch instruction.
Analysis pass providing the TargetTransformInfo.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
void setOperand(unsigned i, Value *Val)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
bool erase(const ValueT &V)
An opaque object representing a hash code.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
iterator erase(iterator I)
Remove a node by iterator; never deletes.
iterator insert(iterator I, reference Node)
Insert a node by reference; never copies.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
std::vector< SimilarityGroup > SimilarityGroupList
std::vector< IRSimilarityCandidate > SimilarityGroup
@ BasicBlock
Various leaf nodes.
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
hash_code hash_value(const FixedPointSemantics &Val)
void interleave(ForwardIterator begin, ForwardIterator end, UnaryFunctor each_fn, NullaryFunctor between_fn)
An STL-style algorithm similar to std::for_each that applies a second functor between every pair of e...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
cl::opt< bool > DisableIndirectCalls("no-ir-sim-indirect-calls", cl::init(false), cl::ReallyHidden, cl::desc("disable outlining indirect calls."))
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
@ RF_IgnoreMissingLocals
If this flag is set, the remapper ignores missing function-local entries (Argument,...
@ RF_NoModuleLevelChanges
If this flag is set, the remapper knows that only local values within a function (such as an instruct...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
cl::opt< bool > DisableBranches("no-ir-sim-branch-matching", cl::init(false), cl::ReallyHidden, cl::desc("disable similarity matching, and outlining, " "across branches for debugging purposes."))
cl::opt< bool > DisableIntrinsics("no-ir-sim-intrinsics", cl::init(false), cl::ReallyHidden, cl::desc("Don't match or outline intrinsics"))
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void RemapFunction(Function &F, ValueToValueMapTy &VM, RemapFlags Flags=RF_None, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataPredicate *IdentityMD=nullptr)
Remap the operands, metadata, arguments, and instructions of a function.
auto predecessors(const MachineBasicBlock *BB)
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
LLVM_ABI void updateLoopMetadataDebugLocations(Instruction &I, function_ref< Metadata *(Metadata *)> Updater)
Update the debug locations contained within the MD_loop metadata attached to the instruction I,...
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
The OutlinableGroup holds all the overarching information for outlining a set of regions that are str...
std::optional< unsigned > SwiftErrorArgument
The argument that needs to be marked with the swifterr attribute.
std::vector< Type * > ArgumentTypes
The argument types for the function created as the overall function to replace the extracted function...
DenseSet< ArrayRef< unsigned > > OutputGVNCombinations
A set containing the different GVN store sets needed.
void findSameConstants(DenseSet< unsigned > &NotSame)
For the Regions, we look at every Value.
InstructionCost Cost
The number of added instructions needed for the outlining of the Regions.
DenseMap< unsigned, std::pair< std::pair< unsigned, unsigned >, SmallVector< unsigned, 2 > > > PHINodeGVNToGVNs
unsigned PHINodeGVNTracker
Tracker counting backwards from the highest unsigned value possible to avoid conflicting with the GVN...
std::vector< OutlinableRegion * > Regions
The sections that could be outlined.
DenseMap< hash_code, unsigned > GVNsToPHINodeGVN
bool IgnoreGroup
Flag for whether we should not consider this group of OutlinableRegions for extraction.
DenseMap< Value *, BasicBlock * > EndBBs
The return blocks for the overall function.
unsigned BranchesToOutside
The number of branches in the region target a basic block that is outside of the region.
Function * OutlinedFunction
The Function for the collective overall function.
bool InputTypesSet
Flag for whether the ArgumentTypes have been defined after the extraction of the first region.
DenseMap< Value *, BasicBlock * > PHIBlocks
The PHIBlocks with their corresponding return block based on the return value as the key.
FunctionType * OutlinedFunctionType
The FunctionType for the overall function.
DenseMap< unsigned, unsigned > CanonicalNumberToAggArg
The mapping of the canonical numbering of the values in outlined sections to specific arguments.
void collectGVNStoreSets(Module &M)
For the regions, look at each set of GVN stores needed and account for each combination.
InstructionCost Benefit
The number of instructions that will be outlined by extracting Regions.
unsigned NumAggregateInputs
The number of input values in ArgumentTypes.
This struct is a compact representation of a valid (non-zero power of two) alignment.
This provides the utilities for hashing an Instruction to an unsigned integer.
Instruction * Inst
The source Instruction that is being wrapped.
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...
The OutlinableRegion holds all the information for a specific region, or sequence of instructions.
CallInst * Call
The call site of the extracted region.
CodeExtractor * CE
Used to create an outlined function.
InstructionCost getBenefit(TargetTransformInfo &TTI)
Get the size of the code removed from the region.
BasicBlock * FollowBB
The BasicBlock that is after the start of the region BasicBlock, only defined when the region has bee...
unsigned OutputBlockNum
The corresponding BasicBlock with the appropriate stores for this OutlinableRegion in the overall fun...
bool CandidateSplit
Flag for whether we have split out the IRSimilarityCanidate.
bool IgnoreRegion
Flag for whether we should not consider this region for extraction.
void splitCandidate()
For the contained region, split the parent BasicBlock at the starting and ending instructions of the ...
Value * findCorrespondingValueIn(const OutlinableRegion &Other, Value *V)
Find a corresponding value for V in similar OutlinableRegion Other.
BasicBlock * findCorrespondingBlockIn(const OutlinableRegion &Other, BasicBlock *BB)
Find a corresponding BasicBlock for BB in similar OutlinableRegion Other.
BasicBlock * PrevBB
The BasicBlock that is before the start of the region BasicBlock, only defined when the region has be...
BasicBlock * EndBB
The BasicBlock that contains the ending instruction of the region.
IRSimilarityCandidate * Candidate
Describes the region of code.
DenseMap< Value *, Value * > RemappedArguments
Values in the outlined functions will often be replaced by arguments.
OutlinableRegion(IRSimilarityCandidate &C, OutlinableGroup &Group)
Function * ExtractedFunction
The function for the extracted region.
bool EndsInBranch
Marks whether this region ends in a branch, there is special handling required for the following basi...
BasicBlock * StartBB
The BasicBlock that contains the starting instruction of the region.
void reattachCandidate()
For the contained region, reattach the BasicBlock at the starting and ending instructions of the cont...