LLVM: lib/Analysis/ModuleSummaryAnalysis.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

55#include

56#include

57#include

58

59using namespace llvm;

61

62#define DEBUG_TYPE "module-summary-analysis"

63

64

65

66namespace llvm {

69}

70

73 cl::desc("Force all edges in the function summary to cold"),

76 "all-non-critical", "All non-critical edges."),

78

81 cl::desc("File to emit dot graph of new summary into"));

82

86 "Enable MemProf support for summarizing and cloning indirect calls"));

87

89

91

93

94

95

96

97

98

99

100

101

102

103

104

105

106static bool

110 bool &RefLocalLinkageIFunc) {

111 bool HasBlockAddress = false;

113 if (Visited.insert(CurUser).second)

115

116 while (!Worklist.empty()) {

118 const auto *CB = dyn_cast(U);

119

120 for (const auto &OI : U->operands()) {

121 const User *Operand = dyn_cast(OI);

122 if (!Operand)

123 continue;

124 if (isa(Operand)) {

125 HasBlockAddress = true;

126 continue;

127 }

128 if (auto *GV = dyn_cast(Operand)) {

129

130

131

132 if (!(CB && CB->isCallee(&OI))) {

133

134

135

136

137 if (auto *GI = dyn_cast_if_present(GV);

138 GI && GI->hasLocalLinkage()) {

139 RefLocalLinkageIFunc = true;

140 continue;

141 }

142 RefEdges.insert(Index.getOrInsertValueInfo(GV));

143 }

144 continue;

145 }

146 if (Visited.insert(Operand).second)

148 }

149 }

150

151 const Instruction *I = dyn_cast(CurUser);

152 if (I) {

154

155

158

159 for (const auto &V : ValueDataArray)

160 RefEdges.insert(Index.getOrInsertValueInfo(

161 V.Value));

162 }

163 return HasBlockAddress;

164}

165

168 if (!PSI)

169 return CalleeInfo::HotnessType::Unknown;

171 return CalleeInfo::HotnessType::Hot;

173 return CalleeInfo::HotnessType::Cold;

174 return CalleeInfo::HotnessType::None;

175}

176

179}

180

181

182

186 &VCalls,

188 std::vectorFunctionSummary::ConstVCall> &ConstVCalls) {

189 std::vector<uint64_t> Args;

190

191 for (auto &Arg : drop_begin(Call.CB.args())) {

192 auto *CI = dyn_cast(Arg);

193 if (!CI || CI->getBitWidth() > 64) {

194 VCalls.insert({Guid, Call.Offset});

195 return;

196 }

197 Args.push_back(CI->getZExtValue());

198 }

199 ConstVCalls.insert({{Guid, Call.Offset}, std::move(Args)});

200}

201

202

203

208 &TypeTestAssumeVCalls,

210 &TypeCheckedLoadVCalls,

212 std::vectorFunctionSummary::ConstVCall>

213 &TypeTestAssumeConstVCalls,

215 std::vectorFunctionSummary::ConstVCall>

216 &TypeCheckedLoadConstVCalls,

219 case Intrinsic::type_test:

220 case Intrinsic::public_type_test: {

221 auto *TypeMDVal = cast(CI->getArgOperand(1));

222 auto *TypeId = dyn_cast(TypeMDVal->getMetadata());

223 if (!TypeId)

224 break;

226

227

228

229

230

232 return !isa(CIU.getUser());

233 });

234 if (HasNonAssumeUses)

235 TypeTests.insert(Guid);

236

240 for (auto &Call : DevirtCalls)

242 TypeTestAssumeConstVCalls);

243

244 break;

245 }

246

247 case Intrinsic::type_checked_load_relative:

248 case Intrinsic::type_checked_load: {

249 auto *TypeMDVal = cast(CI->getArgOperand(2));

250 auto *TypeId = dyn_cast(TypeMDVal->getMetadata());

251 if (!TypeId)

252 break;

254

258 bool HasNonCallUses = false;

260 HasNonCallUses, CI, DT);

261

262

263 if (HasNonCallUses)

264 TypeTests.insert(Guid);

265 for (auto &Call : DevirtCalls)

267 TypeCheckedLoadConstVCalls);

268

269 break;

270 }

271 default:

272 break;

273 }

274}

275

277 if (const auto *LI = dyn_cast(I))

278 return !LI->isVolatile();

279

280 return false;

281}

282

284 if (const auto *SI = dyn_cast(I))

285 return !SI->isVolatile();

286

287 return false;

288}

289

290

291

292

293

294

296

297

298 assert(F.isDeclaration());

299 return isa(F.getEntryBlock().getTerminator());

300}

301

306 bool IsThinLTO,

308

309

311

312 unsigned NumInsts = 0;

313

314

317 CallGraphEdges;

319 StoreRefEdges;

322 TypeTestAssumeVCalls, TypeCheckedLoadVCalls;

324 std::vectorFunctionSummary::ConstVCall>

325 TypeTestAssumeConstVCalls, TypeCheckedLoadConstVCalls;

328

329

330

