LLVM: lib/Transforms/IPO/PartialInlining.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

54#include

55#include

56#include

57#include

58#include

59#include

60

61using namespace llvm;

62

63#define DEBUG_TYPE "partial-inlining"

64

66 "Number of callsites functions partially inlined into.");

67STATISTIC(NumColdOutlinePartialInlined, "Number of times functions with "

68 "cold outlined regions were partially "

69 "inlined into its caller(s).");

71 "Number of cold single entry/exit regions found.");

73 "Number of cold single entry/exit regions outlined.");

74

75

79

80

83 cl::desc("Disable multi-region partial inlining"));

84

85

86

89 cl::desc("Force outline regions with live exits"));

90

91

92

95 cl::desc("Mark outline function calls with ColdCC"));

96

97

99

101 cl::desc("Skip Cost Analysis"));

102

103

104

105

108 cl::desc("Minimum ratio comparing relative sizes of each "

109 "outline candidate and original function"));

110

111

114 cl::desc("Minimum block executions to consider "

115 "its BranchProbabilityInfo valid"));

116

117

120 cl::desc("Minimum BranchProbability to consider a region cold."));

121

124 cl::desc("Max number of blocks to be partially inlined"));

125

126

127

130 cl::desc("Max number of partial inlining. The default is unlimited"));

131

132

133

134

138 cl::desc("Relative frequency of outline region to "

139 "the entry block"));

140

143 cl::desc("A debug option to add additional penalty to the computed one."));

144

145namespace {

146

147struct FunctionOutliningInfo {

148 FunctionOutliningInfo() = default;

149

150

151

152 unsigned getNumInlinedBlocks() const { return Entries.size() + 1; }

153

154

155

157

158

160

161

162 BasicBlock *NonReturnBlock = nullptr;

163

164

166};

167

168struct FunctionOutliningMultiRegionInfo {

169 FunctionOutliningMultiRegionInfo() = default;

170

171

172 struct OutlineRegionInfo {

174 BasicBlock *ExitBlock, BasicBlock *ReturnBlock)

175 : Region(Region), EntryBlock(EntryBlock), ExitBlock(ExitBlock),

176 ReturnBlock(ReturnBlock) {}

177 SmallVector<BasicBlock *, 8> Region;

181 };

182

184};

185

186struct PartialInlinerImpl {

187

188 PartialInlinerImpl(

189 function_ref<AssumptionCache &(Function &)> GetAC,

190 function_ref<AssumptionCache *(Function &)> LookupAC,

191 function_ref<TargetTransformInfo &(Function &)> GTTI,

192 function_ref<const TargetLibraryInfo &(Function &)> GTLI,

193 ProfileSummaryInfo &ProfSI,

194 function_ref<BlockFrequencyInfo &(Function &)> GBFI = nullptr)

195 : GetAssumptionCache(GetAC), LookupAssumptionCache(LookupAC),

196 GetTTI(GTTI), GetBFI(GBFI), GetTLI(GTLI), PSI(ProfSI) {}

197

199

200

201

202

203

204

205

206 std::pair<bool, Function *> unswitchFunction(Function &F);

207

208

209

210

211

212 struct FunctionCloner {

213

214

215 FunctionCloner(Function *F, FunctionOutliningInfo *OI,

216 OptimizationRemarkEmitter &ORE,

217 function_ref<AssumptionCache *(Function &)> LookupAC,

218 function_ref<TargetTransformInfo &(Function &)> GetTTI);

219 FunctionCloner(Function *F, FunctionOutliningMultiRegionInfo *OMRI,

220 OptimizationRemarkEmitter &ORE,

221 function_ref<AssumptionCache *(Function &)> LookupAC,

222 function_ref<TargetTransformInfo &(Function &)> GetTTI);

223

224 ~FunctionCloner();

225

226

227

228

229 void normalizeReturnBlock() const;

230

231

232 bool doMultiRegionFunctionOutlining();

233

234

235

236

237

238

239 Function *doSingleRegionFunctionOutlining();

240

241 Function *OrigFunc = nullptr;

242 Function *ClonedFunc = nullptr;

243

244 typedef std::pair<Function *, BasicBlock *> FuncBodyCallerPair;

245

247

248

249

250 bool IsFunctionInlined = false;

251

253

254 std::unique_ptr ClonedOI = nullptr;

255

256 std::unique_ptr ClonedOMRI = nullptr;

257 std::unique_ptr ClonedFuncBFI = nullptr;

258 OptimizationRemarkEmitter &ORE;

259 function_ref<AssumptionCache *(Function &)> LookupAC;

260 function_ref<TargetTransformInfo &(Function &)> GetTTI;

261 };

262

263private:

264 int NumPartialInlining = 0;

265 function_ref<AssumptionCache &(Function &)> GetAssumptionCache;

266 function_ref<AssumptionCache *(Function &)> LookupAssumptionCache;

267 function_ref<TargetTransformInfo &(Function &)> GetTTI;

268 function_ref<BlockFrequencyInfo &(Function &)> GetBFI;

269 function_ref<const TargetLibraryInfo &(Function &)> GetTLI;

270 ProfileSummaryInfo &PSI;

271

272

273

274

275

276 BranchProbability

277 getOutliningCallBBRelativeFreq(FunctionCloner &Cloner) const;

278

279

280

281 bool shouldPartialInline(CallBase &CB, FunctionCloner &Cloner,

282 BlockFrequency WeightedOutliningRcost,

283 OptimizationRemarkEmitter &ORE) const;

284

285

286

287

288 bool tryPartialInline(FunctionCloner &Cloner);

289

290

291

292 void

293 computeCallsiteToProfCountMap(Function *DuplicateFunction,

294 DenseMap<User *, uint64_t> &SiteCountMap) const;

295

296 bool isLimitReached() const {

299 }

300

301 static CallBase *getSupportedCallBase(User *U) {

305 return nullptr;

306 }

307

308 static CallBase *getOneCallSiteTo(Function &F) {

310 return getSupportedCallBase(User);

311 }

312

313 std::tuple<DebugLoc, BasicBlock *> getOneDebugLoc(Function &F) const {

314 CallBase *CB = getOneCallSiteTo(F);

317 return std::make_tuple(DLoc, Block);

318 }

319

320

321

322

323

324

325

326 std::tuple<InstructionCost, InstructionCost>

327 computeOutliningCosts(FunctionCloner &Cloner) const;

328

329

330

331

332 static InstructionCost computeBBInlineCost(BasicBlock *BB,

333 TargetTransformInfo *TTI);

334

335 std::unique_ptr

336 computeOutliningInfo(Function &F) const;

337

338 std::unique_ptr

339 computeOutliningColdRegionsInfo(Function &F,

340 OptimizationRemarkEmitter &ORE) const;

341};

