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) {
 
 2114    NewMap.
insert(std::make_pair(RetVal, NewBB));
 
 
 2143    for (std::pair<Value *, BasicBlock *> &RetBlockPair : ReturnBBs) {
 
 2144      std::pair<Value *, BasicBlock *> &OutputBlock =
 
 2145          *OG.
EndBBs.find(RetBlockPair.first);
 
 2146      BasicBlock *ReturnBlock = RetBlockPair.second;
 
 2151      Term->moveBefore(*ReturnBlock, ReturnBlock->
end());
 
 2154      LLVM_DEBUG(
dbgs() << 
"Create switch statement in " << *AggFunc << 
" for " 
 2155                        << OutputStoreBBs.
size() << 
"\n");
 
 2158                             ReturnBlock, OutputStoreBBs.
size(), EndBB);
 
 2163            OutputStoreBB.
find(OutputBlock.first);
 
 2165        if (OSBBIt == OutputStoreBB.
end())
 
 2172        Term->setSuccessor(0, ReturnBlock);
 
 2179  assert(OutputStoreBBs.size() < 2 && 
"Different store sets not handled!");
 
 2187  if (OutputStoreBBs.size() == 1) {
 
 2188    LLVM_DEBUG(
dbgs() << 
"Move store instructions to the end block in " 
 2191    for (std::pair<Value *, BasicBlock *> &VBPair : OutputBlocks) {
 
 2193          EndBBs.
find(VBPair.first);
 
 2194      assert(EndBBIt != EndBBs.
end() && 
"Could not find end block");
 
 2198      Term->eraseFromParent();
 
 2201      Term->moveBefore(*EndBB, EndBB->
end());
 
 
 2223    std::vector<Function *> &FuncsToRemove,
 
 2252    for (std::pair<Value *, BasicBlock *> &VToBB : NewBBs) {
 
 2254          CurrentGroup.
EndBBs.find(VToBB.first);
 
 2257      OutputStoreBBs.back().insert(VToBB);
 
 
 2269void IROutliner::deduplicateExtractedSections(
 
 2270    Module &M, OutlinableGroup &CurrentGroup,
 
 2271    std::vector<Function *> &FuncsToRemove, 
unsigned &OutlinedFunctionNum) {
 
 2272  createFunction(M, CurrentGroup, OutlinedFunctionNum);
 
 2274  std::vector<DenseMap<Value *, BasicBlock *>> OutputStoreBBs;
 
 2276  OutlinableRegion *CurrentOS;
 
 2281  for (
unsigned Idx = 1; Idx < CurrentGroup.
Regions.size(); Idx++) {
 
 2282    CurrentOS = CurrentGroup.
Regions[Idx];
 
 2283    AttributeFuncs::mergeAttributesForOutlining(*CurrentGroup.
OutlinedFunction,
 
 2288    DenseMap<Value *, BasicBlock *> NewBBs;
 
 2291        "output_block_" + Twine(
static_cast<unsigned>(Idx)));
 
 2294                                CurrentGroup.
EndBBs, OutputMappings,
 
 2304  OutlinedFunctionNum++;
 
 2321  IRInstructionDataList::iterator NextIDIt = std::next(
ID.getIterator());
 
 2324  if (!
ID.Inst->isTerminator())
 
 2325    NextModuleInst = 
ID.Inst->getNextNode();
 
 2326  else if (NextIDLInst != 
nullptr)
 
 2328        &*NextIDIt->Inst->
getParent()->instructionsWithoutDebug().begin();
 
 2330  if (NextIDLInst && NextIDLInst != NextModuleInst)
 
 
 2336bool IROutliner::isCompatibleWithAlreadyOutlinedCode(
 
 2338  IRSimilarityCandidate *IRSC = 
Region.Candidate;
 
 2344  for (
unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
 
 2345    if (Outlined.contains(Idx))
 
 2350  if (!
Region.Candidate->backInstruction()->isTerminator()) {
 
 2352        Region.Candidate->backInstruction()->getNextNode();
 
 2353    assert(NewEndInst && 
"Next instruction is a nullptr?");
 
 2354    if (
Region.Candidate->end()->Inst != NewEndInst) {
 
 2355      IRInstructionDataList *IDL = 
Region.Candidate->front()->IDL;
 
 2356      IRInstructionData *NewEndIRID = 
new (InstDataAllocator.Allocate())
 
 2357          IRInstructionData(*NewEndInst,
 
 2358                            InstructionClassifier.visit(*NewEndInst), *IDL);
 
 2366  return none_of(*IRSC, [
this](IRInstructionData &
ID) {
 
 2370    return !this->InstructionClassifier.visit(
ID.Inst);
 
 2374void IROutliner::pruneIncompatibleRegions(
 
 2375    std::vector<IRSimilarityCandidate> &CandidateVec,
 
 2376    OutlinableGroup &CurrentGroup) {
 
 2377  bool PreviouslyOutlined;
 
 2381                               const IRSimilarityCandidate &
RHS) {
 
 2382    return LHS.getStartIdx() < 
RHS.getStartIdx();
 
 2385  IRSimilarityCandidate &FirstCandidate = CandidateVec[0];
 
 2388  if (FirstCandidate.getLength() == 2) {
 
 2394  unsigned CurrentEndIdx = 0;
 
 2395  for (IRSimilarityCandidate &IRSC : CandidateVec) {
 
 2396    PreviouslyOutlined = 
false;
 
 2401    for (
unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
 
 2402      if (Outlined.contains(Idx)) {
 
 2403        PreviouslyOutlined = 
true;
 
 2407    if (PreviouslyOutlined)
 
 2412    bool BBHasAddressTaken = 
any_of(IRSC, [](IRInstructionData &
ID){
 
 2413      return ID.Inst->getParent()->hasAddressTaken();
 
 2416    if (BBHasAddressTaken)
 
 2424        dbgs() << 
"... Skipping function with nooutline attribute: " 
 2425               << FnForCurrCand.
getName() << 
"\n";
 
 2431        !OutlineFromLinkODRs)
 
 2436    if (CurrentEndIdx != 0 && StartIdx <= CurrentEndIdx)
 
 2439    bool BadInst = 
any_of(IRSC, [
this](IRInstructionData &
ID) {
 
 2443      return !this->InstructionClassifier.visit(
ID.Inst);
 
 2449    OutlinableRegion *OS = 
new (RegionAllocator.Allocate())
 
 2450        OutlinableRegion(IRSC, CurrentGroup);
 
 2451    CurrentGroup.
Regions.push_back(OS);
 
 2453    CurrentEndIdx = EndIdx;
 
 2458IROutliner::findBenefitFromAllRegions(OutlinableGroup &CurrentGroup) {
 
 2460  for (OutlinableRegion *Region : CurrentGroup.
Regions) {
 
 2461    TargetTransformInfo &
TTI = getTTI(*
Region->StartBB->getParent());
 
 2464    RegionBenefit += 
Region->getBenefit(
TTI);
 
 2466                      << 
" saved instructions to overfall benefit.\n");
 
 2469  return RegionBenefit;
 
 2481                                      unsigned OutputCanon) {
 
 2489           "Could not find GVN set for PHINode number!");
 
 2490    assert(It->second.second.size() > 0 && 
"PHINode does not have any values!");
 
 2491    OutputCanon = *It->second.second.begin();
 
 2493  std::optional<unsigned> OGVN =
 
 2494      Region.Candidate->fromCanonicalNum(OutputCanon);
 
 2495  assert(OGVN && 
"Could not find GVN for Canonical Number?");
 
 2496  std::optional<Value *> OV = 
Region.Candidate->fromGVN(*OGVN);
 
 2497  assert(OV && 
"Could not find value for GVN?");
 
 
 2502IROutliner::findCostOutputReloads(OutlinableGroup &CurrentGroup) {
 
 2504  for (OutlinableRegion *Region : CurrentGroup.
Regions) {
 
 2505    TargetTransformInfo &
TTI = getTTI(*
Region->StartBB->getParent());
 
 2508    for (
unsigned OutputCanon : 
Region->GVNStores) {
 
 2515                        << 
" instructions to cost for output of type " 
 2516                        << *
V->getType() << 
"\n");
 
 2517      OverallCost += LoadCost;
 
 2536  unsigned NumOutputBranches = 0;
 
 2550    for (
Value *V : 
ID.OperVals) {
 
 2552      if (!CandidateBlocks.
contains(BB) && FoundBlocks.
insert(BB).second)
 
 2553        NumOutputBranches++;
 
 2561    for (
unsigned OutputCanon : OutputUse) {
 
 2564          TTI.getMemoryOpCost(Instruction::Load, V->getType(), 
Align(1), 0,
 
 2571                        << 
" instructions to cost for output of type " 
 2572                        << *V->getType() << 
"\n");
 
 2573      OutputCost += StoreCost * NumOutputBranches;
 
 2578    LLVM_DEBUG(
dbgs() << 
"Adding " << BranchCost << 
" to the current cost for" 
 2579                      << 
" a branch instruction\n");
 
 2580    OutputCost += BranchCost * NumOutputBranches;
 
 2594    InstructionCost TotalCost = ComparisonCost * BranchCost * DifferentBlocks;
 
 2597                      << 
" instructions for each switch case for each different" 
 2598                      << 
" output path in a function\n");
 
 2599    OutputCost += TotalCost * NumOutputBranches;
 
 
 2605void IROutliner::findCostBenefit(
Module &M, OutlinableGroup &CurrentGroup) {
 
 2606  InstructionCost RegionBenefit = findBenefitFromAllRegions(CurrentGroup);
 
 2607  CurrentGroup.
Benefit += RegionBenefit;
 
 2610  InstructionCost OutputReloadCost = findCostOutputReloads(CurrentGroup);
 
 2611  CurrentGroup.
Cost += OutputReloadCost;
 
 2615      RegionBenefit / CurrentGroup.
Regions.size();
 
 2616  unsigned OverallArgumentNum = CurrentGroup.
ArgumentTypes.size();
 
 2617  unsigned NumRegions = CurrentGroup.
Regions.size();
 
 2618  TargetTransformInfo &
TTI =
 
 2619      getTTI(*CurrentGroup.
Regions[0]->Candidate->getFunction());
 
 2624                    << 
" instructions to cost for body of new function.\n");
 
 2625  CurrentGroup.
Cost += AverageRegionBenefit;
 
 2631                    << 
" instructions to cost for each argument in the new" 
 2633  CurrentGroup.
Cost +=
 
 2641                    << 
" instructions to cost for each argument in the new" 
 2642                    << 
" function " << NumRegions << 
" times for the " 
 2643                    << 
"needed argument handling at the call site.\n");
 
 2644  CurrentGroup.
Cost +=
 
 2657  std::optional<unsigned> OutputIdx;
 
 2659  for (
unsigned ArgIdx = 
Region.NumExtractedInputs;
 
 2660       ArgIdx < Region.Call->arg_size(); ArgIdx++) {
 
 2661    if (Operand == 
Region.Call->getArgOperand(ArgIdx)) {
 
 2662      OutputIdx = ArgIdx - 
Region.NumExtractedInputs;
 
 2672  auto It = OutputMappings.find(Outputs[*OutputIdx]);
 
 2673  if (It == OutputMappings.end()) {
 
 2674    LLVM_DEBUG(
dbgs() << 
"Mapping extracted output " << *LI << 
" to " 
 2675                      << *Outputs[*OutputIdx] << 
"\n");
 
 2676    OutputMappings.insert(std::make_pair(LI, Outputs[*OutputIdx]));
 
 2678    Value *Orig = It->second;
 
 2679    LLVM_DEBUG(
dbgs() << 
"Mapping extracted output " << *Orig << 
" to " 
 2680                      << *Outputs[*OutputIdx] << 
"\n");
 
 2681    OutputMappings.insert(std::make_pair(LI, Orig));
 
 2686  SetVector<Value *> ArgInputs, Outputs;
 
 2687  assert(
Region.StartBB && 
"StartBB for the OutlinableRegion is nullptr!");
 
 2690  CodeExtractorAnalysisCache CEAC(*OrigF);
 
 2691  Region.ExtractedFunction =
 
 2692      Region.CE->extractCodeRegion(CEAC, ArgInputs, Outputs);
 
 2696  if (!
Region.ExtractedFunction) {
 
 2699    Region.reattachCandidate();
 
 2707  User *InstAsUser = 
Region.ExtractedFunction->user_back();
 
 2711  if (
Region.PrevBB == InitialStart) {
 
 2720  Region.StartBB = RewrittenBB;
 
 2721  Region.EndBB = RewrittenBB;
 
 2728  IRInstructionDataList *IDL = 
Region.Candidate->front()->IDL;
 
 2731  Region.NewFront = 
new (InstDataAllocator.Allocate()) IRInstructionData(
 
 2732      *BeginRewritten, InstructionClassifier.visit(*BeginRewritten), *IDL);
 
 2733  Region.NewBack = 
new (InstDataAllocator.Allocate()) IRInstructionData(
 
 2734      *EndRewritten, InstructionClassifier.visit(*EndRewritten), *IDL);
 
 2745  assert(RewrittenBB != 
nullptr &&
 
 2746         "Could not find a predecessor after extraction!");
 
 2750  for (Instruction &
I : *RewrittenBB)
 
 2752      if (
Region.ExtractedFunction == CI->getCalledFunction())
 
 2755      updateOutputMapping(Region, Outputs.
getArrayRef(), LI);
 
 2756  Region.reattachCandidate();
 
 2760unsigned IROutliner::doOutline(
Module &M) {
 
 2766  IRSimilarityIdentifier &
Identifier = getIRSI(M);
 
 2770  unsigned OutlinedFunctionNum = 0;
 
 2773  if (SimilarityCandidates.size() > 1)
 
 2775                      [](
const std::vector<IRSimilarityCandidate> &
LHS,
 
 2776                         const std::vector<IRSimilarityCandidate> &
RHS) {
 
 2777                        return LHS[0].getLength() * 
LHS.size() >
 
 2778                               RHS[0].getLength() * 
RHS.size();
 
 2782  std::vector<OutlinableGroup> PotentialGroups(SimilarityCandidates.size());
 
 2784  DenseSet<unsigned> NotSame;
 
 2785  std::vector<OutlinableGroup *> NegativeCostGroups;
 
 2786  std::vector<OutlinableRegion *> OutlinedRegions;
 
 2788  unsigned PotentialGroupIdx = 0;
 
 2790    OutlinableGroup &CurrentGroup = PotentialGroups[PotentialGroupIdx++];
 
 2793    pruneIncompatibleRegions(CandidateVec, CurrentGroup);
 
 2798    if (CurrentGroup.
Regions.size() < 2)
 
 2812    OutlinedRegions.clear();
 
 2813    for (OutlinableRegion *OS : CurrentGroup.
Regions) {
 
 2825      DenseSet<BasicBlock *> BlocksInRegion;
 
 2827      OS->
CE = 
new (ExtractorAllocator.Allocate())
 
 2828          CodeExtractor(BE, 
nullptr, 
false, 
nullptr, 
nullptr, 
nullptr, 
false,
 
 2829                        false, 
nullptr, 
"outlined");
 
 2830      findAddInputsOutputs(M, *OS, NotSame);
 
 2832        OutlinedRegions.push_back(OS);
 
 2839    CurrentGroup.
Regions = std::move(OutlinedRegions);
 
 2841    if (CurrentGroup.
Regions.empty())
 
 2847      findCostBenefit(M, CurrentGroup);
 
 2851    if (CurrentGroup.
Cost >= CurrentGroup.
Benefit && CostModel) {
 
 2852      OptimizationRemarkEmitter &ORE =
 
 2853          getORE(*CurrentGroup.
Regions[0]->Candidate->getFunction());
 
 2855        IRSimilarityCandidate *
C = CurrentGroup.
Regions[0]->Candidate;
 
 2856        OptimizationRemarkMissed 
R(
DEBUG_TYPE, 
"WouldNotDecreaseSize",
 
 2857                                   C->frontInstruction());
 
 2858        R << 
"did not outline " 
 2860          << 
" regions due to estimated increase of " 
 2861          << 
ore::NV(
"InstructionIncrease",
 
 2863          << 
" instructions at locations ";
 
 2866            [&R](OutlinableRegion *Region) {
 
 2869                  Region->Candidate->frontInstruction()->getDebugLoc());
 
 2871            [&R]() { R << 
" "; });
 
 2877    NegativeCostGroups.push_back(&CurrentGroup);
 
 2880  ExtractorAllocator.DestroyAll();
 
 2882  if (NegativeCostGroups.size() > 1)
 
 2884                [](
const OutlinableGroup *
LHS, 
const OutlinableGroup *
RHS) {
 
 2885                  return LHS->Benefit - 
LHS->Cost > 
RHS->Benefit - 
RHS->Cost;
 
 2888  std::vector<Function *> FuncsToRemove;
 
 2889  for (OutlinableGroup *CG : NegativeCostGroups) {
 
 2890    OutlinableGroup &CurrentGroup = *CG;
 
 2892    OutlinedRegions.clear();
 
 2893    for (OutlinableRegion *Region : CurrentGroup.
Regions) {
 
 2896      if (!isCompatibleWithAlreadyOutlinedCode(*Region))
 
 2898      OutlinedRegions.push_back(Region);
 
 2901    if (OutlinedRegions.size() < 2)
 
 2906    CurrentGroup.
Regions = std::move(OutlinedRegions);
 
 2909      CurrentGroup.
Cost = 0;
 
 2910      findCostBenefit(M, CurrentGroup);
 
 2914    OutlinedRegions.clear();
 
 2915    for (OutlinableRegion *Region : CurrentGroup.
Regions) {
 
 2916      Region->splitCandidate();
 
 2917      if (!
Region->CandidateSplit)
 
 2919      OutlinedRegions.push_back(Region);
 
 2922    CurrentGroup.
Regions = std::move(OutlinedRegions);
 
 2923    if (CurrentGroup.
Regions.size() < 2) {
 
 2924      for (OutlinableRegion *R : CurrentGroup.
Regions)
 
 2925        R->reattachCandidate();
 
 2930                      << 
" and benefit " << CurrentGroup.
Benefit << 
"\n");
 
 2933    OutlinedRegions.clear();
 
 2934    for (OutlinableRegion *OS : CurrentGroup.
Regions) {
 
 2936      DenseSet<BasicBlock *> BlocksInRegion;
 
 2938      OS->
CE = 
new (ExtractorAllocator.Allocate())
 
 2939          CodeExtractor(BE, 
nullptr, 
false, 
nullptr, 
nullptr, 
nullptr, 
false,
 
 2940                        false, 
nullptr, 
"outlined");
 
 2941      bool FunctionOutlined = extractSection(*OS);
 
 2942      if (FunctionOutlined) {
 
 2945        for (
unsigned Idx = StartIdx; Idx <= EndIdx; Idx++)
 
 2946          Outlined.insert(Idx);
 
 2948        OutlinedRegions.push_back(OS);
 
 2953                      << 
" with benefit " << CurrentGroup.
Benefit 
 2954                      << 
" and cost " << CurrentGroup.
Cost << 
"\n");
 
 2956    CurrentGroup.
Regions = std::move(OutlinedRegions);
 
 2958    if (CurrentGroup.
Regions.empty())
 
 2961    OptimizationRemarkEmitter &ORE =
 
 2962        getORE(*CurrentGroup.
Regions[0]->Call->getFunction());
 
 2964      IRSimilarityCandidate *
C = CurrentGroup.
Regions[0]->Candidate;
 
 2965      OptimizationRemark 
R(
DEBUG_TYPE, 
"Outlined", 
C->front()->Inst);
 
 2966      R << 
"outlined " << 
ore::NV(std::to_string(CurrentGroup.
Regions.size()))
 
 2967        << 
" regions with decrease of " 
 2969        << 
" instructions at locations ";
 
 2972          [&R](OutlinableRegion *Region) {
 
 2973            R << ore::NV(
"DebugLoc",
 
 2974                         Region->Candidate->frontInstruction()->getDebugLoc());
 
 2976          [&R]() { R << 
" "; });
 
 2980    deduplicateExtractedSections(M, CurrentGroup, FuncsToRemove,
 
 2981                                 OutlinedFunctionNum);
 
 2984  for (Function *
F : FuncsToRemove)
 
 2985    F->eraseFromParent();
 
 2987  return OutlinedFunctionNum;
 
 2994  return doOutline(M) > 0;
 
 
 3010  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...