331 bool HasLocalIFuncCallOrRef = false;

332 findRefEdges(Index, &F, RefEdges, Visited, HasLocalIFuncCallOrRef);

333 std::vector<const Instruction *> NonVolatileLoads;

334 std::vector<const Instruction *> NonVolatileStores;

335

336 std::vector Callsites;

337 std::vector Allocs;

338

339#ifndef NDEBUG

341#endif

342

343 bool HasInlineAsmMaybeReferencingInternal = false;

344 bool HasIndirBranchToBlockAddress = false;

345 bool HasUnknownCall = false;

346 bool MayThrow = false;

348

349

350

351

352 if (BB.hasAddressTaken()) {

354 if (!isa(*U)) {

355 HasIndirBranchToBlockAddress = true;

356 break;

357 }

358 }

359

361 if (I.isDebugOrPseudoInst())

362 continue;

363 ++NumInsts;

364

365

366

367

368 if (IsThinLTO) {

370

371

373 NonVolatileLoads.push_back(&I);

374 continue;

377 NonVolatileStores.push_back(&I);

378

379

380

381

382

383

384 Value *Stored = I.getOperand(0);

385 if (auto *GV = dyn_cast(Stored))

386

387

388 RefEdges.insert(Index.getOrInsertValueInfo(GV));

389 else if (auto *U = dyn_cast(Stored))

390 findRefEdges(Index, U, RefEdges, Visited, HasLocalIFuncCallOrRef);

391 continue;

392 }

393 }

394 findRefEdges(Index, &I, RefEdges, Visited, HasLocalIFuncCallOrRef);

395 const auto *CB = dyn_cast(&I);

396 if (!CB) {

397 if (I.mayThrow())

398 MayThrow = true;

399 continue;

400 }

401

402 const auto *CI = dyn_cast(&I);

403

404

405

406

407

408 if (HasLocalsInUsedOrAsm && CI && CI->isInlineAsm())

409 HasInlineAsmMaybeReferencingInternal = true;

410

411

415

416 auto *CalledValue = CB->getCalledOperand();

417 auto *CalledFunction = CB->getCalledFunction();

418 if (CalledValue && !CalledFunction) {

419 CalledValue = CalledValue->stripPointerCasts();

420

421 CalledFunction = dyn_cast(CalledValue);

422 }

423

424

425 if (auto *GA = dyn_cast(CalledValue)) {

426 assert(!CalledFunction && "Expected null called function in callsite for alias");

427 CalledFunction = dyn_cast(GA->getAliaseeObject());

428 }

429

430

431 if (CalledFunction) {

432 if (CI && CalledFunction->isIntrinsic()) {

434 CI, TypeTests, TypeTestAssumeVCalls, TypeCheckedLoadVCalls,

435 TypeTestAssumeConstVCalls, TypeCheckedLoadConstVCalls, DT);

436 continue;

437 }

438

439 assert(CalledFunction->hasName());

441 auto Hotness = ScaledCount ? getHotness(*ScaledCount, PSI)

442 : CalleeInfo::HotnessType::Unknown;

444 Hotness = CalleeInfo::HotnessType::Cold;

445

446

447

448

449

450 auto &ValueInfo = CallGraphEdges[Index.getOrInsertValueInfo(

451 cast(CalledValue))];

452 ValueInfo.updateHotness(Hotness);

453 if (CB->isTailCall())

455

456

457 if (BFI != nullptr && Hotness == CalleeInfo::HotnessType::Unknown) {

458 uint64_t BBFreq = BFI->getBlockFreq(&BB).getFrequency();

459 uint64_t EntryFreq = BFI->getEntryFreq().getFrequency();

461 }

462 } else {

463 HasUnknownCall = true;

464

465

466

467

468

469

470

471 if (auto *GI = dyn_cast_if_present(CalledValue))

472 if (GI->hasLocalLinkage())

473 HasLocalIFuncCallOrRef = true;

474

475 if (CI && CI->isInlineAsm())

476 continue;

477

478 if (!CalledValue || isa(CalledValue))

479 continue;

480

481

482

483

484

485 if (auto *MD = I.getMetadata(LLVMContext::MD_callees)) {

486 for (const auto &Op : MD->operands()) {

487 Function *Callee = mdconst::extract_or_null(Op);

488 if (Callee)

489 CallGraphEdges[Index.getOrInsertValueInfo(Callee)];

490 }

491 }

492

493 CandidateProfileData =

495 NumCandidates);

496 for (const auto &Candidate : CandidateProfileData)

497 CallGraphEdges[Index.getOrInsertValueInfo(Candidate.Value)]

498 .updateHotness(getHotness(Candidate.Count, PSI));

499 }

500

501

502 if (!IsThinLTO)

503 continue;

504

505

507 continue;

508

509

510

511

513#ifndef NDEBUG

514 CallsThatMayHaveMemprofSummary.insert(CB);

515#endif

516

517

518

520 I.getMetadata(LLVMContext::MD_callsite));

521 auto *MemProfMD = I.getMetadata(LLVMContext::MD_memprof);