342

343}

344

345std::unique_ptr

346PartialInlinerImpl::computeOutliningColdRegionsInfo(

349

350 DominatorTree DT(F);

351 LoopInfo LI(DT);

352 BranchProbabilityInfo BPI(F, LI);

353 std::unique_ptr ScopedBFI;

354 BlockFrequencyInfo *BFI;

355 if (!GetBFI) {

356 ScopedBFI.reset(new BlockFrequencyInfo(F, BPI, LI));

357 BFI = ScopedBFI.get();

358 } else

359 BFI = &(GetBFI(F));

360

361

362 if (!PSI.hasInstrumentationProfile())

363 return std::unique_ptr();

364

365 std::unique_ptr OutliningInfo =

366 std::make_unique();

367

368 auto IsSingleExit =

369 [&ORE](SmallVectorImpl<BasicBlock *> &BlockList) -> BasicBlock * {

371 for (auto *Block : BlockList) {

374 if (ExitBlock) {

375 ORE.emit([&]() {

376 return OptimizationRemarkMissed(DEBUG_TYPE, "MultiExitRegion",

377 &Succ->front())

378 << "Region dominated by "

379 << ore::NV("Block", BlockList.front()->getName())

380 << " has more than one region exit edge.";

381 });

382 return nullptr;

383 }

384

385 ExitBlock = Block;

386 }

387 }

388 }

389 return ExitBlock;

390 };

391

392 auto BBProfileCount = [BFI](BasicBlock *BB) {

394 };

395

396

397

398 TargetTransformInfo *FTTI = &GetTTI(F);

400 for (auto &BB : F)

401 OverallFunctionCost += computeBBInlineCost(&BB, FTTI);

402

403 LLVM_DEBUG(dbgs() << "OverallFunctionCost = " << OverallFunctionCost

404 << "\n";);

405

408

409 BranchProbability MinBranchProbability(

412 bool ColdCandidateFound = false;

414 std::vector<BasicBlock *> DFS;

415 SmallPtrSet<BasicBlock *, 8> VisitedSet;

416 DFS.push_back(CurrEntry);

417 VisitedSet.insert(CurrEntry);

418

419

420

421

422

423

424

425 while (!DFS.empty()) {

426 auto *ThisBB = DFS.back();

427 DFS.pop_back();

428

429

430

431 if (PSI.isColdBlock(ThisBB, BFI) ||

433 continue;

435 if (!VisitedSet.insert(*SI).second)

436 continue;

437 DFS.push_back(*SI);

438

439 BranchProbability SuccProb = BPI.getEdgeProbability(ThisBB, *SI);

440 if (SuccProb > MinBranchProbability)

441 continue;

442

443 LLVM_DEBUG(dbgs() << "Found cold edge: " << ThisBB->getName() << "->"

444 << SI->getName()

445 << "\nBranch Probability = " << SuccProb << "\n";);

446

447 SmallVector<BasicBlock *, 8> DominateVector;

448 DT.getDescendants(*SI, DominateVector);

450 "SI should be reachable and have at least itself as descendant");

451

452

453 if (!DominateVector.front()->hasNPredecessors(1)) {

455 << " doesn't have a single predecessor in the "

456 "dominator tree\n";);

457 continue;

458 }

459

461

462 if (!(ExitBlock = IsSingleExit(DominateVector))) {

464 << " doesn't have a unique successor\n";);

465 continue;

466 }

467

469 for (auto *BB : DominateVector)

470 OutlineRegionCost += computeBBInlineCost(BB, &GetTTI(*BB->getParent()));

471

472 LLVM_DEBUG(dbgs() << "OutlineRegionCost = " << OutlineRegionCost

473 << "\n";);

474

475 if (SkipCostAnalysis && OutlineRegionCost < MinOutlineRegionCost) {

476 ORE.emit([&]() {

477 return OptimizationRemarkAnalysis(DEBUG_TYPE, "TooCostly",

478 &SI->front())

480 << " inline cost-savings smaller than "

481 << ore::NV("Cost", MinOutlineRegionCost);

482 });

483

484 LLVM_DEBUG(dbgs() << "ABORT: Outline region cost is smaller than "

485 << MinOutlineRegionCost << "\n";);

486 continue;

487 }

488

489

490

491

492

494

495

497 FunctionOutliningMultiRegionInfo::OutlineRegionInfo RegInfo(

498 DominateVector, DominateVector.front(), ExitBlock, ReturnBlock);

499 OutliningInfo->ORI.push_back(RegInfo);

500 LLVM_DEBUG(dbgs() << "Found Cold Candidate starting at block: "

501 << DominateVector.front()->getName() << "\n";);

502 ColdCandidateFound = true;

503 NumColdRegionsFound++;

504 }

505 }

506

507 if (ColdCandidateFound)

508 return OutliningInfo;

509

510 return std::unique_ptr();

511}

512

513std::unique_ptr

514PartialInlinerImpl::computeOutliningInfo(Function &F) const {

518 return std::unique_ptr();

519

520

523 };

524

525 auto IsReturnBlock = [](BasicBlock *BB) {

528 };

529

531 if (IsReturnBlock(Succ1))

532 return std::make_tuple(Succ1, Succ2);

533 if (IsReturnBlock(Succ2))

534 return std::make_tuple(Succ2, Succ1);

535

536 return std::make_tuple<BasicBlock *, BasicBlock *>(nullptr, nullptr);

537 };

538

539

541 if (IsSuccessor(Succ1, Succ2))

542 return std::make_tuple(Succ1, Succ2);

543 if (IsSuccessor(Succ2, Succ1))

