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;
247 assert(EndInst &&
"Expected an end instruction?");
258 assert(StartInst &&
"Expected a start instruction?");
276 bool EndBBTermAndBackInstDifferent =
EndBB->getTerminator() != BackInst;
278 unsigned NumPredsOutsideRegion = 0;
279 for (
unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
280 if (!BBSet.
contains(PN->getIncomingBlock(i))) {
281 PHIPredBlock = PN->getIncomingBlock(i);
282 ++NumPredsOutsideRegion;
289 IBlock = PN->getIncomingBlock(i);
290 if (IBlock ==
EndBB && EndBBTermAndBackInstDifferent) {
291 PHIPredBlock = PN->getIncomingBlock(i);
292 ++NumPredsOutsideRegion;
296 if (NumPredsOutsideRegion > 1)
310 BackInst != &*std::prev(
EndBB->getFirstInsertionPt()))
328 std::string OriginalName =
PrevBB->getName().str();
330 StartBB =
PrevBB->splitBasicBlock(StartInst, OriginalName +
"_to_outline");
335 PrevBB->replaceSuccessorsPhiUsesWith(PHIPredBlock,
PrevBB);
340 FollowBB =
EndBB->splitBasicBlock(EndInst, OriginalName +
"_after_outline");
376 assert(
StartBB !=
nullptr &&
"StartBB for Candidate is not defined!");
378 assert(
PrevBB->getTerminator() &&
"Terminator removed from PrevBB!");
394 "PrevBB has more than one predecessor. Should be 0 or 1.");
396 PrevBB->replaceSuccessorsPhiUsesWith(
PrevBB, BeforePrevBB);
398 PrevBB->getTerminator()->eraseFromParent();
418 assert(
FollowBB !=
nullptr &&
"FollowBB for Candidate is not defined!");
446static std::optional<bool>
460 std::tie(GVNToConstantIt, Inserted) =
461 GVNToConstant.
insert(std::make_pair(GVN, CST));
464 if (Inserted || (GVNToConstantIt->second == CST))
487 switch (
I->getOpcode()) {
488 case Instruction::FDiv:
489 case Instruction::FRem:
490 case Instruction::SDiv:
491 case Instruction::SRem:
492 case Instruction::UDiv:
493 case Instruction::URem:
516 auto OutputMapping = OutputMappings.
find(
Input);
517 if (OutputMapping != OutputMappings.
end())
518 return OutputMapping->second;
535 bool ConstantsTheSame =
true;
544 std::optional<unsigned> GVNOpt =
C.getGVN(V);
545 assert(GVNOpt &&
"Expected a GVN for operand?");
546 unsigned GVN = *GVNOpt;
551 ConstantsTheSame =
false;
559 std::optional<bool> ConstantMatches =
561 if (ConstantMatches) {
562 if (*ConstantMatches)
565 ConstantsTheSame =
false;
572 ConstantsTheSame =
false;
578 return ConstantsTheSame;
612Function *IROutliner::createFunction(
Module &M, OutlinableGroup &Group,
613 unsigned FunctionNameSuffix) {
625 for (OutlinableRegion *R : Group.
Regions) {
626 Type *ExtractedFuncType =
R->ExtractedFunction->getReturnType();
629 RetTy = ExtractedFuncType;
639 "outlined_ir_func_" + std::to_string(FunctionNameSuffix), M);
644 Attribute::SwiftError);
654 DICompileUnit *CU =
SP->getUnit();
655 DIBuilder
DB(M,
true, CU);
656 DIFile *
Unit =
SP->getFile();
660 llvm::raw_string_ostream MangledNameStream(Dummy);
663 DISubprogram *OutlinedSP =
DB.createFunction(
664 Unit ,
F->getName(), Dummy, Unit ,
666 DB.createSubroutineType(
DB.getOrCreateTypeArray({})),
668 DINode::DIFlags::FlagArtificial ,
670 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
673 F->setSubprogram(OutlinedSP);
689 CurrBB.removeFromParent();
690 CurrBB.insertInto(&New);
697 NewEnds.
insert(std::make_pair(RI->getReturnValue(), &CurrBB));
704 Val.dropDbgRecords();
719 Loc->getColumn(), SP,
nullptr);
745 std::vector<unsigned> &Inputs) {
749 for (IRInstructionDataList::iterator IDIt =
C.begin(), EndIDIt =
C.end();
750 IDIt != EndIDIt; IDIt++) {
751 for (
Value *V : (*IDIt).OperVals) {
754 unsigned GVN = *
C.getGVN(V);
757 Inputs.push_back(GVN);
775 std::vector<unsigned> &EndInputNumbers) {
782 if (It != OutputMappings.
end())
784 assert(
C.getGVN(
Input) &&
"Could not find a numbering for the given input");
785 EndInputNumbers.push_back(*
C.getGVN(
Input));
805 if (It != OutputMappings.
end())
850 CE->findInputsOutputs(OverallInputs, DummyOutputs, SinkCands);
851 assert(
Region.StartBB &&
"Region must have a start BasicBlock!");
858 if (!CE->isEligible()) {
859 Region.IgnoreRegion =
true;
864 CE->findAllocas(CEAC, SinkCands, HoistCands, Dummy);
865 CE->findInputsOutputs(PremappedInputs, Outputs, SinkCands);
872 if (OverallInputs.
size() != PremappedInputs.
size()) {
873 Region.IgnoreRegion =
true;
901 std::vector<unsigned> &InputGVNs,
908 unsigned TypeIndex = 0;
911 unsigned OriginalIndex = 0;
922 for (
unsigned InputVal : InputGVNs) {
923 std::optional<unsigned> CanonicalNumberOpt =
C.getCanonicalNum(InputVal);
924 assert(CanonicalNumberOpt &&
"Canonical number not found?");
925 unsigned CanonicalNumber = *CanonicalNumberOpt;
927 std::optional<Value *> InputOpt =
C.fromGVN(InputVal);
928 assert(InputOpt &&
"Global value number not found?");
937 if (
Input->isSwiftError()) {
940 "Argument already marked with swifterr for this OutlinableGroup!");
949 Region.AggArgToConstant.insert(std::make_pair(AggArgIt->second, CST));
952 std::make_pair(CanonicalNumber, TypeIndex));
953 Region.AggArgToConstant.insert(std::make_pair(TypeIndex, CST));
964 if (OriginalIndex != AggArgIt->second)
965 Region.ChangedArgOrder =
true;
966 Region.ExtractedArgToAgg.insert(
967 std::make_pair(OriginalIndex, AggArgIt->second));
968 Region.AggArgToExtracted.insert(
969 std::make_pair(AggArgIt->second, OriginalIndex));
972 std::make_pair(CanonicalNumber, TypeIndex));
973 Region.ExtractedArgToAgg.insert(std::make_pair(OriginalIndex, TypeIndex));
974 Region.AggArgToExtracted.insert(std::make_pair(TypeIndex, OriginalIndex));
989 Region.NumExtractedInputs = OriginalIndex;
1008 [PHILoc, &PN, V, &BlocksInRegion](
unsigned Idx) {
1009 return (Idx != PHILoc && V == PN.getIncomingValue(Idx) &&
1010 !BlocksInRegion.contains(PN.getIncomingBlock(Idx)));
1015 return any_of(V->users(), [&Exits, &BlocksInRegion](
User *U) {
1016 Instruction *I = dyn_cast<Instruction>(U);
1023 BasicBlock *Parent = I->getParent();
1024 if (BlocksInRegion.contains(Parent))
1030 if (!isa<PHINode>(I))
1037 if (!Exits.contains(Parent))
1064 for (
PHINode &PN : CurrentExitFromRegion->
phis()) {
1067 for (
unsigned I = 0,
E = PN.getNumIncomingValues();
I <
E; ++
I)
1068 if (RegionBlocks.
contains(PN.getIncomingBlock(
I)))
1072 unsigned NumIncomingVals = IncomingVals.
size();
1073 if (NumIncomingVals == 0)
1078 if (NumIncomingVals == 1) {
1079 Value *V = PN.getIncomingValue(*IncomingVals.
begin());
1080 OutputsWithNonPhiUses.
insert(V);
1081 OutputsReplacedByPHINode.
erase(V);
1091 for (
unsigned Idx : IncomingVals) {
1092 Value *V = PN.getIncomingValue(Idx);
1094 outputHasNonPHI(V, Idx, PN, PotentialExitsFromRegion, RegionBlocks)) {
1095 OutputsWithNonPhiUses.
insert(V);
1096 OutputsReplacedByPHINode.
erase(V);
1099 if (!OutputsWithNonPhiUses.
contains(V))
1100 OutputsReplacedByPHINode.
insert(V);
1143 unsigned AggArgIdx) {
1155 if (!Blocks.
contains(IncomingBlock))
1163 std::optional<unsigned> OGVN = Cand.
getGVN(Incoming);
1165 Region.IgnoreRegion =
true;
1166 return std::nullopt;
1170 unsigned GVN = *OGVN;
1172 assert(OGVN &&
"No GVN found for incoming value?");
1177 OGVN = Cand.
getGVN(IncomingBlock);
1184 "Unknown basic block used in exit path PHINode.");
1196 assert(PrevBlock &&
"Expected a predecessor not in the reigon!");
1197 OGVN = Cand.
getGVN(PrevBlock);
1201 assert(OGVN &&
"No GVN found for incoming block?");
1210 std::optional<unsigned> BBGVN = Cand.
getGVN(PHIBB);
1211 assert(BBGVN &&
"Could not find GVN for the incoming block!");
1214 assert(BBGVN &&
"Could not find canonical number for the incoming block!");
1219 std::make_pair(std::make_pair(*BBGVN, AggArgIdx), PHIGVNs);
1226 bool Inserted =
false;
1233 return GVNToPHIIt->second;
1249 C.getBasicBlocks(BlocksInRegion, BE);
1255 if (!BlocksInRegion.
contains(Succ))
1265 OutputsReplacedByPHINode,
1266 OutputsWithNonPhiUses);
1269 unsigned OriginalIndex =
Region.NumExtractedInputs;
1282 for (
Value *Output : Outputs) {
1292 if (OutputsReplacedByPHINode.
contains(Output))
1295 unsigned AggArgIdx = 0;
1296 for (
unsigned Jdx = TypeIndex; Jdx < ArgumentSize; Jdx++) {
1300 if (!AggArgsUsed.
insert(Jdx).second)
1304 Region.ExtractedArgToAgg.insert(std::make_pair(OriginalIndex, Jdx));
1305 Region.AggArgToExtracted.insert(std::make_pair(Jdx, OriginalIndex));
1315 M.getDataLayout().getAllocaAddrSpace()));
1319 AggArgsUsed.
insert(ArgTypeIdx);
1320 Region.ExtractedArgToAgg.insert(
1321 std::make_pair(OriginalIndex, ArgTypeIdx));
1322 Region.AggArgToExtracted.insert(
1323 std::make_pair(ArgTypeIdx, OriginalIndex));
1324 AggArgIdx = ArgTypeIdx;
1330 std::optional<unsigned> GVN;
1348 GVN =
C.getGVN(Output);
1349 GVN =
C.getCanonicalNum(*GVN);
1355 Region.GVNStores.push_back(*GVN);
1368 std::vector<unsigned> Inputs;
1369 SetVector<Value *> ArgInputs, Outputs;
1396 std::vector<Value *> NewCallArgs;
1401 assert(
Call &&
"Call to replace is nullptr?");
1403 assert(AggFunc &&
"Function to replace with is nullptr?");
1411 << *AggFunc <<
" with same number of arguments\n");
1412 Call->setCalledFunction(AggFunc);
1420 for (
unsigned AggArgIdx = 0; AggArgIdx < AggFunc->
arg_size(); AggArgIdx++) {
1422 if (AggArgIdx == AggFunc->
arg_size() - 1 &&
1428 <<
Region.OutputBlockNum <<
"\n");
1434 ArgPair =
Region.AggArgToExtracted.find(AggArgIdx);
1435 if (ArgPair !=
Region.AggArgToExtracted.
end()) {
1436 Value *ArgumentValue =
Call->getArgOperand(ArgPair->second);
1440 LLVM_DEBUG(
dbgs() <<
"Setting argument " << AggArgIdx <<
" to value "
1441 << *ArgumentValue <<
"\n");
1442 NewCallArgs.push_back(ArgumentValue);
1447 if (
auto It =
Region.AggArgToConstant.find(AggArgIdx);
1450 LLVM_DEBUG(
dbgs() <<
"Setting argument " << AggArgIdx <<
" to value "
1452 NewCallArgs.push_back(CST);
1459 LLVM_DEBUG(
dbgs() <<
"Setting argument " << AggArgIdx <<
" to nullptr\n");
1465 << *AggFunc <<
" with new set of arguments\n");
1468 Call->getIterator());
1475 if (
Region.NewFront->Inst == OldCall)
1477 if (
Region.NewBack->Inst == OldCall)
1481 Call->setDebugLoc(
Region.Call->getDebugLoc());
1510 auto [PhiBlockForRetVal, Inserted] = Group.
PHIBlocks.try_emplace(RetVal);
1512 return PhiBlockForRetVal->second;
1514 auto ReturnBlockForRetVal = Group.
EndBBs.find(RetVal);
1516 "Could not find output value!");
1517 BasicBlock *ReturnBB = ReturnBlockForRetVal->second;
1523 PhiBlockForRetVal->second = PHIBlock;
1531 return PhiBlockForRetVal->second;
1548 return Region.Call->getArgOperand(
A->getArgNo());
1561 unsigned ArgNum =
A->getArgNo();
1565 if (
auto It =
Region.AggArgToConstant.find(ArgNum);
1571 ArgNum =
Region.AggArgToExtracted.find(ArgNum)->second;
1572 return Region.Call->getArgOperand(ArgNum);
1588 SmallVector<std::pair<unsigned, BasicBlock *>> &CanonNums,
1589 bool ReplacedWithOutlinedCall =
true) {
1597 if (ReplacedWithOutlinedCall)
1607 std::optional<unsigned> GVN =
Region.Candidate->getGVN(IVal);
1608 assert(GVN &&
"No GVN for incoming value");
1609 std::optional<unsigned> CanonNum =
Region.Candidate->getCanonicalNum(*GVN);
1610 assert(CanonNum &&
"No Canonical Number for GVN");
1611 CanonNums.push_back(std::make_pair(*CanonNum, IBlock));
1662 CurrentCanonNums.
clear();
1668 if (PNCanonNums.
size() != CurrentCanonNums.
size())
1671 bool FoundMatch =
true;
1680 for (
unsigned Idx = 0, Edx = PNCanonNums.
size(); Idx < Edx; ++Idx) {
1681 std::pair<unsigned, BasicBlock *> ToCompareTo = CurrentCanonNums[Idx];
1682 std::pair<unsigned, BasicBlock *> ToAdd = PNCanonNums[Idx];
1683 if (ToCompareTo.first != ToAdd.first) {
1689 Region.findCorrespondingBlockIn(*FirstRegion, ToAdd.second);
1690 assert(CorrespondingBlock &&
"Found block is nullptr");
1691 if (CorrespondingBlock != ToCompareTo.second) {
1700 UsedPHIs.
insert(&CurrPN);
1717 Region.findCorrespondingBlockIn(*FirstRegion, IncomingBlock);
1730 Value *Val =
Region.findCorrespondingValueIn(*FirstRegion, IncomingVal);
1731 assert(Val &&
"Value is nullptr?");
1734 Val = RemappedIt->second;
1753 bool FirstFunction =
false) {
1755 assert(
Region.ExtractedFunction &&
"Region has no extracted function?");
1763 for (
unsigned ArgIdx = 0; ArgIdx <
Region.ExtractedFunction->arg_size();
1766 "No mapping from extracted to outlined?");
1767 unsigned AggArgIdx =
Region.ExtractedArgToAgg.find(ArgIdx)->second;
1772 if (ArgIdx <
Region.NumExtractedInputs) {
1773 LLVM_DEBUG(
dbgs() <<
"Replacing uses of input " << *Arg <<
" in function "
1774 << *
Region.ExtractedFunction <<
" with " << *AggArg
1778 Region.RemappedArguments.insert(std::make_pair(V, AggArg));
1787 assert(InstAsUser &&
"User is nullptr!");
1793 bool EdgeAdded =
false;
1794 if (Descendants.
size() == 0) {
1808 auto VBBIt = OutputBBs.
find(RetVal);
1809 assert(VBBIt != OutputBBs.
end() &&
"Could not find output value!");
1815 Value *ValueOperand =
SI->getValueOperand();
1822 << *OutputBB <<
"\n");
1827 Region.Candidate->getGVN(ValueOperand).has_value()) {
1831 Region.findCorrespondingValueIn(*Group.
Regions[0], ValueOperand);
1832 assert(CorrVal &&
"Value is nullptr?");
1839 if (
Region.Candidate->getGVN(PN))
1849 if (FirstFunction) {
1851 Group.
PHIBlocks.insert(std::make_pair(RetVal, PHIBlock));
1863 OutputMappings, UsedPHIs);
1871 I->eraseFromParent();
1873 LLVM_DEBUG(
dbgs() <<
"Replacing uses of output " << *Arg <<
" in function "
1874 << *
Region.ExtractedFunction <<
" with " << *AggArg
1890 for (std::pair<unsigned, Constant *> &Const :
Region.AggArgToConstant) {
1891 unsigned AggArgIdx = Const.first;
1892 assert(OutlinedFunction &&
"Overall Function is not defined?");
1899 <<
" in function " << *OutlinedFunction <<
" with "
1917 bool Mismatch =
false;
1918 unsigned MatchingNum = 0;
1924 for (std::pair<Value *, BasicBlock *> &VToB : CompBBs) {
1925 auto OutputBBIt = OutputBBs.
find(VToB.first);
1926 if (OutputBBIt == OutputBBs.
end()) {
1933 if (CompBB->
size() - 1 != OutputBB->
size()) {
1943 if (!
I.isIdenticalTo(&(*NIt))) {
1958 return std::nullopt;
1969 bool AllRemoved =
true;
1970 Value *RetValueForBB;
1974 for (std::pair<Value *, BasicBlock *> &VtoBB : BlocksToPrune) {
1975 RetValueForBB = VtoBB.first;
1976 NewBB = VtoBB.second;
1980 if (NewBB->
size() == 0) {
1993 BlocksToPrune.
erase(V);
1997 Region.OutputBlockNum = -1;
2027 std::optional<unsigned> MatchingBB =
2034 <<
Region.ExtractedFunction <<
" to " << *MatchingBB);
2036 Region.OutputBlockNum = *MatchingBB;
2037 for (std::pair<Value *, BasicBlock *> &VtoBB : OutputBBs)
2038 VtoBB.second->eraseFromParent();
2042 Region.OutputBlockNum = OutputStoreBBs.size();
2044 Value *RetValueForBB;
2047 for (std::pair<Value *, BasicBlock *> &VtoBB : OutputBBs) {
2048 RetValueForBB = VtoBB.first;
2049 NewBB = VtoBB.second;
2050 auto VBBIt = EndBBs.
find(RetValueForBB);
2052 <<
Region.ExtractedFunction <<
" to "
2055 OutputStoreBBs.back().insert(std::make_pair(RetValueForBB, NewBB));
2072 std::vector<Value *> SortedKeys;
2076 for (
Value *RetVal : SortedKeys) {
2080 NewMap.
insert(std::make_pair(RetVal, NewBB));
2109 for (std::pair<Value *, BasicBlock *> &RetBlockPair : ReturnBBs) {
2110 std::pair<Value *, BasicBlock *> &OutputBlock =
2111 *OG.
EndBBs.find(RetBlockPair.first);
2112 BasicBlock *ReturnBlock = RetBlockPair.second;
2117 Term->moveBefore(*ReturnBlock, ReturnBlock->
end());
2120 LLVM_DEBUG(
dbgs() <<
"Create switch statement in " << *AggFunc <<
" for "
2121 << OutputStoreBBs.
size() <<
"\n");
2124 ReturnBlock, OutputStoreBBs.
size(), EndBB);
2128 auto OSBBIt = OutputStoreBB.find(OutputBlock.first);
2130 if (OSBBIt == OutputStoreBB.end())
2137 Term->setSuccessor(0, ReturnBlock);
2144 assert(OutputStoreBBs.size() < 2 &&
"Different store sets not handled!");
2152 if (OutputStoreBBs.size() == 1) {
2153 LLVM_DEBUG(
dbgs() <<
"Move store instructions to the end block in "
2156 for (std::pair<Value *, BasicBlock *> &VBPair : OutputBlocks) {
2157 auto EndBBIt = EndBBs.
find(VBPair.first);
2158 assert(EndBBIt != EndBBs.
end() &&
"Could not find end block");
2162 Term->eraseFromParent();
2165 Term->moveBefore(*EndBB, EndBB->
end());
2171void IROutliner::fillOverallFunction(
2172 Module &M, OutlinableGroup &CurrentGroup,
2174 std::vector<Function *> &FuncsToRemove) {
2175 OutlinableRegion *CurrentOS = CurrentGroup.
Regions[0];
2197 DenseMap<Value *, BasicBlock *> NewBBs;
2209 OutputStoreBBs.push_back(DenseMap<Value *, BasicBlock *>());
2210 for (std::pair<Value *, BasicBlock *> &VToBB : NewBBs) {
2211 auto VBBIt = CurrentGroup.
EndBBs.find(VToBB.first);
2214 OutputStoreBBs.back().insert(VToBB);
2226void IROutliner::deduplicateExtractedSections(
2227 Module &M, OutlinableGroup &CurrentGroup,
2228 std::vector<Function *> &FuncsToRemove,
unsigned &OutlinedFunctionNum) {
2229 createFunction(M, CurrentGroup, OutlinedFunctionNum);
2231 std::vector<DenseMap<Value *, BasicBlock *>> OutputStoreBBs;
2233 OutlinableRegion *CurrentOS;
2235 fillOverallFunction(M, CurrentGroup, OutputStoreBBs, FuncsToRemove);
2237 for (
unsigned Idx = 1; Idx < CurrentGroup.
Regions.size(); Idx++) {
2238 CurrentOS = CurrentGroup.
Regions[Idx];
2239 AttributeFuncs::mergeAttributesForOutlining(*CurrentGroup.
OutlinedFunction,
2244 DenseMap<Value *, BasicBlock *> NewBBs;
2247 "output_block_" + Twine(Idx));
2250 CurrentGroup.
EndBBs, OutputMappings,
2260 OutlinedFunctionNum++;
2277 IRInstructionDataList::iterator NextIDIt = std::next(
ID.getIterator());
2280 if (!
ID.Inst->isTerminator())
2281 NextModuleInst =
ID.Inst->getNextNode();
2282 else if (NextIDLInst !=
nullptr)
2283 NextModuleInst = &*NextIDIt->Inst->
getParent()->begin();
2285 if (NextIDLInst && NextIDLInst != NextModuleInst)
2291bool IROutliner::isCompatibleWithAlreadyOutlinedCode(
2293 IRSimilarityCandidate *IRSC =
Region.Candidate;
2299 for (
unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
2300 if (Outlined.contains(Idx))
2305 if (!
Region.Candidate->backInstruction()->isTerminator()) {
2307 Region.Candidate->backInstruction()->getNextNode();
2308 assert(NewEndInst &&
"Next instruction is a nullptr?");
2309 if (
Region.Candidate->end()->Inst != NewEndInst) {
2310 IRInstructionDataList *IDL =
Region.Candidate->front()->IDL;
2311 IRInstructionData *NewEndIRID =
new (InstDataAllocator.Allocate())
2312 IRInstructionData(*NewEndInst,
2313 InstructionClassifier.visit(*NewEndInst), *IDL);
2321 return none_of(*IRSC, [
this](IRInstructionData &
ID) {
2325 return !this->InstructionClassifier.visit(
ID.Inst);
2329void IROutliner::pruneIncompatibleRegions(
2330 std::vector<IRSimilarityCandidate> &CandidateVec,
2331 OutlinableGroup &CurrentGroup) {
2332 bool PreviouslyOutlined;
2336 const IRSimilarityCandidate &
RHS) {
2337 return LHS.getStartIdx() <
RHS.getStartIdx();
2340 IRSimilarityCandidate &FirstCandidate = CandidateVec[0];
2343 if (FirstCandidate.getLength() == 2) {
2349 unsigned CurrentEndIdx = 0;
2350 for (IRSimilarityCandidate &IRSC : CandidateVec) {
2351 PreviouslyOutlined =
false;
2356 for (
unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
2357 if (Outlined.contains(Idx)) {
2358 PreviouslyOutlined =
true;
2362 if (PreviouslyOutlined)
2367 bool BBHasAddressTaken =
any_of(IRSC, [](IRInstructionData &
ID){
2368 return ID.Inst->getParent()->hasAddressTaken();
2371 if (BBHasAddressTaken)
2379 dbgs() <<
"... Skipping function with nooutline attribute: "
2380 << FnForCurrCand.
getName() <<
"\n";
2386 !OutlineFromLinkODRs)
2391 if (CurrentEndIdx != 0 && StartIdx <= CurrentEndIdx)
2394 bool BadInst =
any_of(IRSC, [
this](IRInstructionData &
ID) {
2398 return !this->InstructionClassifier.visit(
ID.Inst);
2404 OutlinableRegion *OS =
new (RegionAllocator.Allocate())
2405 OutlinableRegion(IRSC, CurrentGroup);
2406 CurrentGroup.
Regions.push_back(OS);
2408 CurrentEndIdx = EndIdx;
2413IROutliner::findBenefitFromAllRegions(OutlinableGroup &CurrentGroup) {
2415 for (OutlinableRegion *Region : CurrentGroup.
Regions) {
2416 TargetTransformInfo &
TTI = getTTI(*
Region->StartBB->getParent());
2419 RegionBenefit +=
Region->getBenefit(
TTI);
2421 <<
" saved instructions to overfall benefit.\n");
2424 return RegionBenefit;
2436 unsigned OutputCanon) {
2444 "Could not find GVN set for PHINode number!");
2445 assert(It->second.second.size() > 0 &&
"PHINode does not have any values!");
2446 OutputCanon = *It->second.second.begin();
2448 std::optional<unsigned> OGVN =
2449 Region.Candidate->fromCanonicalNum(OutputCanon);
2450 assert(OGVN &&
"Could not find GVN for Canonical Number?");
2451 std::optional<Value *> OV =
Region.Candidate->fromGVN(*OGVN);
2452 assert(OV &&
"Could not find value for GVN?");
2457IROutliner::findCostOutputReloads(OutlinableGroup &CurrentGroup) {
2459 for (OutlinableRegion *Region : CurrentGroup.
Regions) {
2460 TargetTransformInfo &
TTI = getTTI(*
Region->StartBB->getParent());
2463 for (
unsigned OutputCanon :
Region->GVNStores) {
2470 <<
" instructions to cost for output of type "
2471 << *
V->getType() <<
"\n");
2472 OverallCost += LoadCost;
2491 unsigned NumOutputBranches = 0;
2505 for (
Value *V :
ID.OperVals) {
2507 if (!CandidateBlocks.
contains(BB) && FoundBlocks.
insert(BB).second)
2508 NumOutputBranches++;
2516 for (
unsigned OutputCanon : OutputUse) {
2519 TTI.getMemoryOpCost(Instruction::Load, V->getType(),
Align(1), 0,
2526 <<
" instructions to cost for output of type "
2527 << *V->getType() <<
"\n");
2528 OutputCost += StoreCost * NumOutputBranches;
2533 LLVM_DEBUG(
dbgs() <<
"Adding " << BranchCost <<
" to the current cost for"
2534 <<
" a branch instruction\n");
2535 OutputCost += BranchCost * NumOutputBranches;
2549 InstructionCost TotalCost = ComparisonCost * BranchCost * DifferentBlocks;
2552 <<
" instructions for each switch case for each different"
2553 <<
" output path in a function\n");
2554 OutputCost += TotalCost * NumOutputBranches;
2560void IROutliner::findCostBenefit(
Module &M, OutlinableGroup &CurrentGroup) {
2561 InstructionCost RegionBenefit = findBenefitFromAllRegions(CurrentGroup);
2562 CurrentGroup.
Benefit += RegionBenefit;
2565 InstructionCost OutputReloadCost = findCostOutputReloads(CurrentGroup);
2566 CurrentGroup.
Cost += OutputReloadCost;
2570 RegionBenefit / CurrentGroup.
Regions.size();
2571 unsigned OverallArgumentNum = CurrentGroup.
ArgumentTypes.size();
2572 unsigned NumRegions = CurrentGroup.
Regions.size();
2573 TargetTransformInfo &
TTI =
2574 getTTI(*CurrentGroup.
Regions[0]->Candidate->getFunction());
2579 <<
" instructions to cost for body of new function.\n");
2580 CurrentGroup.
Cost += AverageRegionBenefit;
2586 <<
" instructions to cost for each argument in the new"
2588 CurrentGroup.
Cost +=
2596 <<
" instructions to cost for each argument in the new"
2597 <<
" function " << NumRegions <<
" times for the "
2598 <<
"needed argument handling at the call site.\n");
2599 CurrentGroup.
Cost +=
2612 std::optional<unsigned> OutputIdx;
2614 for (
unsigned ArgIdx =
Region.NumExtractedInputs;
2615 ArgIdx < Region.Call->arg_size(); ArgIdx++) {
2616 if (Operand ==
Region.Call->getArgOperand(ArgIdx)) {
2617 OutputIdx = ArgIdx -
Region.NumExtractedInputs;
2627 auto It = OutputMappings.find(Outputs[*OutputIdx]);
2628 if (It == OutputMappings.end()) {
2629 LLVM_DEBUG(
dbgs() <<
"Mapping extracted output " << *LI <<
" to "
2630 << *Outputs[*OutputIdx] <<
"\n");
2631 OutputMappings.insert(std::make_pair(LI, Outputs[*OutputIdx]));
2633 Value *Orig = It->second;
2634 LLVM_DEBUG(
dbgs() <<
"Mapping extracted output " << *Orig <<
" to "
2635 << *Outputs[*OutputIdx] <<
"\n");
2636 OutputMappings.insert(std::make_pair(LI, Orig));
2641 SetVector<Value *> ArgInputs, Outputs;
2642 assert(
Region.StartBB &&
"StartBB for the OutlinableRegion is nullptr!");
2645 CodeExtractorAnalysisCache CEAC(*OrigF);
2646 Region.ExtractedFunction =
2647 Region.CE->extractCodeRegion(CEAC, ArgInputs, Outputs);
2651 if (!
Region.ExtractedFunction) {
2654 Region.reattachCandidate();
2662 User *InstAsUser =
Region.ExtractedFunction->user_back();
2666 if (
Region.PrevBB == InitialStart) {
2675 Region.StartBB = RewrittenBB;
2676 Region.EndBB = RewrittenBB;
2683 IRInstructionDataList *IDL =
Region.Candidate->front()->IDL;
2686 Region.NewFront =
new (InstDataAllocator.Allocate()) IRInstructionData(
2687 *BeginRewritten, InstructionClassifier.visit(*BeginRewritten), *IDL);
2688 Region.NewBack =
new (InstDataAllocator.Allocate()) IRInstructionData(
2689 *EndRewritten, InstructionClassifier.visit(*EndRewritten), *IDL);
2700 assert(RewrittenBB !=
nullptr &&
2701 "Could not find a predecessor after extraction!");
2705 for (Instruction &
I : *RewrittenBB)
2707 if (
Region.ExtractedFunction == CI->getCalledFunction())
2710 updateOutputMapping(Region, Outputs.
getArrayRef(), LI);
2711 Region.reattachCandidate();
2715unsigned IROutliner::doOutline(
Module &M) {
2721 IRSimilarityIdentifier &
Identifier = getIRSI(M);
2725 unsigned OutlinedFunctionNum = 0;
2728 if (SimilarityCandidates.size() > 1)
2730 [](
const std::vector<IRSimilarityCandidate> &
LHS,
2731 const std::vector<IRSimilarityCandidate> &
RHS) {
2732 return LHS[0].getLength() *
LHS.size() >
2733 RHS[0].getLength() *
RHS.size();
2737 std::vector<OutlinableGroup> PotentialGroups(SimilarityCandidates.size());
2739 DenseSet<unsigned> NotSame;
2740 std::vector<OutlinableGroup *> NegativeCostGroups;
2741 std::vector<OutlinableRegion *> OutlinedRegions;
2743 unsigned PotentialGroupIdx = 0;
2745 OutlinableGroup &CurrentGroup = PotentialGroups[PotentialGroupIdx++];
2748 pruneIncompatibleRegions(CandidateVec, CurrentGroup);
2753 if (CurrentGroup.
Regions.size() < 2)
2767 OutlinedRegions.clear();
2768 for (OutlinableRegion *OS : CurrentGroup.
Regions) {
2780 DenseSet<BasicBlock *> BlocksInRegion;
2782 OS->
CE =
new (ExtractorAllocator.Allocate())
2783 CodeExtractor(BE,
nullptr,
false,
nullptr,
nullptr,
nullptr,
false,
2784 false,
nullptr, {},
"outlined");
2785 findAddInputsOutputs(M, *OS, NotSame);
2787 OutlinedRegions.push_back(OS);
2794 CurrentGroup.
Regions = std::move(OutlinedRegions);
2796 if (CurrentGroup.
Regions.empty())
2802 findCostBenefit(M, CurrentGroup);
2806 if (CurrentGroup.
Cost >= CurrentGroup.
Benefit && CostModel) {
2807 OptimizationRemarkEmitter &ORE =
2808 getORE(*CurrentGroup.
Regions[0]->Candidate->getFunction());
2810 IRSimilarityCandidate *
C = CurrentGroup.
Regions[0]->Candidate;
2811 OptimizationRemarkMissed
R(
DEBUG_TYPE,
"WouldNotDecreaseSize",
2812 C->frontInstruction());
2813 R <<
"did not outline "
2815 <<
" regions due to estimated increase of "
2816 <<
ore::NV(
"InstructionIncrease",
2818 <<
" instructions at locations ";
2821 [&R](OutlinableRegion *Region) {
2824 Region->Candidate->frontInstruction()->getDebugLoc());
2826 [&R]() { R <<
" "; });
2832 NegativeCostGroups.push_back(&CurrentGroup);
2835 ExtractorAllocator.DestroyAll();
2837 if (NegativeCostGroups.size() > 1)
2839 [](
const OutlinableGroup *
LHS,
const OutlinableGroup *
RHS) {
2840 return LHS->Benefit -
LHS->Cost >
RHS->Benefit -
RHS->Cost;
2843 std::vector<Function *> FuncsToRemove;
2844 for (OutlinableGroup *CG : NegativeCostGroups) {
2845 OutlinableGroup &CurrentGroup = *CG;
2847 OutlinedRegions.clear();
2848 for (OutlinableRegion *Region : CurrentGroup.
Regions) {
2851 if (!isCompatibleWithAlreadyOutlinedCode(*Region))
2853 OutlinedRegions.push_back(Region);
2856 if (OutlinedRegions.size() < 2)
2861 CurrentGroup.
Regions = std::move(OutlinedRegions);
2864 CurrentGroup.
Cost = 0;
2865 findCostBenefit(M, CurrentGroup);
2869 OutlinedRegions.clear();
2870 for (OutlinableRegion *Region : CurrentGroup.
Regions) {
2871 Region->splitCandidate();
2872 if (!
Region->CandidateSplit)
2874 OutlinedRegions.push_back(Region);
2877 CurrentGroup.
Regions = std::move(OutlinedRegions);
2878 if (CurrentGroup.
Regions.size() < 2) {
2879 for (OutlinableRegion *R : CurrentGroup.
Regions)
2880 R->reattachCandidate();
2885 <<
" and benefit " << CurrentGroup.
Benefit <<
"\n");
2888 OutlinedRegions.clear();
2889 for (OutlinableRegion *OS : CurrentGroup.
Regions) {
2891 DenseSet<BasicBlock *> BlocksInRegion;
2893 OS->
CE =
new (ExtractorAllocator.Allocate())
2894 CodeExtractor(BE,
nullptr,
false,
nullptr,
nullptr,
nullptr,
false,
2895 false,
nullptr, {},
"outlined");
2896 bool FunctionOutlined = extractSection(*OS);
2897 if (FunctionOutlined) {
2900 for (
unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
2901 Outlined.insert(Idx);
2903 OutlinedRegions.push_back(OS);
2908 <<
" with benefit " << CurrentGroup.
Benefit
2909 <<
" and cost " << CurrentGroup.
Cost <<
"\n");
2911 CurrentGroup.
Regions = std::move(OutlinedRegions);
2913 if (CurrentGroup.
Regions.empty())
2916 OptimizationRemarkEmitter &ORE =
2917 getORE(*CurrentGroup.
Regions[0]->Call->getFunction());
2919 IRSimilarityCandidate *
C = CurrentGroup.
Regions[0]->Candidate;
2920 OptimizationRemark
R(
DEBUG_TYPE,
"Outlined",
C->front()->Inst);
2921 R <<
"outlined " <<
ore::NV(std::to_string(CurrentGroup.
Regions.size()))
2922 <<
" regions with decrease of "
2924 <<
" instructions at locations ";
2927 [&R](OutlinableRegion *Region) {
2928 R << ore::NV(
"DebugLoc",
2929 Region->Candidate->frontInstruction()->getDebugLoc());
2931 [&R]() { R <<
" "; });
2935 deduplicateExtractedSections(M, CurrentGroup, FuncsToRemove,
2936 OutlinedFunctionNum);
2939 for (Function *
F : FuncsToRemove)
2940 F->eraseFromParent();
2942 return OutlinedFunctionNum;
2949 return doOutline(M) > 0;
2965 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 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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
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; assumes that the block is well-formed.
void splice(BasicBlock::iterator ToIt, BasicBlock *FromBB)
Transfer all instructions from FromBB to this basic block at ToIt.
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 void replaceSuccessorWith(BasicBlock *OldBB, BasicBlock *NewBB)
Replace specified successor OldBB to point at the provided block.
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_arg_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'.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
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.
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...