522 if (MemProfMD) {

523 std::vector MIBs;

524 std::vector<uint64_t> TotalSizes;

525 std::vector<std::vector> ContextSizeInfos;

526 for (auto &MDOp : MemProfMD->operands()) {

527 auto *MIBMD = cast(MDOp);

532

533 for (auto ContextIter =

535 ContextIter != StackContext.end(); ++ContextIter) {

536 unsigned StackIdIdx = Index.addOrGetStackIdIndex(*ContextIter);

537

538

539

540 if (StackIdIndices.empty() || StackIdIndices.back() != StackIdIdx)

541 StackIdIndices.push_back(StackIdIdx);

542 }

543

544

546 if (MIBMD->getNumOperands() > 2) {

547 std::vector ContextSizes;

548 for (unsigned I = 2; I < MIBMD->getNumOperands(); I++) {

549 MDNode *ContextSizePair = dyn_cast(MIBMD->getOperand(I));

551 uint64_t FullStackId = mdconst::dyn_extract(

553 ->getZExtValue();

554 uint64_t TS = mdconst::dyn_extract(

556 ->getZExtValue();

557 ContextSizes.push_back({FullStackId, TS});

558 }

559 ContextSizeInfos.push_back(std::move(ContextSizes));

560 }

561 MIBs.push_back(

563 }

564 Allocs.push_back(AllocInfo(std::move(MIBs)));

566 if (!ContextSizeInfos.empty()) {

567 assert(Allocs.back().MIBs.size() == ContextSizeInfos.size());

568 Allocs.back().ContextSizeInfos = std::move(ContextSizeInfos);

569 }

570 } else if (!InstCallsite.empty()) {

572 for (auto StackId : InstCallsite)

573 StackIdIndices.push_back(Index.addOrGetStackIdIndex(StackId));

574 if (CalledFunction) {

575

576

577

578

579 auto CalleeValueInfo =

580 Index.getOrInsertValueInfo(cast(CalledValue));

581 Callsites.push_back({CalleeValueInfo, StackIdIndices});

582 } else {

584

585

586

587

588 for (const auto &Candidate : CandidateProfileData) {

589 auto CalleeValueInfo = Index.getOrInsertValueInfo(Candidate.Value);

590 Callsites.push_back({CalleeValueInfo, StackIdIndices});

591 }

592 }

593 }

594 }

595 }

596

598 Index.addBlockCount(F.size());

599

601 if (IsThinLTO) {

602 auto AddRefEdges =

603 [&](const std::vector<const Instruction *> &Instrs,

606 for (const auto *I : Instrs) {

608 findRefEdges(Index, I, Edges, Cache, HasLocalIFuncCallOrRef);

609 }

610 };

611

612

613

614

615 AddRefEdges(NonVolatileLoads, LoadRefEdges, Visited);

616

617

618

619

620

621

622

623

624

625

627 AddRefEdges(NonVolatileStores, StoreRefEdges, StoreCache);

628

629

630

631

632 for (const auto &VI : StoreRefEdges)

633 if (LoadRefEdges.remove(VI))

635

636 unsigned RefCnt = RefEdges.size();

637

638

639

640 for (const auto &VI : LoadRefEdges)

642

643 unsigned FirstWORef = RefEdges.size();

644 for (const auto &VI : StoreRefEdges)

646

648 for (; RefCnt < FirstWORef; ++RefCnt)

649 Refs[RefCnt].setReadOnly();

650

651 for (; RefCnt < Refs.size(); ++RefCnt)

652 Refs[RefCnt].setWriteOnly();

653 } else {

655 }

656

657

658 for (auto &I : F.getImportGUIDs())

659 CallGraphEdges[Index.getOrInsertValueInfo(I)].updateHotness(

661 ? CalleeInfo::HotnessType::Cold

662 : CalleeInfo::HotnessType::Critical);

663

664#ifndef NDEBUG

665

666

667

668 if (IsThinLTO) {

671 const auto *CB = dyn_cast(&I);

672 if (!CB)

673 continue;

674

675 if (CallsThatMayHaveMemprofSummary.count(CB))

676 continue;

678 }

679 }

680 }

681#endif

682

684 bool NotEligibleForImport =

685 NonRenamableLocal || HasInlineAsmMaybeReferencingInternal ||

686 HasIndirBranchToBlockAddress || HasLocalIFuncCallOrRef;

688 F.getLinkage(), F.getVisibility(), NotEligibleForImport,

689 false, F.isDSOLocal(), F.canBeOmittedFromSymbolTable(),

690 GlobalValueSummary::ImportKind::Definition);

692 F.doesNotAccessMemory(), F.onlyReadsMemory() && F.doesNotAccessMemory(),

693 F.hasFnAttribute(Attribute::NoRecurse), F.returnDoesNotAlias(),

694

695

696 F.getAttributes().hasFnAttr(Attribute::NoInline),

697 F.hasFnAttribute(Attribute::AlwaysInline),

698 F.hasFnAttribute(Attribute::NoUnwind), MayThrow, HasUnknownCall,

700 std::vectorFunctionSummary::ParamAccess ParamAccesses;