544 return std::make_tuple(Succ2, Succ1);

545

546 return std::make_tuple<BasicBlock *, BasicBlock *>(nullptr, nullptr);

547 };

548

549 std::unique_ptr OutliningInfo =

550 std::make_unique();

551

553 bool CandidateFound = false;

554 do {

555

556

557

559 break;

560

562 break;

563

566

567 BasicBlock *ReturnBlock, *NonReturnBlock;

568 std::tie(ReturnBlock, NonReturnBlock) = GetReturnBlock(Succ1, Succ2);

569

570 if (ReturnBlock) {

571 OutliningInfo->Entries.push_back(CurrEntry);

572 OutliningInfo->ReturnBlock = ReturnBlock;

573 OutliningInfo->NonReturnBlock = NonReturnBlock;

574 CandidateFound = true;

575 break;

576 }

577

579 std::tie(CommSucc, OtherSucc) = GetCommonSucc(Succ1, Succ2);

580

581 if (!CommSucc)

582 break;

583

584 OutliningInfo->Entries.push_back(CurrEntry);

586 } while (true);

587

588 if (!CandidateFound)

589 return std::unique_ptr();

590

591

592

593 assert(OutliningInfo->Entries[0] == &F.front() &&

594 "Function Entry must be the first in Entries vector");

595 DenseSet<BasicBlock *> Entries(llvm::from_range, OutliningInfo->Entries);

596

597

598

599 auto HasNonEntryPred = [Entries](BasicBlock *BB) {

601 if (!Entries.count(Pred))

602 return true;

603 }

604 return false;

605 };

606 auto CheckAndNormalizeCandidate =

607 [Entries, HasNonEntryPred](FunctionOutliningInfo *OutliningInfo) {

608 for (BasicBlock *E : OutliningInfo->Entries) {

610 if (Entries.count(Succ))

611 continue;

612 if (Succ == OutliningInfo->ReturnBlock)

613 OutliningInfo->ReturnBlockPreds.push_back(E);

614 else if (Succ != OutliningInfo->NonReturnBlock)

615 return false;

616 }

617

618 if (HasNonEntryPred(E))

619 return false;

620 }

621 return true;

622 };

623

624 if (!CheckAndNormalizeCandidate(OutliningInfo.get()))

625 return std::unique_ptr();

626

627

628

630 BasicBlock *Cand = OutliningInfo->NonReturnBlock;

632 break;

633

634 if (HasNonEntryPred(Cand))

635 break;

636

639

640 BasicBlock *ReturnBlock, *NonReturnBlock;

641 std::tie(ReturnBlock, NonReturnBlock) = GetReturnBlock(Succ1, Succ2);

642 if (!ReturnBlock || ReturnBlock != OutliningInfo->ReturnBlock)

643 break;

644

646 break;

647

648

649 OutliningInfo->Entries.push_back(Cand);

650 OutliningInfo->NonReturnBlock = NonReturnBlock;

651 OutliningInfo->ReturnBlockPreds.push_back(Cand);

652 Entries.insert(Cand);

653 }

654

655 return OutliningInfo;

656}

657

658

660 if (F.hasProfileData())

661 return true;

662

663 for (auto *E : OI.Entries) {

666 continue;

668 return true;

669 }

670 return false;

671}

672

673BranchProbability PartialInlinerImpl::getOutliningCallBBRelativeFreq(

674 FunctionCloner &Cloner) const {

675 BasicBlock *OutliningCallBB = Cloner.OutlinedFunctions.back().second;

676 auto EntryFreq =

677 Cloner.ClonedFuncBFI->getBlockFreq(&Cloner.ClonedFunc->getEntryBlock());

678 auto OutliningCallFreq =

679 Cloner.ClonedFuncBFI->getBlockFreq(OutliningCallBB);

680

681

682

683 if (OutliningCallFreq.getFrequency() > EntryFreq.getFrequency())

684 OutliningCallFreq = EntryFreq;

685

687 OutliningCallFreq.getFrequency(), EntryFreq.getFrequency());

688

689 if (hasProfileData(*Cloner.OrigFunc, *Cloner.ClonedOI))

690 return OutlineRegionRelFreq;

691

692

693

694

695

696

697

698

699

700

701

702

703

704 if (OutlineRegionRelFreq < BranchProbability(45, 100))

705 return OutlineRegionRelFreq;

706

707 OutlineRegionRelFreq = std::max(

709

710 return OutlineRegionRelFreq;

711}

712

713bool PartialInlinerImpl::shouldPartialInline(

714 CallBase &CB, FunctionCloner &Cloner, BlockFrequency WeightedOutliningRcost,

715 OptimizationRemarkEmitter &ORE) const {

716 using namespace ore;

717

719 assert(Callee == Cloner.ClonedFunc);

720

723

725 auto &CalleeTTI = GetTTI(*Callee);

726 bool RemarksEnabled =

727 Callee->getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(

729 InlineCost IC =

731 GetTLI, GetBFI, &PSI, RemarksEnabled ? &ORE : nullptr);

732

734 ORE.emit([&]() {

735 return OptimizationRemarkAnalysis(DEBUG_TYPE, "AlwaysInline", &CB)

736 << NV("Callee", Cloner.OrigFunc)

737 << " should always be fully inlined, not partially";

738 });

739 return false;

740 }

741

743 ORE.emit([&]() {

744 return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", &CB)

745 << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "

746 << NV("Caller", Caller)

747 << " because it should never be inlined (cost=never)";

748 });

749 return false;

750 }

751

752 if (!IC) {

753 ORE.emit([&]() {

754 return OptimizationRemarkAnalysis(DEBUG_TYPE, "TooCostly", &CB)

755 << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "

756 << NV("Caller", Caller) << " because too costly to inline (cost="

757 << NV("Cost", IC.getCost()) << ", threshold="

759 });

760 return false;

761 }

762 const DataLayout &DL = Caller->getDataLayout();

763

764

766 BlockFrequency NormWeightedSavings(NonWeightedSavings);

767

768