701 if (auto *SSI = GetSSICallback(F))

702 ParamAccesses = SSI->getParamAccesses(Index);

703 auto FuncSummary = std::make_unique(

704 Flags, NumInsts, FunFlags, std::move(Refs), CallGraphEdges.takeVector(),

707 TypeTestAssumeConstVCalls.takeVector(),

708 TypeCheckedLoadConstVCalls.takeVector(), std::move(ParamAccesses),

709 std::move(Callsites), std::move(Allocs));

710 if (NonRenamableLocal)

711 CantBePromoted.insert(F.getGUID());

712 Index.addGlobalValueSummary(F, std::move(FuncSummary));

713}

714

715

716

717

718

719

724

725 if (I->getType()->isPointerTy()) {

726 auto C = I->stripPointerCasts();

727 auto A = dyn_cast(C);

728 if (isa(C) || (A && isa(A->getAliasee()))) {

729 auto GV = dyn_cast(C);

731

732

733 if (GV && GV->getName() != "__cxa_pure_virtual")

734 VTableFuncs.push_back({Index.getOrInsertValueInfo(GV), StartingOffset});

735 return;

736 }

737 }

738

739

740

742 if (auto *C = dyn_cast(I)) {

743 StructType *STy = dyn_cast(C->getType());

745 const StructLayout *SL = DL.getStructLayout(C->getType());

746

751 StartingOffset + Offset, M, Index, VTableFuncs, OrigGV);

752 }

753 } else if (auto *C = dyn_cast(I)) {

755 Type *EltTy = ATy->getElementType();

756 uint64_t EltSize = DL.getTypeAllocSize(EltTy);

757 for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {

759 StartingOffset + i * EltSize, M, Index, VTableFuncs,

760 OrigGV);

761 }

762 } else if (const auto *CE = dyn_cast(I)) {

763

764 if (CE->getOpcode() != Instruction::Trunc ||

765 !(CE = dyn_cast(CE->getOperand(0))))

766 return;

767

768

769

770

771 if (CE->getOpcode() == Instruction::Sub) {

773 APSInt LHSOffset, RHSOffset;

776 RHS == &OrigGV &&

777

778

779

780 LHSOffset == 0 &&

781

782

783 RHSOffset <=

786 }

787 }

788 }

789}

790

791

795 if (!V.isConstant())

796 return;

797

798 findFuncPointers(V.getInitializer(), 0, M, Index,

799 VTableFuncs, V);

800

801#ifndef NDEBUG

802

804 for (auto &P : VTableFuncs) {

805

806

807

808 assert(P.VTableOffset >= PrevOffset);

809 PrevOffset = P.VTableOffset;

810 }

811#endif

812}

813

814

815static void

820 auto TypeID = Type->getOperand(1).get();

821

823 cast(

824 cast(Type->getOperand(0))->getValue())

825 ->getZExtValue();

826

827 if (auto *TypeId = dyn_cast(TypeID))

828 Index.getOrInsertTypeIdCompatibleVtableSummary(TypeId->getString())

829 .push_back({Offset, Index.getOrInsertValueInfo(&V)});

830 }

831}

832

840 bool RefLocalIFunc = false;

841 bool HasBlockAddress =

842 findRefEdges(Index, &V, RefEdges, Visited, RefLocalIFunc);

843 const bool NotEligibleForImport = (HasBlockAddress || RefLocalIFunc);

846 V.getLinkage(), V.getVisibility(), NonRenamableLocal,

847 false, V.isDSOLocal(), V.canBeOmittedFromSymbolTable(),

849

851

852

853 if (!Index.enableSplitLTOUnit()) {

854 Types.clear();

855 V.getMetadata(LLVMContext::MD_type, Types);

856 if (!Types.empty()) {

857

859

860

862 }

863 }

864

865

866 bool CanBeInternalized =

867 !V.hasComdat() && !V.hasAppendingLinkage() && !V.isInterposable() &&

868 !V.hasAvailableExternallyLinkage() && !V.hasDLLExportStorageClass();

869 bool Constant = V.isConstant();

871 Constant ? false : CanBeInternalized,

872 Constant, V.getVCallVisibility());

873 auto GVarSummary = std::make_unique(Flags, VarFlags,

875 if (NonRenamableLocal)

876 CantBePromoted.insert(V.getGUID());

877 if (NotEligibleForImport)

878 GVarSummary->setNotEligibleToImport();

879 if (!VTableFuncs.empty())

880 GVarSummary->setVTableFuncs(VTableFuncs);

881 Index.addGlobalValueSummary(V, std::move(GVarSummary));

882}

883

886

887

888 const GlobalObject *Aliasee = A.getAliaseeObject();

889 if (isa(Aliasee))

890 return;

893 A.getLinkage(), A.getVisibility(), NonRenamableLocal,

894 false, A.isDSOLocal(), A.canBeOmittedFromSymbolTable(),

896 auto AS = std::make_unique(Flags);

897 auto AliaseeVI = Index.getValueInfo(Aliasee->getGUID());

898 assert(AliaseeVI && "Alias expects aliasee summary to be available");

899 assert(AliaseeVI.getSummaryList().size() == 1 &&

900 "Expected a single entry per aliasee in per-module index");

901 AS->setAliasee(AliaseeVI, AliaseeVI.getSummaryList()[0].get());

902 if (NonRenamableLocal)

903 CantBePromoted.insert(A.getGUID());

904 Index.addGlobalValueSummary(A, std::move(AS));

905}

906

907

910 for (const auto &Summary : VI.getSummaryList())

911 Summary->setLive(true);

912}

913

920 bool EnableSplitLTOUnit = false;

921 bool UnifiedLTO = false;

922 if (auto *MD = mdconst::extract_or_null(

923 M.getModuleFlag("EnableSplitLTOUnit")))

924 EnableSplitLTOUnit = MD->getZExtValue();

925 if (auto *MD =

926 mdconst::extract_or_null(M.getModuleFlag("UnifiedLTO")))

927 UnifiedLTO = MD->getZExtValue();

928 ModuleSummaryIndex Index(true, EnableSplitLTOUnit, UnifiedLTO);

929

930

931

932

933

934

937

939

942 for (auto *V : Used) {

943 if (V->hasLocalLinkage()) {

944 LocalsUsed.insert(V);

945 CantBePromoted.insert(V->getGUID());

946 }

947 }

948

949 bool HasLocalInlineAsmSymbol = false;

950 if (!M.getModuleInlineAsm().empty()) {

951

952

953

954

955

956

957

958

959

962

965 return;

966 HasLocalInlineAsmSymbol = true;

968 if (!GV)

969 return;

970 assert(GV->isDeclaration() && "Def in module asm already has definition");

973 true,

974 true,

978

979 if (Function *F = dyn_cast(GV)) {

980 std::unique_ptr Summary =

981 std::make_unique(

982 GVFlags, 0,

984 F->hasFnAttribute(Attribute::ReadNone),

985 F->hasFnAttribute(Attribute::ReadOnly),

986 F->hasFnAttribute(Attribute::NoRecurse),

987 F->returnDoesNotAlias(),

988 false,

989 F->hasFnAttribute(Attribute::AlwaysInline),

990 F->hasFnAttribute(Attribute::NoUnwind),

991 true,

992 true,

993 false},

1003 Index.addGlobalValueSummary(*GV, std::move(Summary));

1004 } else {

1005 std::unique_ptr Summary =

1006 std::make_unique(

1007 GVFlags,

1009 false, false, cast(GV)->isConstant(),

1012 Index.addGlobalValueSummary(*GV, std::move(Summary));

1013 }

1014 });

1015 }

1016

1017 bool IsThinLTO = true;

1018 if (auto *MD =

1019 mdconst::extract_or_null(M.getModuleFlag("ThinLTO")))

1020 IsThinLTO = MD->getZExtValue();

1021

1022

1023

1024 for (const auto &F : M) {

1025 if (F.isDeclaration())

1026 continue;

1027

1030 std::unique_ptr BFIPtr;

1031 if (GetBFICallback)

1032 BFI = GetBFICallback(F);

1033 else if (F.hasProfileData()) {

1036 BFIPtr = std::make_unique(F, BPI, LI);

1037 BFI = BFIPtr.get();

1038 }

1039

1041 !LocalsUsed.empty() || HasLocalInlineAsmSymbol,

1042 CantBePromoted, IsThinLTO, GetSSICallback);

1043 }

1044

1045

1046

1049 if (G.isDeclaration())

1050 continue;

1052 }

1053

1054

1055

1058

1059

1061 I.applyAlongResolverPath([&Index](const GlobalValue &GV) {

1062 Index.getGlobalValueSummary(GV)->setLive(true);

1063 });

1064 }

1065

1066 for (auto *V : LocalsUsed) {

1067 auto *Summary = Index.getGlobalValueSummary(*V);

1068 assert(Summary && "Missing summary for global value");

1069 Summary->setNotEligibleToImport();

1070 }

1071

1072

1073

1074

1076 setLiveRoot(Index, "llvm.compiler.used");

1077 setLiveRoot(Index, "llvm.global_ctors");

1078 setLiveRoot(Index, "llvm.global_dtors");

1079 setLiveRoot(Index, "llvm.global.annotations");

1080

1081 for (auto &GlobalList : Index) {

1082

1083 if (GlobalList.second.SummaryList.empty())

1084 continue;

1085

1086 assert(GlobalList.second.SummaryList.size() == 1 &&

1087 "Expected module's index to have one summary per GUID");

1088 auto &Summary = GlobalList.second.SummaryList[0];

1089 if (!IsThinLTO) {

1090 Summary->setNotEligibleToImport();

1091 continue;

1092 }

1093

1094 bool AllRefsCanBeExternallyReferenced =

1096 return !CantBePromoted.count(VI.getGUID());

1097 });

1098 if (!AllRefsCanBeExternallyReferenced) {

1099 Summary->setNotEligibleToImport();

1100 continue;

1101 }

1102