769 if (NormWeightedSavings < WeightedOutliningRcost) {

770 ORE.emit([&]() {

771 return OptimizationRemarkAnalysis(DEBUG_TYPE, "OutliningCallcostTooHigh",

772 &CB)

773 << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "

774 << NV("Caller", Caller) << " runtime overhead (overhead="

775 << NV("Overhead", (unsigned)WeightedOutliningRcost.getFrequency())

776 << ", savings="

777 << NV("Savings", (unsigned)NormWeightedSavings.getFrequency())

778 << ")"

779 << " of making the outlined call is too high";

780 });

781

782 return false;

783 }

784

785 ORE.emit([&]() {

786 return OptimizationRemarkAnalysis(DEBUG_TYPE, "CanBePartiallyInlined", &CB)

787 << NV("Callee", Cloner.OrigFunc) << " can be partially inlined into "

788 << NV("Caller", Caller) << " with cost=" << NV("Cost", IC.getCost())

789 << " (threshold="

791 });

792 return true;

793}

794

795

796

797

799PartialInlinerImpl::computeBBInlineCost(BasicBlock *BB,

800 TargetTransformInfo *TTI) {

805

806 switch (I.getOpcode()) {

807 case Instruction::BitCast:

808 case Instruction::PtrToInt:

809 case Instruction::IntToPtr:

810 case Instruction::Alloca:

811 case Instruction::PHI:

812 continue;

813 case Instruction::GetElementPtr:

815 continue;

816 break;

817 default:

818 break;

819 }

820

821 if (I.isLifetimeStartOrEnd())

822 continue;

823

827 FastMathFlags FMF;

828 for (Value *Val : II->args())

830

832 FMF = FPMO->getFastMathFlags();

833

834 IntrinsicCostAttributes ICA(IID, II->getType(), Tys, FMF);

836 continue;

837 }

838

841 continue;

842 }

843

846 continue;

847 }

848

850 InlineCost += (SI->getNumCases() + 1) * InstrCost;

851 continue;

852 }

854 }

855

856 return InlineCost;

857}

858

859std::tuple<InstructionCost, InstructionCost>

860PartialInlinerImpl::computeOutliningCosts(FunctionCloner &Cloner) const {

861 InstructionCost OutliningFuncCallCost = 0, OutlinedFunctionCost = 0;

862 for (auto FuncBBPair : Cloner.OutlinedFunctions) {

863 Function *OutlinedFunc = FuncBBPair.first;

864 BasicBlock* OutliningCallBB = FuncBBPair.second;

865

866

867 auto *OutlinedFuncTTI = &GetTTI(*OutlinedFunc);

868 OutliningFuncCallCost +=

869 computeBBInlineCost(OutliningCallBB, OutlinedFuncTTI);

870

871

872 for (BasicBlock &BB : *OutlinedFunc)

873 OutlinedFunctionCost += computeBBInlineCost(&BB, OutlinedFuncTTI);

874 }

875 assert(OutlinedFunctionCost >= Cloner.OutlinedRegionCost &&

876 "Outlined function cost should be no less than the outlined region");

877

878

879

880

881 OutlinedFunctionCost -=

883

885 OutliningFuncCallCost +

886 (OutlinedFunctionCost - Cloner.OutlinedRegionCost) +

888

889 return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead);

890}

891

892

893

894

895void PartialInlinerImpl::computeCallsiteToProfCountMap(

896 Function *DuplicateFunction,

897 DenseMap<User *, uint64_t> &CallSiteToProfCountMap) const {

898 std::vector<User *> Users(DuplicateFunction->user_begin(),

899 DuplicateFunction->user_end());

900 Function *CurrentCaller = nullptr;

901 std::unique_ptr TempBFI;

902 BlockFrequencyInfo *CurrentCallerBFI = nullptr;

903

905

906 if (!GetBFI) {

907 DominatorTree DT(*Caller);

908 LoopInfo LI(DT);

909 BranchProbabilityInfo BPI(*Caller, LI);

910 TempBFI.reset(new BlockFrequencyInfo(*Caller, BPI, LI));

911 CurrentCallerBFI = TempBFI.get();

912 } else {

913

914 CurrentCallerBFI = &(GetBFI(*Caller));

915 }

916 };

917

918 for (User *User : Users) {

919 CallBase *CB = getSupportedCallBase(User);

921 if (CurrentCaller != Caller) {

922 CurrentCaller = Caller;

923 ComputeCurrBFI(Caller);

924 } else {

925 assert(CurrentCallerBFI && "CallerBFI is not set");

926 }

930 CallSiteToProfCountMap[User] = *Count;

931 else

932 CallSiteToProfCountMap[User] = 0;

933 }

934}

935

936PartialInlinerImpl::FunctionCloner::FunctionCloner(

937 Function *F, FunctionOutliningInfo *OI, OptimizationRemarkEmitter &ORE,

938 function_ref<AssumptionCache *(Function &)> LookupAC,

939 function_ref<TargetTransformInfo &(Function &)> GetTTI)

940 : OrigFunc(F), ORE(ORE), LookupAC(LookupAC), GetTTI(GetTTI) {

941 ClonedOI = std::make_unique();

942

943

946

947 ClonedOI->ReturnBlock = cast(VMap[OI->ReturnBlock]);

948 ClonedOI->NonReturnBlock = cast(VMap[OI->NonReturnBlock]);

951

952 for (BasicBlock *E : OI->ReturnBlockPreds) {

954 ClonedOI->ReturnBlockPreds.push_back(NewE);

955 }

956

957

958 F->replaceAllUsesWith(ClonedFunc);

959}

960

961PartialInlinerImpl::FunctionCloner::FunctionCloner(

962 Function *F, FunctionOutliningMultiRegionInfo *OI,

966 : OrigFunc(F), ORE(ORE), LookupAC(LookupAC), GetTTI(GetTTI) {

967 ClonedOMRI = std::make_unique();

968

969

972

973

974

975 for (const FunctionOutliningMultiRegionInfo::OutlineRegionInfo &RegionInfo :

976 OI->ORI) {

980

983 BasicBlock *NewReturnBlock = nullptr;

986 FunctionOutliningMultiRegionInfo::OutlineRegionInfo MappedRegionInfo(

987 Region, NewEntryBlock, NewExitBlock, NewReturnBlock);

988 ClonedOMRI->ORI.push_back(MappedRegionInfo);

989 }

990

991

992 F->replaceAllUsesWith(ClonedFunc);

993}

994

995void PartialInlinerImpl::FunctionCloner::normalizeReturnBlock() const {

996 auto GetFirstPHI = [](BasicBlock *BB) {

998 PHINode *FirstPhi = nullptr;

999 while (I != BB->end()) {

1001 if (!Phi)

1002 break;

1003 if (!FirstPhi) {

1004 FirstPhi = Phi;

1005 break;

1006 }

1007 }

1008 return FirstPhi;

1009 };

1010

1011

1012

1013 if (!ClonedOI)

1014 return;

1015

1016

1017

1018

1019

1020 BasicBlock *PreReturn = ClonedOI->ReturnBlock;

1021

1022 PHINode *FirstPhi = GetFirstPHI(PreReturn);

1023 unsigned NumPredsFromEntries = ClonedOI->ReturnBlockPreds.size();

1024

1025 if (!FirstPhi || FirstPhi->getNumIncomingValues() <= NumPredsFromEntries + 1)

1026 return;

1027

1028 auto IsTrivialPhi = [](PHINode *PN) -> Value * {

1030 return PN->getIncomingValue(0);

1031 return nullptr;

1032 };

1033

1034 ClonedOI->ReturnBlock = ClonedOI->ReturnBlock->splitBasicBlock(

1035 ClonedOI->ReturnBlock->getFirstNonPHIIt());

1038 SmallVector<Instruction *, 4> DeadPhis;

1039 while (I != PreReturn->end()) {

1041 if (!OldPhi)

1042 break;

1043

1044 PHINode *RetPhi =

1048 Ins = ClonedOI->ReturnBlock->getFirstNonPHIIt();

1049

1051 for (BasicBlock *E : ClonedOI->ReturnBlockPreds) {

1054 }

1055

1056

1057

1058

1059

1060 if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) {

1063 }

1064 ++I;

1065 }

1066 for (auto *DP : DeadPhis)

1067 DP->eraseFromParent();

1068

1069 for (auto *E : ClonedOI->ReturnBlockPreds)

1070 E->getTerminator()->replaceUsesOfWith(PreReturn, ClonedOI->ReturnBlock);

1071}

1072

1073bool PartialInlinerImpl::FunctionCloner::doMultiRegionFunctionOutlining() {

1074

1075 auto ComputeRegionCost =

1078 for (BasicBlock* BB : Region)

1079 Cost += computeBBInlineCost(BB, &GetTTI(*BB->getParent()));

1080 return Cost;

1081 };

1082

1083 assert(ClonedOMRI && "Expecting OutlineInfo for multi region outline");

1084

1085 if (ClonedOMRI->ORI.empty())

1086 return false;

1087

1088

1089 DominatorTree DT;

1091

1092

1093 LoopInfo LI(DT);

1094 BranchProbabilityInfo BPI(*ClonedFunc, LI);

1095 ClonedFuncBFI.reset(new BlockFrequencyInfo(*ClonedFunc, BPI, LI));

1096

1097

1098 CodeExtractorAnalysisCache CEAC(*ClonedFunc);

1099

1100 SetVector<Value *> Inputs, Outputs, Sinks;

1101 for (FunctionOutliningMultiRegionInfo::OutlineRegionInfo RegionInfo :

1102 ClonedOMRI->ORI) {

1104 ComputeRegionCost(RegionInfo.Region);

1105

1106 CodeExtractor CE(RegionInfo.Region, &DT, false,

1107 ClonedFuncBFI.get(), &BPI,

1108 LookupAC(*RegionInfo.EntryBlock->getParent()),

1109 false);

1110

1111 CE.findInputsOutputs(Inputs, Outputs, Sinks);

1112

1114 dbgs() << "inputs: " << Inputs.size() << "\n";

1115 dbgs() << "outputs: " << Outputs.size() << "\n";

1116 for (Value *value : Inputs)

1117 dbgs() << "value used in func: " << *value << "\n";

1118 for (Value *output : Outputs)

1119 dbgs() << "instr used in func: " << *output << "\n";

1120 });

1121

1122

1124 continue;

1125

1126 if (Function *OutlinedFunc = CE.extractCodeRegion(CEAC)) {

1127 CallBase *OCS = PartialInlinerImpl::getOneCallSiteTo(*OutlinedFunc);

1130 OutlinedFunctions.push_back(std::make_pair(OutlinedFunc,OutliningCallBB));

1131 NumColdRegionsOutlined++;

1132 OutlinedRegionCost += CurrentOutlinedRegionCost;

1133

1137 }

1138 } else

1139 ORE.emit([&]() {

1140 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",

1141 &RegionInfo.Region.front()->front())

1142 << "Failed to extract region at block "

1143 << ore::NV("Block", RegionInfo.Region.front());

1144 });

1145 }

1146

1147 return !OutlinedFunctions.empty();

1148}

1149

1151PartialInlinerImpl::FunctionCloner::doSingleRegionFunctionOutlining() {

1152

1153

1154 auto ToBeInlined = [&, this](BasicBlock *BB) {

1155 return BB == ClonedOI->ReturnBlock ||

1157 };

1158

1159 assert(ClonedOI && "Expecting OutlineInfo for single region outline");

1160

1161 DominatorTree DT;

1163

1164

1165 LoopInfo LI(DT);

1166 BranchProbabilityInfo BPI(*ClonedFunc, LI);

1167 ClonedFuncBFI.reset(new BlockFrequencyInfo(*ClonedFunc, BPI, LI));

1168

1169

1170 std::vector<BasicBlock *> ToExtract;

1171 auto *ClonedFuncTTI = &GetTTI(*ClonedFunc);

1172 ToExtract.push_back(ClonedOI->NonReturnBlock);

1173 OutlinedRegionCost += PartialInlinerImpl::computeBBInlineCost(

1174 ClonedOI->NonReturnBlock, ClonedFuncTTI);

1175 for (BasicBlock *BB : depth_first(&ClonedFunc->getEntryBlock()))

1176 if (!ToBeInlined(BB) && BB != ClonedOI->NonReturnBlock) {

1177 ToExtract.push_back(BB);

1178

1179

1180

1181

1182 OutlinedRegionCost += computeBBInlineCost(BB, ClonedFuncTTI);

1183 }

1184

1185

1186 CodeExtractorAnalysisCache CEAC(*ClonedFunc);

1188 CodeExtractor(ToExtract, &DT, false,

1189 ClonedFuncBFI.get(), &BPI, LookupAC(*ClonedFunc),

1190 true)

1191 .extractCodeRegion(CEAC);

1192

1193 if (OutlinedFunc) {

1195 PartialInlinerImpl::getOneCallSiteTo(*OutlinedFunc)->getParent();

1197 OutlinedFunctions.push_back(std::make_pair(OutlinedFunc, OutliningCallBB));

1198 } else

1199 ORE.emit([&]() {

1200 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",

1201 &ToExtract.front()->front())

1202 << "Failed to extract region at block "

1203 << ore::NV("Block", ToExtract.front());

1204 });