1103 if (auto *FuncSummary = dyn_cast(Summary.get())) {

1104 bool AllCallsCanBeExternallyReferenced = llvm::all_of(

1106 return !CantBePromoted.count(Edge.first.getGUID());

1107 });

1108 if (!AllCallsCanBeExternallyReferenced)

1109 Summary->setNotEligibleToImport();

1110 }

1111 }

1112

1114 std::error_code EC;

1116 if (EC)

1119 Index.exportToDot(OSDot, {});

1120 }

1121

1122 return Index;

1123}

1124

1125AnalysisKey ModuleSummaryIndexAnalysis::Key;

1126

1133 M,

1137 },

1138 &PSI,

1142 : nullptr;

1143 });

1144}

1145

1147

1149 "Module Summary Analysis", false, true)

1155

1158}

1159

1163}

1164

1166 auto *PSI = &getAnalysis().getPSI();

1169 M,

1171 return &(this->getAnalysis(

1173 .getBFI());

1174 },

1175 PSI,

1177 return NeedSSI ? &getAnalysis(

1179 .getResult()

1180 : nullptr;

1181 }));

1182 return false;

1183}

1184

1186 Index.reset();

1187 return false;

1188}

1189

1195}

1196

1198

1204}

1205

1209}

1210

1214}

1215

1217 "Module summary info", false, true)

1218

1220 if (!CB)

1221 return false;

1222 if (CB->isDebugOrPseudoInst())

1223 return false;

1224 auto *CI = dyn_cast(CB);

1225 auto *CalledValue = CB->getCalledOperand();

1226 auto *CalledFunction = CB->getCalledFunction();

1227 if (CalledValue && !CalledFunction) {

1228 CalledValue = CalledValue->stripPointerCasts();

1229

1230 CalledFunction = dyn_cast(CalledValue);

1231 }

1232

1233

1234 if (auto *GA = dyn_cast(CalledValue)) {

1235 assert(!CalledFunction &&

1236 "Expected null called function in callsite for alias");

1237 CalledFunction = dyn_cast(GA->getAliaseeObject());

1238 }

1239

1240

1241 if (CalledFunction) {

1242 if (CI && CalledFunction->isIntrinsic())

1243 return false;

1244 } else {

1245

1247 return false;

1248

1249 if (CI && CI->isInlineAsm())

1250 return false;

1251

1252 if (!CalledValue || isa(CalledValue))

1253 return false;

1254 return true;

1255 }

1256 return true;

1257}

static bool isConstant(const MachineInstr &MI)

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

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

block Block Frequency Analysis

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

#define clEnumValN(ENUMVAL, FLAGNAME, DESC)

This file contains the declarations for the subclasses of Constant, which represent the different fla...

This file defines the DenseSet and SmallDenseSet classes.

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

This defines the Use class.

This file implements a map that provides insertion order iteration.

static void addVCallToSet(DevirtCallSite Call, GlobalValue::GUID Guid, SetVector< FunctionSummary::VFuncId, std::vector< FunctionSummary::VFuncId > > &VCalls, SetVector< FunctionSummary::ConstVCall, std::vector< FunctionSummary::ConstVCall > > &ConstVCalls)

Determine whether this call has all constant integer arguments (excluding "this") and summarize it to...

cl::opt< unsigned > MaxNumVTableAnnotations

static void computeVTableFuncs(ModuleSummaryIndex &Index, const GlobalVariable &V, const Module &M, VTableFuncList &VTableFuncs)

static void computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A, DenseSet< GlobalValue::GUID > &CantBePromoted)

static void findFuncPointers(const Constant *I, uint64_t StartingOffset, const Module &M, ModuleSummaryIndex &Index, VTableFuncList &VTableFuncs, const GlobalVariable &OrigGV)

Find function pointers referenced within the given vtable initializer (or subset of an initializer) I...

static void computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V, DenseSet< GlobalValue::GUID > &CantBePromoted, const Module &M, SmallVectorImpl< MDNode * > &Types)

static void setLiveRoot(ModuleSummaryIndex &Index, StringRef Name)

static CalleeInfo::HotnessType getHotness(uint64_t ProfileCount, ProfileSummaryInfo *PSI)

static cl::opt< bool > EnableMemProfIndirectCallSupport("enable-memprof-indirect-call-support", cl::init(false), cl::Hidden, cl::desc("Enable MemProf support for summarizing and cloning indirect calls"))

static bool isNonVolatileLoad(const Instruction *I)

cl::opt< bool > ScalePartialSampleProfileWorkingSetSize

cl::opt< bool > MemProfReportHintedSizes

static bool isNonRenamableLocal(const GlobalValue &GV)

static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M, const Function &F, BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, DominatorTree &DT, bool HasLocalsInUsedOrAsm, DenseSet< GlobalValue::GUID > &CantBePromoted, bool IsThinLTO, std::function< const StackSafetyInfo *(const Function &F)> GetSSICallback)

static cl::opt< FunctionSummary::ForceSummaryHotnessType, true > FSEC("force-summary-edges-cold", cl::Hidden, cl::location(ForceSummaryEdgesCold), cl::desc("Force all edges in the function summary to cold"), cl::values(clEnumValN(FunctionSummary::FSHT_None, "none", "None."), clEnumValN(FunctionSummary::FSHT_AllNonCritical, "all-non-critical", "All non-critical edges."), clEnumValN(FunctionSummary::FSHT_All, "all", "All edges.")))

static bool mustBeUnreachableFunction(const Function &F)

static bool isNonVolatileStore(const Instruction *I)

static cl::opt< std::string > ModuleSummaryDotFile("module-summary-dot-file", cl::Hidden, cl::value_desc("filename"), cl::desc("File to emit dot graph of new summary into"))

static bool findRefEdges(ModuleSummaryIndex &Index, const User *CurUser, SetVector< ValueInfo, SmallVector< ValueInfo, 0 > > &RefEdges, SmallPtrSet< const User *, 8 > &Visited, bool &RefLocalLinkageIFunc)

static void addIntrinsicToSummary(const CallInst *CI, SetVector< GlobalValue::GUID, std::vector< GlobalValue::GUID > > &TypeTests, SetVector< FunctionSummary::VFuncId, std::vector< FunctionSummary::VFuncId > > &TypeTestAssumeVCalls, SetVector< FunctionSummary::VFuncId, std::vector< FunctionSummary::VFuncId > > &TypeCheckedLoadVCalls, SetVector< FunctionSummary::ConstVCall, std::vector< FunctionSummary::ConstVCall > > &TypeTestAssumeConstVCalls, SetVector< FunctionSummary::ConstVCall, std::vector< FunctionSummary::ConstVCall > > &TypeCheckedLoadConstVCalls, DominatorTree &DT)

If this intrinsic call requires that we add information to the function summary, do so via the non-co...

static void recordTypeIdCompatibleVtableReferences(ModuleSummaryIndex &Index, const GlobalVariable &V, SmallVectorImpl< MDNode * > &Types)

Record vtable definition V for each type metadata it references.

This is the interface to build a ModuleSummaryIndex for a module.

ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...

FunctionAnalysisManager FAM

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file implements a set that has insertion order iteration characteristics.

This file defines the SmallPtrSet class.

This file defines the SmallVector class.

An arbitrary precision integer that knows its signedness.

A container for analyses that lazily runs them and caches their results.

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

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

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

void setPreservesAll()

Set by analyses that do not transform their input at all.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

LLVM Basic Block Representation.

static BlockAddress * get(Function *F, BasicBlock *BB)

Return a BlockAddress for the specified function and basic block.

Analysis pass which computes BlockFrequencyInfo.

Legacy analysis pass which computes BlockFrequencyInfo.

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

Analysis providing branch probability information.

Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...

Function * getCalledFunction() const

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

Value * getArgOperand(unsigned i) const

This class represents a function call, abstracting a target machine's calling convention.

This is an important base class in LLVM.

This class represents an Operation in the Expression.

A parsed version of the target data layout string in and methods for querying it.

Implements a dense probed hash-table based set.

Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.

std::pair< ValueInfo, CalleeInfo > EdgeTy

<CalleeValueInfo, CalleeInfo> call edge pair.

ForceSummaryHotnessType

Types for -force-summary-edges-cold debugging option.

Class to represent profile counts.

Intrinsic::ID getIntrinsicID() const LLVM_READONLY

getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...

bool isDeclaration() const

Return true if the primary definition of this global value is outside of the current translation unit...

bool hasLocalLinkage() const

static GUID getGUID(StringRef GlobalName)