1205

1206 return OutlinedFunc;

1207}

1208

1209PartialInlinerImpl::FunctionCloner::~FunctionCloner() {

1210

1211

1213 ClonedFunc->eraseFromParent();

1214 if (!IsFunctionInlined) {

1215

1216

1217 for (auto FuncBBPair : OutlinedFunctions) {

1219 Func->eraseFromParent();

1220 }

1221 }

1222}

1223

1224std::pair<bool, Function *> PartialInlinerImpl::unswitchFunction(Function &F) {

1225 if (F.hasAddressTaken())

1226 return {false, nullptr};

1227

1228

1229 if (F.hasFnAttribute(Attribute::AlwaysInline))

1230 return {false, nullptr};

1231

1232 if (F.hasFnAttribute(Attribute::NoInline))

1233 return {false, nullptr};

1234

1235 if (PSI.isFunctionEntryCold(&F))

1236 return {false, nullptr};

1237

1238 if (F.users().empty())

1239 return {false, nullptr};

1240

1241 OptimizationRemarkEmitter ORE(&F);

1242

1243

1244

1245 if (PSI.hasProfileSummary() && F.hasProfileData() &&

1247 std::unique_ptr OMRI =

1248 computeOutliningColdRegionsInfo(F, ORE);

1249 if (OMRI) {

1250 FunctionCloner Cloner(&F, OMRI.get(), ORE, LookupAssumptionCache, GetTTI);

1251

1253 dbgs() << "HotCountThreshold = " << PSI.getHotCountThreshold() << "\n";

1254 dbgs() << "ColdCountThreshold = " << PSI.getColdCountThreshold()

1255 << "\n";

1256 });

1257

1258 bool DidOutline = Cloner.doMultiRegionFunctionOutlining();

1259

1260 if (DidOutline) {

1262 dbgs() << ">>>>>> Outlined (Cloned) Function >>>>>>\n";

1263 Cloner.ClonedFunc->print(dbgs());

1264 dbgs() << "<<<<<< Outlined (Cloned) Function <<<<<<\n";

1265 });

1266

1267 if (tryPartialInline(Cloner))

1268 return {true, nullptr};

1269 }

1270 }

1271 }

1272

1273

1274

1275

1276 std::unique_ptr OI = computeOutliningInfo(F);

1277 if (!OI)

1278 return {false, nullptr};

1279

1280 FunctionCloner Cloner(&F, OI.get(), ORE, LookupAssumptionCache, GetTTI);

1281 Cloner.normalizeReturnBlock();

1282

1283 Function *OutlinedFunction = Cloner.doSingleRegionFunctionOutlining();

1284

1285 if (!OutlinedFunction)

1286 return {false, nullptr};

1287

1288 if (tryPartialInline(Cloner))

1289 return {true, OutlinedFunction};

1290

1291 return {false, nullptr};

1292}

1293

1294bool PartialInlinerImpl::tryPartialInline(FunctionCloner &Cloner) {

1295 if (Cloner.OutlinedFunctions.empty())

1296 return false;

1297

1298 auto OutliningCosts = computeOutliningCosts(Cloner);

1299

1301 InstructionCost NonWeightedRcost = std::get<1>(OutliningCosts);

1302

1304 "Expected valid costs");

1305

1306

1307

1308 BranchProbability RelativeToEntryFreq;

1309 if (Cloner.ClonedOI)

1310 RelativeToEntryFreq = getOutliningCallBBRelativeFreq(Cloner);

1311 else

1312

1313

1314

1315

1316

1317 RelativeToEntryFreq = BranchProbability(0, 1);

1318

1319 BlockFrequency WeightedRcost =

1320 BlockFrequency(NonWeightedRcost.getValue()) * RelativeToEntryFreq;

1321

1322

1323

1324

1325