Return a 64-bit global unique ID constructed from global value name (i.e.

GUID getGUID() const

Return a 64-bit global unique ID constructed from global value name (i.e.

@ DefaultVisibility

The GV is visible.

bool canBeOmittedFromSymbolTable() const

True if GV can be left out of the object symbol table.

@ InternalLinkage

Rename collisions when linking (static functions).

const Constant * getInitializer() const

getInitializer - Return the initializer for this global variable.

Legacy wrapper pass to provide the ModuleSummaryIndex object.

ImmutableModuleSummaryIndexWrapperPass(const ModuleSummaryIndex *Index=nullptr)

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...

ImmutablePass class - This class is used to provide information that does not need to be run.

An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...

const MDOperand & getOperand(unsigned I) const

unsigned getNumOperands() const

Return number of MDNode operands.

This class implements a map that also provides access to all stored values in a deterministic order.

VectorType takeVector()

Clear the MapVector and return the underlying vector.

ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...

Result run(Module &M, ModuleAnalysisManager &AM)

Legacy wrapper pass to provide the ModuleSummaryIndex object.

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...

bool doFinalization(Module &M) override

doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes...

ModuleSummaryIndexWrapperPass()

bool runOnModule(Module &M) override

runOnModule - Virtual method overriden by subclasses to process the module being operated on.

Class to hold module path string table and global value map, and encapsulate methods for operating on...

static void CollectAsmSymbols(const Module &M, function_ref< void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol)

Parse inline ASM and collect the symbols that are defined or referenced in the current module.

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

MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...

static PassRegistry * getPassRegistry()

getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...

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

An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.

Analysis providing profile information.

std::optional< uint64_t > getProfileCount(const CallBase &CallInst, BlockFrequencyInfo *BFI, bool AllowSynthetic=false) const

Returns the profile count for CallInst.

bool isColdCount(uint64_t C) const

Returns true if count C is considered cold.

bool hasPartialSampleProfile() const

Returns true if module M has partial-profile sample profile.

bool isHotCount(uint64_t C) const

Returns true if count C is considered hot.

A vector that has set insertion semantics.

bool remove(const value_type &X)

Remove an item from the set vector.

size_type size() const

Determine the number of elements in the SetVector.

Vector takeVector()

Clear the SetVector and return the underlying vector.

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.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

iterator erase(const_iterator CI)

void push_back(const T &Elt)

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

StackSafetyInfo wrapper for the new pass manager.

StackSafetyInfo wrapper for the legacy pass manager.

Interface to access stack safety analysis results for single function.

StringRef - Represent a constant reference to a string, i.e.

Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...

unsigned getElementContainingOffset(uint64_t FixedOffset) const

Given a valid byte offset into the structure, returns the structure index that contains it.

TypeSize getElementOffset(unsigned Idx) const

Class to represent struct types.

ArrayRef< Type * > elements() const

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

TypeID

Definitions of all of the base types for the Type system.

A Use represents the edge between a Value definition and its users.

LLVM Value Representation.

Type * getType() const

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

iterator_range< use_iterator > uses()

std::pair< iterator, bool > insert(const ValueT &V)

size_type count(const_arg_type_t< ValueT > V) const

Return 1 if the specified key is in the set, 0 otherwise.

Helper class to iterate through stack ids in both metadata (memprof MIB and callsite) and the corresp...

CallStackIterator end() const

CallStackIterator beginAfterSharedPrefix(CallStack &Other)

A raw_ostream that writes to a file descriptor.

@ C

The default llvm calling convention, compatible with C.

ValuesClass values(OptsTy... Options)

Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...

initializer< Ty > init(const Ty &Val)

LocationClass< Ty > location(Ty &L)

AllocationType getMIBAllocType(const MDNode *MIB)

Returns the allocation type from an MIB metadata node.

MDNode * getMIBStackNode(const MDNode *MIB)

Returns the stack node from an MIB metadata node.

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

auto enumerate(FirstRange &&First, RestRanges &&...Rest)

Given two or more input ranges, returns a new range whose values are tuples (A, B,...

bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, APInt &Offset, const DataLayout &DL, DSOLocalEquivalent **DSOEquiv=nullptr)

If this constant is a constant offset from a global, return the global and the constant.

FunctionSummary::ForceSummaryHotnessType ForceSummaryEdgesCold

bool needsParamAccessSummary(const Module &M)

ModuleSummaryIndex buildModuleSummaryIndex(const Module &M, std::function< BlockFrequencyInfo *(const Function &F)> GetBFICallback, ProfileSummaryInfo *PSI, std::function< const StackSafetyInfo *(const Function &F)> GetSSICallback=[](const Function &F) -> const StackSafetyInfo *{ return nullptr;})

Direct function to compute a ModuleSummaryIndex from a given module.

void initializeModuleSummaryIndexWrapperPassPass(PassRegistry &)

std::vector< VirtFuncOffset > VTableFuncList

List of functions referenced by a particular vtable definition.

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

void findDevirtualizableCallsForTypeCheckedLoad(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< Instruction * > &LoadedPtrs, SmallVectorImpl< Instruction * > &Preds, bool &HasNonCallUses, const CallInst *CI, DominatorTree &DT)

Given a call to the intrinsic @llvm.type.checked.load, find all devirtualizable call sites based on t...

SmallVector< InstrProfValueData, 4 > getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, uint32_t MaxNumValueData, uint64_t &TotalC, bool GetNoICPValue=false)

Extract the value profile data from Inst and returns them if Inst is annotated with value profile dat...

ModulePass * createModuleSummaryIndexWrapperPass()

ImmutablePass * createImmutableModuleSummaryIndexWrapperPass(const ModuleSummaryIndex *Index)

void initializeImmutableModuleSummaryIndexWrapperPassPass(PassRegistry &)

bool mayHaveMemprofSummary(const CallBase *CB)

Returns true if the instruction could have memprof metadata, used to ensure consistency between summa...

void findDevirtualizableCallsForTypeTest(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< CallInst * > &Assumes, const CallInst *CI, DominatorTree &DT)

Given a call to the intrinsic @llvm.type.test, find all devirtualizable call sites based on the call ...

GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)

Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...

Summary of memprof metadata on allocations.

A special type used by analysis passes to provide an address that identifies that particular analysis...

A call site that could be devirtualized.

A specification for a virtual function call with all constant integer arguments.

Flags specific to function summaries.

An "identifier" for a virtual function.

Group flags (Linkage, NotEligibleToImport, etc.) as a bitfield.

Summary of a single MIB in a memprof metadata on allocations.

Struct that holds a reference to a particular GUID in a global value summary.