1326 if (SkipCostAnalysis && Cloner.OutlinedRegionCost < SizeCost) {

1327 OptimizationRemarkEmitter OrigFuncORE(Cloner.OrigFunc);

1330 std::tie(DLoc, Block) = getOneDebugLoc(*Cloner.ClonedFunc);

1331 OrigFuncORE.emit([&]() {

1332 return OptimizationRemarkAnalysis(DEBUG_TYPE, "OutlineRegionTooSmall",

1334 << ore::NV("Function", Cloner.OrigFunc)

1335 << " not partially inlined into callers (Original Size = "

1336 << ore::NV("OutlinedRegionOriginalSize", Cloner.OutlinedRegionCost)

1337 << ", Size of call sequence to outlined function = "

1338 << ore::NV("NewSize", SizeCost) << ")";

1339 });

1340 return false;

1341 }

1342

1343 assert(Cloner.OrigFunc->users().empty() &&

1344 "F's users should all be replaced!");

1345

1346 std::vector<User *> Users(Cloner.ClonedFunc->user_begin(),

1347 Cloner.ClonedFunc->user_end());

1348

1349 DenseMap<User *, uint64_t> CallSiteToProfCountMap;

1350 auto CalleeEntryCount = Cloner.OrigFunc->getEntryCount();

1351 if (CalleeEntryCount)

1352 computeCallsiteToProfCountMap(Cloner.ClonedFunc, CallSiteToProfCountMap);

1353

1354 uint64_t CalleeEntryCountV =

1355 (CalleeEntryCount ? CalleeEntryCount->getCount() : 0);

1356

1357 bool AnyInline = false;

1358 for (User *User : Users) {

1359 CallBase *CB = getSupportedCallBase(User);

1360

1361 if (isLimitReached())

1362 continue;

1363

1364 OptimizationRemarkEmitter CallerORE(CB->getCaller());

1365 if (!shouldPartialInline(*CB, Cloner, WeightedRcost, CallerORE))

1366 continue;

1367

1368

1369

1370 OptimizationRemark OR(DEBUG_TYPE, "PartiallyInlined", CB);

1371 OR << ore::NV("Callee", Cloner.OrigFunc) << " partially inlined into "

1373

1374 InlineFunctionInfo IFI(GetAssumptionCache, &PSI);

1375

1376

1377 if (InlineFunction(*CB, IFI, false, nullptr, true,

1378 (Cloner.ClonedOI ? Cloner.OutlinedFunctions.back().first

1379 : nullptr))

1381 continue;

1382

1383 CallerORE.emit(OR);

1384

1385

1386 if (CalleeEntryCountV) {

1387 if (auto It = CallSiteToProfCountMap.find(User);

1388 It != CallSiteToProfCountMap.end()) {

1389 uint64_t CallSiteCount = It->second;

1390 CalleeEntryCountV -= std::min(CalleeEntryCountV, CallSiteCount);

1391 }

1392 }

1393

1394 AnyInline = true;

1395 NumPartialInlining++;

1396

1397 if (Cloner.ClonedOI)

1398 NumPartialInlined++;

1399 else

1400 NumColdOutlinePartialInlined++;

1401 }

1402

1403 if (AnyInline) {

1404 Cloner.IsFunctionInlined = true;

1405 if (CalleeEntryCount)

1406 Cloner.OrigFunc->setEntryCount(Function::ProfileCount(

1407 CalleeEntryCountV, CalleeEntryCount->getType()));

1408 OptimizationRemarkEmitter OrigFuncORE(Cloner.OrigFunc);

1409 OrigFuncORE.emit([&]() {

1410 return OptimizationRemark(DEBUG_TYPE, "PartiallyInlined", Cloner.OrigFunc)

1411 << "Partially inlined into at least one caller";

1412 });

1413 }

1414

1415 return AnyInline;

1416}

1417

1418bool PartialInlinerImpl::run(Module &M) {

1420 return false;

1421

1422 std::vector<Function *> Worklist;

1423 Worklist.reserve(M.size());

1424 for (Function &F : M)

1425 if (F.use_empty() && F.isDeclaration())

1426 Worklist.push_back(&F);

1427

1429 while (!Worklist.empty()) {

1430 Function *CurrFunc = Worklist.back();

1431 Worklist.pop_back();

1432

1434 continue;

1435

1436 std::pair<bool, Function *> Result = unswitchFunction(*CurrFunc);

1438 Worklist.push_back(Result.second);

1440 }

1441

1443}

1444

1448

1451 };

1452

1455 };

1456

1459 };

1460

1463 };

1464

1467 };

1468

1470

1471 if (PartialInlinerImpl(GetAssumptionCache, LookupAssumptionCache, GetTTI,

1472 GetTLI, PSI, GetBFI)

1473 .run(M))

1476}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

This file contains the simple types necessary to represent the attributes associated with functions a...

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

cl::opt< unsigned > MinBlockCounterExecution

This file defines the DenseMap class.

This file defines the DenseSet and SmallDenseSet classes.

This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.

This file provides various utilities for inspecting and working with the control flow graph in LLVM I...

Module.h This file contains the declarations for the Module class.

iv Induction Variable Users

static cl::opt< int > InstrCost("inline-instr-cost", cl::Hidden, cl::init(5), cl::desc("Cost of a single instruction when inlining"))

Machine Check Debug Module

uint64_t IntrinsicInst * II

static cl::opt< unsigned > MaxNumInlineBlocks("max-num-inline-blocks", cl::init(5), cl::Hidden, cl::desc("Max number of blocks to be partially inlined"))

static cl::opt< int > OutlineRegionFreqPercent("outline-region-freq-percent", cl::init(75), cl::Hidden, cl::desc("Relative frequency of outline region to " "the entry block"))

static cl::opt< bool > MarkOutlinedColdCC("pi-mark-coldcc", cl::init(false), cl::Hidden, cl::desc("Mark outline function calls with ColdCC"))

static cl::opt< float > MinRegionSizeRatio("min-region-size-ratio", cl::init(0.1), cl::Hidden, cl::desc("Minimum ratio comparing relative sizes of each " "outline candidate and original function"))

static cl::opt< bool > DisableMultiRegionPartialInline("disable-mr-partial-inlining", cl::init(false), cl::Hidden, cl::desc("Disable multi-region partial inlining"))

cl::opt< unsigned > MinBlockCounterExecution("min-block-execution", cl::init(100), cl::Hidden, cl::desc("Minimum block executions to consider " "its BranchProbabilityInfo valid"))

static cl::opt< int > MaxNumPartialInlining("max-partial-inlining", cl::init(-1), cl::Hidden, cl::desc("Max number of partial inlining. The default is unlimited"))

static cl::opt< bool > DisablePartialInlining("disable-partial-inlining", cl::init(false), cl::Hidden, cl::desc("Disable partial inlining"))

static bool hasProfileData(const Function &F, const FunctionOutliningInfo &OI)

Definition PartialInlining.cpp:659

static cl::opt< float > ColdBranchRatio("cold-branch-ratio", cl::init(0.1), cl::Hidden, cl::desc("Minimum BranchProbability to consider a region cold."))

static cl::opt< bool > ForceLiveExit("pi-force-live-exit-outline", cl::init(false), cl::Hidden, cl::desc("Force outline regions with live exits"))

static cl::opt< unsigned > ExtraOutliningPenalty("partial-inlining-extra-penalty", cl::init(0), cl::Hidden, cl::desc("A debug option to add additional penalty to the computed one."))

static cl::opt< bool > SkipCostAnalysis("skip-partial-inlining-cost-analysis", cl::ReallyHidden, cl::desc("Skip Cost Analysis"))

FunctionAnalysisManager FAM

This file contains the declarations for profiling metadata utility functions.

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

This pass exposes codegen information to IR-level passes.

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

Get the result of an analysis pass for a given IR unit.

A function analysis which provides an AssumptionCache.

A cache of @llvm.assume calls within a function.

LLVM Basic Block Representation.

iterator begin()

Instruction iterator methods.

const Function * getParent() const

Return the enclosing method, or null if none.

LLVM_ABI iterator_range< filter_iterator< BasicBlock::const_iterator, std::function< bool(const Instruction &)> > > instructionsWithoutDebug(bool SkipPseudoOp=true) const

Return a const iterator range over the instructions in the block, skipping any debug instructions.

LLVM_ABI const BasicBlock * getSinglePredecessor() const

Return the predecessor of this block if it has a single predecessor block.

const Instruction & front() const

LLVM_ABI const BasicBlock * getSingleSuccessor() const

Return the successor of this block if it has a single successor.

LLVM_ABI const DataLayout & getDataLayout() const

Get the data layout of the module this basic block belongs to.

InstListType::iterator iterator

Instruction iterators...

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...

Analysis pass which computes BlockFrequencyInfo.

BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...

LLVM_ABI std::optional< uint64_t > getBlockProfileCount(const BasicBlock *BB, bool AllowSynthetic=false) const

Returns the estimated profile count of BB.

uint64_t getFrequency() const

Returns the frequency as a fixpoint number scaled by the entry frequency.

Conditional or Unconditional Branch instruction.

bool isUnconditional() const

static LLVM_ABI BranchProbability getBranchProbability(uint64_t Numerator, uint64_t Denominator)

void setCallingConv(CallingConv::ID CC)

Function * getCalledFunction() const

Returns the function called, or null if this is an indirect function invocation or the function signa...

LLVM_ABI Function * getCaller()

Helper to get the caller (the parent function).

iterator find(const_arg_type_t< KeyT > Val)

void recalculate(ParentType &Func)

recalculate - compute a dominator tree for the given function

void setCallingConv(CallingConv::ID CC)

int getCost() const

Get the inline cost estimate.

int getCostDelta() const

Get the cost delta from the threshold for inlining.

auto map(const Function &F) const -> InstructionCost

CostType getValue() const

This function is intended to be used as sparingly as possible, since the class provides the full rang...

const DebugLoc & getDebugLoc() const

Return the debug location for this node as a DebugLoc.

LLVM_ABI void insertBefore(InstListType::iterator InsertPos)

Insert an unlinked instruction into a basic block immediately before the specified position.

A Module instance is used to store all the information related to an LLVM module.

void addIncoming(Value *V, BasicBlock *BB)

Add an incoming value to the end of the PHI list.

LLVM_ABI Value * removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty=true)

Remove an incoming value.

Value * getIncomingValueForBlock(const BasicBlock *BB) const

unsigned getNumIncomingValues() const

Return the number of incoming edges.

static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...

PreservedAnalyses run(Module &M, ModuleAnalysisManager &)

Definition PartialInlining.cpp:1445

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.

An analysis pass based on the new PM to deliver ProfileSummaryInfo.

Analysis providing profile information.

size_type size() const

Determine the number of elements in the SetVector.

void insert_range(Range &&R)

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

Analysis pass providing the TargetTransformInfo.

Analysis pass providing the TargetLibraryInfo.

Provides information about what library functions are available for the current target.

This pass provides access to the codegen interfaces that are needed for IR-level transformations.

LLVM_ABI InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const

@ TCK_SizeAndLatency

The weighted sum of size and latency.

Type * getType() const

All values are typed, get the type of this value.

user_iterator user_begin()

LLVM_ABI void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

An efficient, type-erasing, non-owning reference to a callable.

const ParentTy * getParent() const

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ BasicBlock

Various leaf nodes.

LLVM_ABI int getInstrCost()

@ CE

Windows NT (Windows on ARM)

initializer< Ty > init(const Ty &Val)

PointerTypeMap run(const Module &M)

Compute the PointerTypeMap for the module M.

@ User

could "use" a pointer

DiagnosticInfoOptimizationBase::Argument NV

NodeAddr< PhiNode * > Phi

NodeAddr< FuncNode * > Func

friend class Instruction

Iterator for Instructions in a `BasicBlock.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, Function *ForwardVarArgsTo=nullptr, OptimizationRemarkEmitter *ORE=nullptr)

This function inlines the called function into the basic block of the caller.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

auto successors(const MachineBasicBlock *BB)

constexpr from_range_t from_range

InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy

Provide the FunctionAnalysisManager to Module proxy.

LLVM_ABI InlineResult isInlineViable(Function &Callee)

Check if it is mechanically possible to inline the function Callee, based on the contents of the func...

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

FunctionAddr VTableAddr Count

auto succ_size(const MachineBasicBlock *BB)

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)

LLVM_ABI InlineCost getInlineCost(CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< const TargetLibraryInfo &(Function &)> GetTLI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr, function_ref< EphemeralValuesCache &(Function &)> GetEphValuesCache=nullptr)

Get an InlineCost object representing the cost of inlining this callsite.

RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)

ArrayRef(const T &OneElt) -> ArrayRef< T >

LLVM_ABI InlineParams getInlineParams()

Generate the parameters to tune the inline cost analysis based only on the commandline options.

LLVM_ABI int getCallsiteCost(const TargetTransformInfo &TTI, const CallBase &Call, const DataLayout &DL)

Return the cost associated with a callsite, including parameter passing and the call/return instructi...

ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

auto predecessors(const MachineBasicBlock *BB)

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

iterator_range< df_iterator< T > > depth_first(const T &G)

bool all_equal(std::initializer_list< T > Values)

Returns true if all Values in the initializer lists are equal or the list.

LLVM_ABI bool hasBranchWeightMD(const Instruction &I)

Checks if an instructions has Branch Weight Metadata.

LLVM_ABI Function * CloneFunction(Function *F, ValueToValueMapTy &VMap, ClonedCodeInfo *CodeInfo=nullptr)

Return a copy of the specified function and add it to that function's module.

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.