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

1

2

3

4

5

6

7

8

9

10

11

12

49#include

50#include

51#include

52#include <system_error>

53#include

54#include

55

56using namespace llvm;

57

58#define DEBUG_TYPE "function-import"

59

61 "Number of functions thin link decided to import");

63 "Number of hot functions thin link decided to import");

64STATISTIC(NumImportedCriticalFunctionsThinLink,

65 "Number of critical functions thin link decided to import");

67 "Number of global variables thin link decided to import");

68STATISTIC(NumImportedFunctions, "Number of functions imported in backend");

70 "Number of global variables imported in backend");

71STATISTIC(NumImportedModules, "Number of modules imported from");

72STATISTIC(NumDeadSymbols, "Number of dead stripped symbols in index");

73STATISTIC(NumLiveSymbols, "Number of live symbols in index");

74

75namespace llvm {

78 cl::desc("Import functions with noinline attribute"));

79

80

83 cl::desc("Only import functions with less than N instructions"));

84

87 cl::desc("Only import first N functions if N>=0 (default -1)"));

88

92 cl::desc("As we import functions, multiply the "

93 "`import-instr-limit` threshold by this factor "

94 "before processing newly imported functions"));

95

99 cl::desc("As we import functions called from hot callsite, multiply the "

100 "`import-instr-limit` threshold by this factor "

101 "before processing newly imported functions"));

102

105 cl::desc("Multiply the `import-instr-limit` threshold for hot callsites"));

106

111 "Multiply the `import-instr-limit` threshold for critical callsites"));

112

113

116 cl::desc("Multiply the `import-instr-limit` threshold for cold callsites"));

117

119 cl::desc("Print imported functions"));

120

123 cl::desc("Print information for functions rejected for importing"));

124

126 cl::desc("Compute dead symbols"));

127

130 cl::desc("Enable import metadata like 'thinlto_src_module' and "

131 "'thinlto_src_file'"));

132

133

134

137 cl::desc("The summary file to use for function importing."));

138

139

140

143 cl::desc("Import all external functions in index."));

144

145

146

147

148

149

150

153 cl::desc("If true, import function declaration as fallback if the function "

154 "definition is not imported."));

155

156

157

158

159

160

161

162

163

165 "thinlto-workload-def",

166 cl::desc("Pass a workload definition. This is a file containing a JSON "

167 "dictionary. The keys are root functions, the values are lists of "

168 "functions to import in the module defining the root. It is "

169 "assumed -funique-internal-linkage-names was used, to ensure "

170 "local linkage functions have unique names. For example: \n"

171 "{\n"

172 " \"rootFunction_1\": [\"function_to_import_1\", "

173 "\"function_to_import_2\"], \n"

174 " \"rootFunction_2\": [\"function_to_import_3\", "

175 "\"function_to_import_4\"] \n"

176 "}"),

178

180

182 "thinlto-move-ctxprof-trees",

183 cl::desc("Move contextual profiling roots and the graphs under them in "

184 "their own module."),

186

188

190}

191

192

193static std::unique_ptr loadFile(const std::string &FileName,

196 LLVM_DEBUG(dbgs() << "Loading '" << FileName << "'\n");

197

198

199 std::unique_ptr Result =

201 true);

202 if (!Result) {

203 Err.print("function-import", errs());

205 }

206

207 return Result;

208}

209

211 size_t NumDefs,

213

214 if (NumDefs == 1)

215 return false;

216

217

218

219

220

221

223 RefSummary->modulePath() != ImporterModule;

224}

225

226

227

228

229

232 ArrayRef<std::unique_ptr> CalleeSummaryList,

235 CalleeSummaryList,

236 [&Index, CalleeSummaryList,

237 CallerModulePath](const std::unique_ptr &SummaryPtr)

240 auto *GVSummary = SummaryPtr.get();

241 if (!Index.isGlobalValueLive(GVSummary))

243

246 GVSummary};

247

249

250

251

252

253

254

255 if (!Summary)

257

258

259

260

261

262

263

264

265

266

267

268

269

271 CallerModulePath))

272 return {

274 GVSummary};

275

276

277

278 if (Summary->notEligibleToImport())

280 GVSummary};

281

283 });

284}

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

303 ArrayRef<std::unique_ptr> CalleeSummaryList,

304 unsigned Threshold, StringRef CallerModulePath,

307

308 TooLargeOrNoInlineSummary = nullptr;

309 auto QualifiedCandidates =

311 for (auto QualifiedValue : QualifiedCandidates) {

312 Reason = QualifiedValue.first;

313

315 continue;

316 auto *Summary =

318

319

320

321 if ((Summary->instCount() > Threshold) && !Summary->fflags().AlwaysInline &&

323 TooLargeOrNoInlineSummary = Summary;

325 continue;

326 }

327

328

330 TooLargeOrNoInlineSummary = Summary;

332 continue;

333 }

334

335 return Summary;

336 }

337 return nullptr;

338}

339

340namespace {

341

342using EdgeInfo = std::tuple<const FunctionSummary *, unsigned >;

343

344}

345

349 auto [Def, Decl] = IDs.createImportIDs(FromModule, GUID);

350 if (!Imports.insert(Def).second)

351

353

354

355

358}

359

362 auto [Def, Decl] = IDs.createImportIDs(FromModule, GUID);

363

364

365 if (!Imports.contains(Def))

366 Imports.insert(Decl);

367}

368

372 for (const auto &[SrcMod, GUID, ImportType] : *this)

373 ModuleSet.insert(SrcMod);

376 return Modules;

377}

378

379std::optionalGlobalValueSummary::ImportKind

382 if (auto IDPair = IDs.getImportIDs(FromModule, GUID)) {

383 auto [Def, Decl] = *IDPair;

384 if (Imports.contains(Def))

386 if (Imports.contains(Decl))

388 }

389 return std::nullopt;

390}

391

392

393

398 IsPrevailing;

401

402 bool shouldImportGlobal(const ValueInfo &VI) {

403 const auto &GVS = DefinedGVSummaries.find(VI.getGUID());

404 if (GVS == DefinedGVSummaries.end())

405 return true;

406

407

408

409

410

411

412

413

414

415

416 if (VI.getSummaryList().size() > 1 &&

418 !IsPrevailing(VI.getGUID(), GVS->second))

419 return true;

420

421 return false;

422 }

423

424 void

427 for (const auto &VI : Summary.refs()) {

428 if (!shouldImportGlobal(VI)) {

430 dbgs() << "Ref ignored! Target already in destination module.\n");

431 continue;

432 }

433

435

436 for (const auto &RefSummary : VI.getSummaryList()) {

438

439

440

441

442

443 bool CanImportDecl = false;

444 if (!GVS ||

446 Summary.modulePath()) ||

447 !Index.canImportGlobalVar(GVS, true,

448 CanImportDecl)) {

450 ImportList.maybeAddDeclaration(RefSummary->modulePath(),

451 VI.getGUID());

452

453 continue;

454 }

455

456

457

458 if (ImportList.addDefinition(RefSummary->modulePath(), VI.getGUID()) !=

460 break;

461

462

463

464 NumImportedGlobalVarsThinLink++;

465

466

467

468 if (ExportLists)

469 (*ExportLists)[RefSummary->modulePath()].insert(VI);

470

471

472

473 if (!Index.isWriteOnly(GVS))

475 break;

476 }

477 }

478 }

479

480public:

484 IsPrevailing,

487 : Index(Index), DefinedGVSummaries(DefinedGVSummaries),

488 IsPrevailing(IsPrevailing), ImportList(ImportList),

489 ExportLists(ExportLists) {}

490

493 onImportingSummaryImpl(Summary, Worklist);

494 while (!Worklist.empty())

495 onImportingSummaryImpl(*Worklist.pop_back_val(), Worklist);

496 }

497};

498

500

501

503 void computeImportForFunction(

509

510protected:

515

523

524public:

526

527

528

529

530 virtual void

534

535 static std::unique_ptr

540 nullptr);

541};

542

543

544

545

547

548

549

551

552

553

554

556

557 void

558 computeImportForModule(const GVSummaryMapTy &DefinedGVSummaries,

564

565 Filename = Filename.substr(0, Filename.find_last_of('.'));

566 }

567 auto SetIter = Workloads.find(Filename);

568

569 if (SetIter == Workloads.end()) {

571 << " does not contain the root of any context.\n");

573 ModName, ImportList);

574 }

576 << " contains the root(s) of context(s).\n");

577

580 auto &ValueInfos = SetIter->second;

582 auto It = DefinedGVSummaries.find(VI.getGUID());

583 if (It != DefinedGVSummaries.end() &&

586 dbgs() << "[Workload] " << VI.name()

587 << " has the prevailing variant already in the module "

588 << ModName << ". No need to import\n");

589 continue;

590 }

591 auto Candidates =

593

597 Candidates,

598 [&](const auto &Candidate) {

599 LLVM_DEBUG(dbgs() << "[Workflow] Candidate for " << VI.name()

600 << " from " << Candidate.second->modulePath()

601 << " ImportFailureReason: "

603 return Candidate.first ==

605 }),

606 [](const auto &Candidate) { return Candidate.second; });

607 if (PotentialCandidates.empty()) {

608 LLVM_DEBUG(dbgs() << "[Workload] Not importing " << VI.name()

609 << " because can't find eligible Callee. Guid is: "

610 << VI.getGUID() << "\n");

611 continue;

612 }

613

614

615

616

617

618

619

620

621

622

623

624

625

626

628 PotentialCandidates, [&](const auto *Candidate) {

629 return IsPrevailing(VI.getGUID(), Candidate);

630 });

631 if (PrevailingCandidates.empty()) {

632 GVS = *PotentialCandidates.begin();

637 << "[Workload] Found multiple non-prevailing candidates for "

638 << VI.name()

639 << ". This is unexpected. Are module paths passed to the "

640 "compiler unique for the modules passed to the linker?");

641

642

643

644

645

647 } else {

649 GVS = *PrevailingCandidates.begin();

650 }

651

652 auto ExportingModule = GVS->modulePath();

653

654

655

656 if (ExportingModule == ModName) {

657 LLVM_DEBUG(dbgs() << "[Workload] Not importing " << VI.name()

658 << " because its defining module is the same as the "

659 "current module\n");

660 continue;

661 }

662 LLVM_DEBUG(dbgs() << "[Workload][Including]" << VI.name() << " from "

663 << ExportingModule << " : " << VI.getGUID() << "\n");

664 ImportList.addDefinition(ExportingModule, VI.getGUID());

667 (*ExportLists)[ExportingModule].insert(VI);

668 }

670 }

671

672 void loadFromJson() {

673

674

677 for (auto &I : Index) {

679 if (!NameToValueInfo.insert(std::make_pair(VI.name(), VI)).second)

681 }

682 auto DbgReportIfAmbiguous = [&](StringRef Name) {

684 dbgs() << "[Workload] Function name " << Name

685 << " present in the workload definition is ambiguous. Consider "

686 "compiling with -funique-internal-linkage-names.";

687 });

688 };

689 std::error_code EC;

691 if (std::error_code EC = BufferOrErr.getError()) {

693 return;

694 }

695 auto Buffer = std::move(BufferOrErr.get());

696 std::map<std::string, std::vectorstd::string> WorkloadDefs;

698

699

700

701

702

703

704 auto Parsed = json::parse(Buffer->getBuffer());

705 if (!Parsed)

707 if (json::fromJSON(*Parsed, WorkloadDefs, NullRoot))

709 for (const auto &Workload : WorkloadDefs) {

710 const auto &Root = Workload.first;

711 DbgReportIfAmbiguous(Root);

712 LLVM_DEBUG(dbgs() << "[Workload] Root: " << Root << "\n");

713 const auto &AllCallees = Workload.second;

714 auto RootIt = NameToValueInfo.find(Root);

715 if (RootIt == NameToValueInfo.end()) {

717 << " not found in this linkage unit.\n");

718 continue;

719 }

720 auto RootVI = RootIt->second;

721 if (RootVI.getSummaryList().size() != 1) {

723 << " should have exactly one summary, but has "

724 << RootVI.getSummaryList().size() << ". Skipping.\n");

725 continue;

726 }

728 RootVI.getSummaryList().front()->modulePath();

729 LLVM_DEBUG(dbgs() << "[Workload] Root defining module for " << Root

730 << " is : " << RootDefiningModule << "\n");

731 auto &Set = Workloads[RootDefiningModule];

732 for (const auto &Callee : AllCallees) {

733 LLVM_DEBUG(dbgs() << "[Workload] " << Callee << "\n");

734 DbgReportIfAmbiguous(Callee);

735 auto ElemIt = NameToValueInfo.find(Callee);

736 if (ElemIt == NameToValueInfo.end()) {

737 LLVM_DEBUG(dbgs() << "[Workload] " << Callee << " not found\n");

738 continue;

739 }

740 Set.insert(ElemIt->second);

741 }

742 }

743 }

744

745 void loadFromCtxProf() {

746 std::error_code EC;

748 if (std::error_code EC = BufferOrErr.getError()) {

750 return;

751 }

752 auto Buffer = std::move(BufferOrErr.get());

753

756 if (!Ctx) {

758 return;

759 }

760 const auto &CtxMap = Ctx->Contexts;

762 for (const auto &[RootGuid, Root] : CtxMap) {

763

764

765 ContainedGUIDs.clear();

766

767 auto RootVI = Index.getValueInfo(RootGuid);

768 if (!RootVI) {

770 << " not found in this linkage unit.\n");

771 continue;

772 }

773 if (RootVI.getSummaryList().size() != 1) {

775 << " should have exactly one summary, but has "

776 << RootVI.getSummaryList().size() << ". Skipping.\n");

777 continue;

778 }

779 std::string RootDefiningModule =

780 RootVI.getSummaryList().front()->modulePath().str();

782 RootDefiningModule = std::to_string(RootGuid);

784 dbgs() << "[Workload] Moving " << RootGuid

785 << " to a module with the filename without extension : "

786 << RootDefiningModule << "\n");

787 } else {

788 LLVM_DEBUG(dbgs() << "[Workload] Root defining module for " << RootGuid

789 << " is : " << RootDefiningModule << "\n");

790 }

791 auto &Set = Workloads[RootDefiningModule];

792 Root.getContainedGuids(ContainedGUIDs);

793 Roots.insert(RootVI);

794 for (auto Guid : ContainedGUIDs)

795 if (auto VI = Index.getValueInfo(Guid))

796 Set.insert(VI);

797 }

798 }

799

800 bool canImport(ValueInfo VI) override { return !Roots.contains(VI); }

801

802public:

810 report_fatal_error(

811 "Pass only one of: -thinlto-pgo-ctx-prof or -thinlto-workload-def");

812 return;

813 }

815 loadFromCtxProf();

816 else

817 loadFromJson();

819 for (const auto &[Root, Set] : Workloads) {

820 dbgs() << "[Workload] Root: " << Root << " we have " << Set.size()

821 << " distinct callees.\n";

822 for (const auto &VI : Set) {

823 dbgs() << "[Workload] Root: " << Root

824 << " Would include: " << VI.getGUID() << "\n";

825 }

826 }

827 });

828 }

829};

830

837 LLVM_DEBUG(dbgs() << "[Workload] Using the regular imports manager.\n");

838 return std::unique_ptr(

840 }

841 LLVM_DEBUG(dbgs() << "[Workload] Using the contextual imports manager.\n");

842 return std::make_unique(IsPrevailing, Index,

844}

845

846static const char *

848 switch (Reason) {

850 return "None";

852 return "GlobalVar";

854 return "NotLive";

856 return "TooLarge";

858 return "InterposableLinkage";

860 return "LocalLinkageNotInModule";

862 return "NotEligible";

864 return "NoInline";

865 }

867}

868

869

870

871

872void ModuleImportsManager::computeImportForFunction(

873 const FunctionSummary &Summary, const unsigned Threshold,

875 SmallVectorImpl &Worklist, GlobalsImporter &GVImporter,

876 FunctionImporter::ImportMapTy &ImportList,

879 static int ImportCount = 0;

880 for (const auto &Edge : Summary.calls()) {

881 ValueInfo VI = Edge.first;

882 LLVM_DEBUG(dbgs() << " edge -> " << VI << " Threshold:" << Threshold

883 << "\n");

884

887 << " reached.\n");

888 continue;

889 }

890

891 if (DefinedGVSummaries.count(VI.getGUID())) {

892

893

894

895 LLVM_DEBUG(dbgs() << "ignored! Target already in destination module.\n");

896 continue;

897 }

898

899 if (!canImport(VI)) {

901 dbgs() << "Skipping over " << VI.getGUID()

902 << " because its import is handled in a different module.");

903 assert(VI.getSummaryList().size() == 1 &&

904 "The root was expected to be an external symbol");

905 continue;

906 }

907

915 return 1.0;

916 };

917

918 const auto NewThreshold =

919 Threshold * GetBonusMultiplier(Edge.second.getHotness());

920

921 auto IT = ImportThresholds.insert(std::make_pair(

922 VI.getGUID(), std::make_tuple(NewThreshold, nullptr, nullptr)));

923 bool PreviouslyVisited = IT.second;

924 auto &ProcessedThreshold = std::get<0>(IT.first->second);

925 auto &CalleeSummary = std::get<1>(IT.first->second);

926 auto &FailureInfo = std::get<2>(IT.first->second);

927

928 bool IsHotCallsite =

930 bool IsCriticalCallsite =

932

933 const FunctionSummary *ResolvedCalleeSummary = nullptr;

934 if (CalleeSummary) {

935 assert(PreviouslyVisited);

936

937

938

939

940 if (NewThreshold <= ProcessedThreshold) {

942 dbgs() << "ignored! Target was already imported with Threshold "

943 << ProcessedThreshold << "\n");

944 continue;

945 }

946

947 ProcessedThreshold = NewThreshold;

949 } else {

950

951

952 if (PreviouslyVisited && NewThreshold <= ProcessedThreshold) {

954 dbgs() << "ignored! Target was already rejected with Threshold "

955 << ProcessedThreshold << "\n");

957 assert(FailureInfo &&

958 "Expected FailureInfo for previously rejected candidate");

959 FailureInfo->Attempts++;

960 }

961 continue;

962 }

963

965

966

967 const GlobalValueSummary *SummaryForDeclImport = nullptr;

968 CalleeSummary =

969 selectCallee(Index, VI.getSummaryList(), NewThreshold,

970 Summary.modulePath(), SummaryForDeclImport, Reason);

971 if (!CalleeSummary) {

972

973

975 StringRef DeclSourceModule = SummaryForDeclImport->modulePath();

976

977

978

980 }

981

982

983

984 if (PreviouslyVisited) {

985 ProcessedThreshold = NewThreshold;

987 assert(FailureInfo &&

988 "Expected FailureInfo for previously rejected candidate");

989 FailureInfo->Reason = Reason;

990 FailureInfo->Attempts++;

991 FailureInfo->MaxHotness =

992 std::max(FailureInfo->MaxHotness, Edge.second.getHotness());

993 }

995 assert(!FailureInfo &&

996 "Expected no FailureInfo for newly rejected candidate");

997 FailureInfo = std::make_uniqueFunctionImporter::ImportFailureInfo(

998 VI, Edge.second.getHotness(), Reason, 1);

999 }

1001 std::string Msg = std::string("Failed to import function ") +

1002 VI.name().str() + " due to " +

1007 "Error importing module: ");

1008 break;

1009 } else {

1011 << "ignored! No qualifying callee with summary found.\n");

1012 continue;

1013 }

1014 }

1015

1016

1017 CalleeSummary = CalleeSummary->getBaseObject();

1019

1021 (ResolvedCalleeSummary->instCount() <= NewThreshold)) &&

1022 "selectCallee() didn't honor the threshold");

1023

1024 auto ExportModulePath = ResolvedCalleeSummary->modulePath();

1025

1026

1027

1028 if (ImportList.addDefinition(ExportModulePath, VI.getGUID()) !=

1030 NumImportedFunctionsThinLink++;

1031 if (IsHotCallsite)

1032 NumImportedHotFunctionsThinLink++;

1033 if (IsCriticalCallsite)

1034 NumImportedCriticalFunctionsThinLink++;

1035 }

1036

1037

1038

1039

1040 if (ExportLists)

1041 (*ExportLists)[ExportModulePath].insert(VI);

1042 }

1043

1044 auto GetAdjustedThreshold = [](unsigned Threshold, bool IsHotCallsite) {

1045

1046

1047

1048 if (IsHotCallsite)

1051 };

1052

1053 const auto AdjThreshold = GetAdjustedThreshold(Threshold, IsHotCallsite);

1054

1055 ImportCount++;

1056

1057

1058 Worklist.emplace_back(ResolvedCalleeSummary, AdjThreshold);

1059 }

1060}

1061

1065

1066

1071

1072

1073

1074 for (const auto &GVSummary : DefinedGVSummaries) {

1075#ifndef NDEBUG

1076

1077

1078 auto VI = Index.getValueInfo(GVSummary.first);

1079#endif

1080 if (Index.isGlobalValueLive(GVSummary.second)) {

1081 LLVM_DEBUG(dbgs() << "Ignores Dead GUID: " << VI << "\n");

1082 continue;

1083 }

1084 auto *FuncSummary =

1086 if (!FuncSummary)

1087

1088 continue;

1089 LLVM_DEBUG(dbgs() << "Initialize import for " << VI << "\n");

1090 computeImportForFunction(*FuncSummary, ImportInstrLimit, DefinedGVSummaries,

1091 Worklist, GVI, ImportList, ImportThresholds);

1092 }

1093

1094

1095 while (!Worklist.empty()) {

1097 auto *Summary = std::get<0>(GVInfo);

1098 auto Threshold = std::get<1>(GVInfo);

1099

1101 computeImportForFunction(*FS, Threshold, DefinedGVSummaries, Worklist,

1102 GVI, ImportList, ImportThresholds);

1103 }

1104

1105

1106

1108 dbgs() << "Missed imports into module " << ModName << "\n";

1109 for (auto &I : ImportThresholds) {

1110 auto &ProcessedThreshold = std::get<0>(I.second);

1111 auto &CalleeSummary = std::get<1>(I.second);

1112 auto &FailureInfo = std::get<2>(I.second);

1113 if (CalleeSummary)

1114 continue;

1115 assert(FailureInfo);

1117 if (!FailureInfo->VI.getSummaryList().empty())

1119 FailureInfo->VI.getSummaryList()[0]->getBaseObject());

1120 dbgs() << FailureInfo->VI

1121 << ": Reason = " << getFailureName(FailureInfo->Reason)

1122 << ", Threshold = " << ProcessedThreshold

1123 << ", Size = " << (FS ? (int)FS->instCount() : -1)

1124 << ", MaxHotness = " << getHotnessName(FailureInfo->MaxHotness)

1125 << ", Attempts = " << FailureInfo->Attempts << "\n";

1126 }

1127 }

1128}

1129

1130#ifndef NDEBUG

1132 auto SL = VI.getSummaryList();

1133 return SL.empty()

1136}

1137

1140 if (const auto &VI = Index.getValueInfo(G))

1142 return false;

1143}

1144

1145

1146static unsigned

1149 unsigned NumGVS = 0;

1150 for (auto &VI : ExportSet)

1152 ++NumGVS;

1153 return NumGVS;

1154}

1155

1161

1162

1167

1168 for (const auto &[FromModule, GUID, Type] : ImportList) {

1170 ++Entry.Count;

1172 ++Entry.NumGVS;

1174 ++Entry.DefinedFS;

1175 }

1176 return Histogram;

1177}

1178#endif

1179

1180#ifndef NDEBUG

1186

1187 for (const auto &ImportPerModule : ImportLists)

1188 for (const auto &[FromModule, GUID, ImportType] : ImportPerModule.second)

1189 FlattenedImports.insert(GUID);

1190

1191

1192

1193

1194

1195

1196

1197 auto IsReadOrWriteOnlyVarNeedingImporting = [&](StringRef ModulePath,

1200 Index.findSummaryInModule(VI, ModulePath));

1201 return GVS && (Index.isReadOnly(GVS) || Index.isWriteOnly(GVS)) &&

1205 };

1206

1207 for (auto &ExportPerModule : ExportLists)

1208 for (auto &VI : ExportPerModule.second)

1209 if (!FlattenedImports.count(VI.getGUID()) &&

1210 IsReadOrWriteOnlyVarNeedingImporting(ExportPerModule.first, VI))

1211 return false;

1212

1213 return true;

1214}

1215#endif

1216

1217

1222 isPrevailing,

1226

1227 for (const auto &DefinedGVSummaries : ModuleToDefinedGVSummaries) {

1228 auto &ImportList = ImportLists[DefinedGVSummaries.first];

1229 LLVM_DEBUG(dbgs() << "Computing import for Module '"

1230 << DefinedGVSummaries.first << "'\n");

1231 MIS->computeImportForModule(DefinedGVSummaries.second,

1232 DefinedGVSummaries.first, ImportList);

1233 }

1234

1235

1236

1237

1238

1239

1240 for (auto &ELI : ExportLists) {

1241

1242

1244 const auto &DefinedGVSummaries =

1245 ModuleToDefinedGVSummaries.lookup(ELI.first);

1246 for (auto &EI : ELI.second) {

1247

1248

1249

1250

1251

1252

1253 auto DS = DefinedGVSummaries.find(EI.getGUID());

1254

1255

1256 assert(DS != DefinedGVSummaries.end());

1257 auto *S = DS->getSecond();

1258 S = S->getBaseObject();

1260

1261

1262

1263

1264 if (!Index.isWriteOnly(GVS))

1266 } else {

1270 }

1271 }

1272

1273

1274

1275

1276 for (auto EI = NewExports.begin(); EI != NewExports.end();) {

1277 if (!DefinedGVSummaries.count(EI->getGUID()))

1278 NewExports.erase(EI++);

1279 else

1280 ++EI;

1281 }

1282 ELI.second.insert_range(NewExports);

1283 }

1284

1286#ifndef NDEBUG

1287 LLVM_DEBUG(dbgs() << "Import/Export lists for " << ImportLists.size()

1288 << " modules:\n");

1289 for (const auto &ModuleImports : ImportLists) {

1290 auto ModName = ModuleImports.first;

1291 auto &Exports = ExportLists[ModName];

1295 LLVM_DEBUG(dbgs() << "* Module " << ModName << " exports "

1296 << Exports.size() - NumGVS << " functions and " << NumGVS

1297 << " vars. Imports from " << Histogram.size()

1298 << " modules.\n");

1299 for (const auto &[SrcModName, Stats] : Histogram) {

1301 << " function definitions and "

1303 << " function declarations imported from " << SrcModName

1304 << "\n");

1306 << " global vars imported from " << SrcModName << "\n");

1307 }

1308 }

1309#endif

1310}

1311

1312#ifndef NDEBUG

1318 LLVM_DEBUG(dbgs() << "* Module " << ModulePath << " imports from "

1319 << Histogram.size() << " modules.\n");

1320 for (const auto &[SrcModName, Stats] : Histogram) {

1322 << " function definitions and "

1324 << " function declarations imported from " << SrcModName

1325 << "\n");

1327 << SrcModName << "\n");

1328 }

1329}

1330#endif

1331

1332

1333

1334

1335

1336

1337

1338

1339

1343 isPrevailing,

1346

1347

1349 Index.collectDefinedFunctionsForModule(ModulePath, FunctionSummaryMap);

1350

1351

1352 LLVM_DEBUG(dbgs() << "Computing import for Module '" << ModulePath << "'\n");

1354 MIS->computeImportForModule(FunctionSummaryMap, ModulePath, ImportList);

1355

1356#ifndef NDEBUG

1358#endif

1359}

1360

1361

1362

1363

1364

1365

1369 for (const auto &GlobalList : Index) {

1370

1371 if (GlobalList.second.getSummaryList().empty())

1372 continue;

1373

1374 auto GUID = GlobalList.first;

1375 assert(GlobalList.second.getSummaryList().size() == 1 &&

1376 "Expected individual combined index to have one summary per GUID");

1377 auto &Summary = GlobalList.second.getSummaryList()[0];

1378

1379

1380 if (Summary->modulePath() == ModulePath)

1381 continue;

1382

1383 ImportList.addGUID(Summary->modulePath(), GUID, Summary->importType());

1384 }

1385#ifndef NDEBUG

1387#endif

1388}

1389

1390

1391

1392

1393

1396 for (auto &EI : FS->mutableCalls()) {

1397 if (!EI.first.getSummaryList().empty())

1398 continue;

1399 auto GUID = Index.getGUIDFromOriginalID(EI.first.getGUID());

1400 if (GUID == 0)

1401 continue;

1402

1403 auto VI = Index.getValueInfo(GUID);

1405 VI.getSummaryList(),

1406 [&](const std::unique_ptr &SummaryPtr) {

1407

1408

1409

1410

1411

1412

1413

1414

1415

1416 return SummaryPtr->getSummaryKind() ==

1417 GlobalValueSummary::GlobalVarKind;

1418 }))

1419 continue;

1420 EI.first = VI;

1421 }

1422}

1423

1425 for (const auto &Entry : Index) {

1426 for (const auto &S : Entry.second.getSummaryList()) {

1429 }

1430 }

1431}

1432

1437 assert(!Index.withGlobalValueDeadStripping());

1439

1440 GUIDPreservedSymbols.empty()) {

1441

1443 return;

1444 }

1445 unsigned LiveSymbols = 0;

1447 Worklist.reserve(GUIDPreservedSymbols.size() * 2);

1448 for (auto GUID : GUIDPreservedSymbols) {

1449 ValueInfo VI = Index.getValueInfo(GUID);

1450 if (!VI)

1451 continue;

1452 for (const auto &S : VI.getSummaryList())

1453 S->setLive(true);

1454 }

1455

1456

1457 for (const auto &Entry : Index) {

1458 auto VI = Index.getValueInfo(Entry);

1459 for (const auto &S : Entry.second.getSummaryList()) {

1462 if (S->isLive()) {

1465 ++LiveSymbols;

1466 break;

1467 }

1468 }

1469 }

1470

1471

1473

1474

1475

1476

1477

1478

1479

1480

1481

1483 [](const std::unique_ptrllvm::GlobalValueSummary &S) {

1484 return S->isLive();

1485 }))

1486 return;

1487

1488

1489

1490

1491

1492

1494 bool KeepAliveLinkage = false;

1495 bool Interposable = false;

1496 for (const auto &S : VI.getSummaryList()) {

1500 KeepAliveLinkage = true;

1502 Interposable = true;

1503 }

1504

1505 if (!IsAliasee) {

1506 if (!KeepAliveLinkage)

1507 return;

1508

1509 if (Interposable)

1511 "Interposable and available_externally/linkonce_odr/weak_odr "

1512 "symbol");

1513 }

1514 }

1515

1516 for (const auto &S : VI.getSummaryList())

1517 S->setLive(true);

1518 ++LiveSymbols;

1520 };

1521

1522 while (!Worklist.empty()) {

1524 for (const auto &Summary : VI.getSummaryList()) {

1526

1527

1528

1529 visit(AS->getAliaseeVI(), true);

1530 continue;

1531 }

1532 for (auto Ref : Summary->refs())

1535 for (auto Call : FS->calls())

1537 }

1538 }

1539 Index.setWithGlobalValueDeadStripping();

1540

1541 unsigned DeadSymbols = Index.size() - LiveSymbols;

1542 LLVM_DEBUG(dbgs() << LiveSymbols << " symbols Live, and " << DeadSymbols

1543 << " symbols Dead \n");

1544 NumDeadSymbols += DeadSymbols;

1545 NumLiveSymbols += LiveSymbols;

1546}

1547

1548

1553 bool ImportEnabled) {

1554 llvm::TimeTraceScope timeScope("Drop dead symbols and propagate attributes");

1556 isPrevailing);

1557 if (ImportEnabled)

1558 Index.propagateAttributes(GUIDPreservedSymbols);

1559}

1560

1561

1562

1569

1570 ModuleToSummariesForIndex[std::string(ModulePath)] =

1571 ModuleToDefinedGVSummaries.lookup(ModulePath);

1572

1573

1574

1575

1576

1577

1580 auto It = Map.find(Key);

1581 if (It == Map.end())

1582 std::tie(It, std::ignore) =

1584 return It->second;

1585 };

1586

1587

1588 for (const auto &[FromModule, GUID, ImportType] : ImportList) {

1589 auto &SummariesForIndex =

1590 LookupOrCreate(ModuleToSummariesForIndex, FromModule);

1591

1592 const auto &DefinedGVSummaries = ModuleToDefinedGVSummaries.at(FromModule);

1593 const auto &DS = DefinedGVSummaries.find(GUID);

1594 assert(DS != DefinedGVSummaries.end() &&

1595 "Expected a defined summary for imported global value");

1597 DecSummaries.insert(DS->second);

1598

1599 SummariesForIndex[GUID] = DS->second;

1600 }

1601}

1602

1603

1607 std::error_code EC;

1609 if (EC)

1613 [&](StringRef M) { ImportsOS << M << "\n"; });

1615}

1616

1617

1618

1623 for (const auto &ILI : ModuleToSummariesForIndex)

1624

1625

1626

1627 if (ILI.first != ModulePath)

1628 F(ILI.first);

1629}

1630

1633 << "\n");

1635 F->deleteBody();

1636 F->clearMetadata();

1637 F->setComdat(nullptr);

1639 V->setInitializer(nullptr);

1641 V->clearMetadata();

1642 V->setComdat(nullptr);

1643 } else {

1646 NewGV =

1650 else

1651 NewGV =

1654 nullptr, "",

1659 return false;

1660 }

1663 return true;

1664}

1665

1671 auto FinalizeInModule = [&](GlobalValue &GV, bool Propagate = false) {

1672

1673 const auto &GS = DefinedGlobals.find(GV.getGUID());

1674 if (GS == DefinedGlobals.end())

1675 return;

1676

1677 if (Propagate)

1680

1681 if (FS->fflags().ReadNone && F->doesNotAccessMemory())

1682 F->setDoesNotAccessMemory();

1683

1684 if (FS->fflags().ReadOnly && F->onlyReadsMemory())

1685 F->setOnlyReadsMemory();

1686

1687 if (FS->fflags().NoRecurse && F->doesNotRecurse())

1688 F->setDoesNotRecurse();

1689

1690 if (FS->fflags().NoUnwind && F->doesNotThrow())

1691 F->setDoesNotThrow();

1692 }

1693 }

1694

1695 auto NewLinkage = GS->second->linkage();

1697

1698

1699

1701

1703 return;

1704

1705

1706

1707

1708

1711

1713 return;

1714

1715

1716

1717

1718

1719

1723

1724

1725

1727 } else {

1728

1729

1730

1731

1732

1734 GS->second->canAutoHide()) {

1737 }

1738

1740 << "` from " << GV.getLinkage() << " to " << NewLinkage

1741 << "\n");

1743 }

1744

1745

1746

1748 if (GO && GO->isDeclarationForLinker() && GO->hasComdat()) {

1749 if (GO->getComdat()->getName() == GO->getName())

1750 NonPrevailingComdats.insert(GO->getComdat());

1751 GO->setComdat(nullptr);

1752 }

1753 };

1754

1755

1756 for (auto &GV : TheModule)

1758 for (auto &GV : TheModule.globals())

1759 FinalizeInModule(GV);

1760 for (auto &GV : TheModule.aliases())

1761 FinalizeInModule(GV);

1762

1763

1764

1765

1766 if (NonPrevailingComdats.empty())

1767 return;

1769 if (auto *C = GO.getComdat(); C && NonPrevailingComdats.count(C)) {

1770 GO.setComdat(nullptr);

1772 }

1773 }

1775 do {

1777

1778

1779

1780

1781 for (auto &GA : TheModule.aliases()) {

1782 if (GA.hasAvailableExternallyLinkage())

1783 continue;

1785 assert(Obj && "aliasee without an base object is unimplemented");

1786 if (Obj->hasAvailableExternallyLinkage()) {

1789 }

1790 }

1792}

1793

1794

1798

1799

1800 auto MustPreserveGV = [&](const GlobalValue &GV) -> bool {

1801

1802

1803

1807 return true;

1808

1809

1810 auto GS = DefinedGlobals.find(GV.getGUID());

1811 if (GS == DefinedGlobals.end()) {

1812

1813

1814

1815

1816

1822 GS = DefinedGlobals.find(

1824 if (GS == DefinedGlobals.end()) {

1825

1826

1827

1828

1829

1830

1831 GS = DefinedGlobals.find(

1833 assert(GS != DefinedGlobals.end());

1834 }

1835 }

1837 };

1838

1839

1840

1842}

1843

1844

1847

1850

1851

1856 return NewFn;

1857}

1858

1859

1860

1862 for (auto &GV : M.globals())

1863

1864

1865 if (!GV.isDeclaration() && GV.hasAttribute("thinlto-internalize")) {

1868 }

1869}

1870

1871

1872

1877 unsigned ImportedCount = 0, ImportedGVCount = 0;

1878

1879

1880

1881

1884 for (auto &F : DestModule)

1885 if (F.isDeclaration() && MoveSymbolGUIDSet.contains(F.getGUID()))

1886 F.deleteBody();

1887

1888 IRMover Mover(DestModule);

1889

1890

1893

1895 if (!SrcModuleOrErr)

1896 return SrcModuleOrErr.takeError();

1897 std::unique_ptr SrcModule = std::move(*SrcModuleOrErr);

1898 assert(&DestModule.getContext() == &SrcModule->getContext() &&

1899 "Context mismatch");

1900

1901

1902

1903 if (Error Err = SrcModule->materializeMetadata())

1904 return std::move(Err);

1905

1906

1908 {

1910 for (Function &F : *SrcModule) {

1911 if (F.hasName())

1912 continue;

1913 auto GUID = F.getGUID();

1914 auto MaybeImportType = ImportList.getImportType(ModName, GUID);

1915 bool ImportDefinition =

1917

1918 LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")

1919 << " importing function"

1920 << (ImportDefinition

1921 ? " definition "

1922 : (MaybeImportType ? " declaration " : " "))

1923 << GUID << " " << F.getName() << " from "

1924 << SrcModule->getSourceFileName() << "\n");

1925 if (ImportDefinition) {

1926 if (Error Err = F.materialize())

1927 return std::move(Err);

1928

1929

1931

1932

1933 F.setMetadata(

1934 "thinlto_src_module",

1936 {MDString::get(DestModule.getContext(),

1937 SrcModule->getModuleIdentifier())}));

1938 F.setMetadata(

1939 "thinlto_src_file",

1941 {MDString::get(DestModule.getContext(),

1942 SrcModule->getSourceFileName())}));

1943 }

1944 GlobalsToImport.insert(&F);

1945 }

1946 }

1947 }

1948 {

1951 if (!GV.hasName())

1952 continue;

1953 auto GUID = GV.getGUID();

1954 auto MaybeImportType = ImportList.getImportType(ModName, GUID);

1955 bool ImportDefinition =

1957

1958 LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")

1959 << " importing global"

1960 << (ImportDefinition

1961 ? " definition "

1962 : (MaybeImportType ? " declaration " : " "))

1963 << GUID << " " << GV.getName() << " from "

1964 << SrcModule->getSourceFileName() << "\n");

1965 if (ImportDefinition) {

1966 if (Error Err = GV.materialize())

1967 return std::move(Err);

1968 ImportedGVCount += GlobalsToImport.insert(&GV);

1969 }

1970 }

1971 }

1972 {

1974 for (GlobalAlias &GA : SrcModule->aliases()) {

1975 if (!GA.hasName() || isa(GA.getAliaseeObject()))

1976 continue;

1977 auto GUID = GA.getGUID();

1978 auto MaybeImportType = ImportList.getImportType(ModName, GUID);

1979 bool ImportDefinition =

1981

1982 LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")

1983 << " importing alias"

1984 << (ImportDefinition

1985 ? " definition "

1986 : (MaybeImportType ? " declaration " : " "))

1987 << GUID << " " << GA.getName() << " from "

1988 << SrcModule->getSourceFileName() << "\n");

1989 if (ImportDefinition) {

1990 if (Error Err = GA.materialize())

1991 return std::move(Err);

1992

1995 return std::move(Err);

1998 << " " << GO->getName() << " from "

1999 << SrcModule->getSourceFileName() << "\n");

2001

2002

2003 Fn->setMetadata(

2004 "thinlto_src_module",

2006 {MDString::get(DestModule.getContext(),

2007 SrcModule->getModuleIdentifier())}));

2008 Fn->setMetadata(

2009 "thinlto_src_file",

2011 {MDString::get(DestModule.getContext(),

2012 SrcModule->getSourceFileName())}));

2013 }

2014 GlobalsToImport.insert(Fn);

2015 }

2016 }

2017 }

2018

2019

2020

2022

2023

2024

2025

2026

2027 SrcModule->setPartialSampleProfileRatio(Index);

2028

2029

2031 &GlobalsToImport);

2032

2034 for (const auto *GV : GlobalsToImport)

2036 << " from " << SrcModule->getSourceFileName() << "\n";

2037 }

2038

2039 if (Error Err = Mover.move(std::move(SrcModule),

2041 true))

2043 Twine("Function Import: link error: ") +

2045

2046 ImportedCount += GlobalsToImport.size();

2047 NumImportedModules++;

2048 }

2049

2051

2052 NumImportedFunctions += (ImportedCount - ImportedGVCount);

2053 NumImportedGlobalVars += ImportedGVCount;

2054

2055

2056 LLVM_DEBUG(dbgs() << "Imported " << ImportedCount - ImportedGVCount

2057 << " functions for Module "

2060 << " global variables for Module "

2062 return ImportedCount;

2063}

2064

2067 isPrevailing) {

2069 report_fatal_error("error: -function-import requires -summary-file\n");

2072 if (!IndexPtrOrErr) {

2074 "Error loading file '" + SummaryFile + "': ");

2075 return false;

2076 }

2077 std::unique_ptr Index = std::move(*IndexPtrOrErr);

2078

2079

2082

2083

2084

2087 *Index, ImportList);

2088 else

2090 isPrevailing, *Index, ImportList);

2091

2092

2093

2094

2095

2096 for (auto &I : *Index) {

2097 for (auto &S : I.second.getSummaryList()) {

2100 }

2101 }

2102

2103

2104

2106 nullptr);

2107

2108

2109 auto ModuleLoader = [&M](StringRef Identifier) {

2110 return loadFile(std::string(Identifier), M.getContext());

2111 };

2113 false);

2115

2116

2117 if (!Result) {

2119 "Error importing module: ");

2120 return true;

2121 }

2122

2123 return true;

2124}

2125

2128

2129

2130

2131

2133 return true;

2134 };

2137

2139}

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

static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))

static auto qualifyCalleeCandidates(const ModuleSummaryIndex &Index, ArrayRef< std::unique_ptr< GlobalValueSummary > > CalleeSummaryList, StringRef CallerModulePath)

Given a list of possible callee implementation for a call site, qualify the legality of importing eac...

Definition FunctionImport.cpp:230

static DenseMap< StringRef, ImportStatistics > collectImportStatistics(const ModuleSummaryIndex &Index, const FunctionImporter::ImportMapTy &ImportList)

Definition FunctionImport.cpp:1164

static unsigned numGlobalVarSummaries(const ModuleSummaryIndex &Index, FunctionImporter::ExportSetTy &ExportSet)

Definition FunctionImport.cpp:1147

static bool checkVariableImport(const ModuleSummaryIndex &Index, FunctionImporter::ImportListsTy &ImportLists, DenseMap< StringRef, FunctionImporter::ExportSetTy > &ExportLists)

Definition FunctionImport.cpp:1181

static bool doImportingForModuleForTest(Module &M, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing)

Definition FunctionImport.cpp:2065

static const char * getFailureName(FunctionImporter::ImportFailureReason Reason)

Definition FunctionImport.cpp:847

static void internalizeGVsAfterImport(Module &M)

Definition FunctionImport.cpp:1861

void updateValueInfoForIndirectCalls(ModuleSummaryIndex &Index, FunctionSummary *FS)

Definition FunctionImport.cpp:1394

static std::unique_ptr< Module > loadFile(const std::string &FileName, LLVMContext &Context)

Definition FunctionImport.cpp:193

static bool shouldSkipLocalInAnotherModule(const GlobalValueSummary *RefSummary, size_t NumDefs, StringRef ImporterModule)

Definition FunctionImport.cpp:210

static bool isGlobalVarSummary(const ModuleSummaryIndex &Index, ValueInfo VI)

Definition FunctionImport.cpp:1131

static Function * replaceAliasWithAliasee(Module *SrcModule, GlobalAlias *GA)

Make alias a clone of its aliasee.

Definition FunctionImport.cpp:1845

static void dumpImportListForModule(const ModuleSummaryIndex &Index, StringRef ModulePath, FunctionImporter::ImportMapTy &ImportList)

Definition FunctionImport.cpp:1313

static void ComputeCrossModuleImportForModuleFromIndexForTest(StringRef ModulePath, const ModuleSummaryIndex &Index, FunctionImporter::ImportMapTy &ImportList)

Mark all external summaries in Index for import into the given module.

Definition FunctionImport.cpp:1366

static const GlobalValueSummary * selectCallee(const ModuleSummaryIndex &Index, ArrayRef< std::unique_ptr< GlobalValueSummary > > CalleeSummaryList, unsigned Threshold, StringRef CallerModulePath, const GlobalValueSummary *&TooLargeOrNoInlineSummary, FunctionImporter::ImportFailureReason &Reason)

Given a list of possible callee implementation for a call site, select one that fits the Threshold fo...

Definition FunctionImport.cpp:302

static void ComputeCrossModuleImportForModuleForTest(StringRef ModulePath, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing, const ModuleSummaryIndex &Index, FunctionImporter::ImportMapTy &ImportList)

Compute all the imports for the given module using the Index.

Definition FunctionImport.cpp:1340

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

This file supports working with JSON data.

block placement Basic Block Placement Stats

static cl::opt< std::string > OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), cl::init("-"))

static cl::opt< bool > PropagateAttrs("propagate-attrs", cl::init(true), cl::Hidden, cl::desc("Propagate attributes in index"))

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

Reader for contextual iFDO profile, which comes in bitstream format.

void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)

std::pair< BasicBlock *, BasicBlock * > Edge

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

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)

Import globals referenced by a function or other globals that are being imported, if importing such g...

Definition FunctionImport.cpp:394

void onImportingSummary(const GlobalValueSummary &Summary)

Definition FunctionImport.cpp:491

GlobalsImporter(const ModuleSummaryIndex &Index, const GVSummaryMapTy &DefinedGVSummaries, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> IsPrevailing, FunctionImporter::ImportMapTy &ImportList, DenseMap< StringRef, FunctionImporter::ExportSetTy > *ExportLists)

Definition FunctionImport.cpp:481

virtual bool canImport(ValueInfo VI)

Definition FunctionImport.cpp:522

DenseMap< StringRef, FunctionImporter::ExportSetTy > *const ExportLists

Definition FunctionImport.cpp:514

virtual ~ModuleImportsManager()=default

static std::unique_ptr< ModuleImportsManager > create(function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> IsPrevailing, const ModuleSummaryIndex &Index, DenseMap< StringRef, FunctionImporter::ExportSetTy > *ExportLists=nullptr)

Definition FunctionImport.cpp:831

function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> IsPrevailing

Definition FunctionImport.cpp:512

ModuleImportsManager(function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> IsPrevailing, const ModuleSummaryIndex &Index, DenseMap< StringRef, FunctionImporter::ExportSetTy > *ExportLists=nullptr)

Definition FunctionImport.cpp:516

const ModuleSummaryIndex & Index

Definition FunctionImport.cpp:513

virtual void computeImportForModule(const GVSummaryMapTy &DefinedGVSummaries, StringRef ModName, FunctionImporter::ImportMapTy &ImportList)

Given the list of globals defined in a module, compute the list of imports as well as the list of "ex...

Definition FunctionImport.cpp:1062

WorkloadImportsManager(function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> IsPrevailing, const ModuleSummaryIndex &Index, DenseMap< StringRef, FunctionImporter::ExportSetTy > *ExportLists)

Definition FunctionImport.cpp:803

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

ValueT & at(const_arg_type_t< KeyT > Val)

at - Return the entry for the specified key, or abort if no such entry exists.

ValueT lookup(const_arg_type_t< KeyT > Val) const

lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...

iterator find(const_arg_type_t< KeyT > Val)

size_type count(const_arg_type_t< KeyT > Val) const

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

Implements a dense probed hash-table based set.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)

Definition FunctionImport.cpp:2126

The map maintains the list of imports.

LLVM_ABI AddDefinitionStatus addDefinition(StringRef FromModule, GlobalValue::GUID GUID)

Definition FunctionImport.cpp:347

void addGUID(StringRef FromModule, GlobalValue::GUID GUID, GlobalValueSummary::ImportKind ImportKind)

LLVM_ABI SmallVector< StringRef, 0 > getSourceModules() const

Definition FunctionImport.cpp:370

LLVM_ABI std::optional< GlobalValueSummary::ImportKind > getImportType(StringRef FromModule, GlobalValue::GUID GUID) const

Definition FunctionImport.cpp:380

LLVM_ABI void maybeAddDeclaration(StringRef FromModule, GlobalValue::GUID GUID)

Definition FunctionImport.cpp:360

The function importer is automatically importing function from other modules based on the provided su...

LLVM_ABI Expected< bool > importFunctions(Module &M, const ImportMapTy &ImportList)

Import functions in Module M based on the supplied import list.

Definition FunctionImport.cpp:1873

DenseMap< GlobalValue::GUID, std::tuple< unsigned, const GlobalValueSummary *, std::unique_ptr< ImportFailureInfo > > > ImportThresholdsTy

Map of callee GUID considered for import into a given module to a pair consisting of the largest thre...

ImportFailureReason

The different reasons selectCallee will chose not to import a candidate.

@ LocalLinkageNotInModule

DenseSet< ValueInfo > ExportSetTy

The set contains an entry for every global value that the module exports.

Function summary information to aid decisions and implementation of importing.

unsigned instCount() const

Get the instruction count recorded for this function.

FFlags fflags() const

Get function summary flags.

static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)

LLVM_ABI const GlobalObject * getAliaseeObject() const

Function and variable summary information to aid decisions and implementation of importing.

StringRef modulePath() const

Get the path to the module containing this function.

GlobalValue::LinkageTypes linkage() const

Return linkage type recorded for this global value.

static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)

Return a 64-bit global unique ID constructed from the name of a global symbol.

VisibilityTypes getVisibility() const

bool isImplicitDSOLocal() const

static bool isLocalLinkage(LinkageTypes Linkage)

LLVM_ABI bool isDeclaration() const

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

LinkageTypes getLinkage() const

uint64_t GUID

Declare a type to represent a global unique identifier for a global value.

ThreadLocalMode getThreadLocalMode() const

static bool isAvailableExternallyLinkage(LinkageTypes Linkage)

void setLinkage(LinkageTypes LT)

unsigned getAddressSpace() const

GUID getGUID() const

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

Module * getParent()

Get the module that this global value is contained inside of...

LLVM_ABI const GlobalObject * getAliaseeObject() const

void setDSOLocal(bool Local)

PointerType * getType() const

Global values are always pointers.

@ DefaultVisibility

The GV is visible.

@ HiddenVisibility

The GV is hidden.

static LLVM_ABI std::string getGlobalIdentifier(StringRef Name, GlobalValue::LinkageTypes Linkage, StringRef FileName)

Return the modified name for a global value suitable to be used as the key for a global lookup (e....

void setVisibility(VisibilityTypes V)

static bool isInterposableLinkage(LinkageTypes Linkage)

Whether the definition of this global may be replaced by something non-equivalent at link time.

LLVM_ABI Error materialize()

Make sure this GlobalValue is fully read.

LLVM_ABI bool canBeOmittedFromSymbolTable() const

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

@ InternalLinkage

Rename collisions when linking (static functions).

@ WeakODRLinkage

Same, but only replaced by something equivalent.

@ ExternalLinkage

Externally visible function.

@ AvailableExternallyLinkage

Available for inspection, not emission.

@ LinkOnceODRLinkage

Same, but only replaced by something equivalent.

Type * getValueType() const

LLVM_ABI Error move(std::unique_ptr< Module > Src, ArrayRef< GlobalValue * > ValuesToLink, LazyCallback AddLazyFor, bool IsPerformingImport)

Move in the provide values in ValuesToLink from Src.

This is an important class for using LLVM in a threaded context.

static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)

static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)

Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".

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

static StringRef getOriginalNameBeforePromote(StringRef Name)

Helper to obtain the unpromoted name for a global value (or the original name if not promoted).

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

LLVMContext & getContext() const

Get the global data context.

const std::string & getSourceFileName() const

Get the module's original source file name.

iterator_range< alias_iterator > aliases()

iterator_range< global_iterator > globals()

const std::string & getModuleIdentifier() const

Get the module identifier which is, essentially, the name of the module.

iterator_range< global_object_iterator > global_objects()

LLVM_ABI Expected< PGOCtxProfile > loadProfiles()

unsigned getAddressSpace() const

Return the address space of the Pointer type.

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.

Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...

A vector that has set insertion semantics.

ArrayRef< value_type > getArrayRef() const

size_type size() const

Determine the number of elements in the SetVector.

Vector takeVector()

Clear the SetVector and return the underlying vector.

bool contains(const_arg_type key) const

Check if the SetVector contains the given key.

void clear()

Completely clear the SetVector.

bool insert(const value_type &X)

Insert a new element into the SetVector.

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

reference emplace_back(ArgTypes &&... Args)

void reserve(size_type N)

void push_back(const T &Elt)

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

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

iterator find(StringRef Key)

size_type count(StringRef Key) const

count - Return 1 if the element is in the map, 0 otherwise.

bool insert(MapEntryTy *KeyValue)

insert - Insert the specified key/value pair into the map.

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

constexpr size_t size() const

size - Get the string size.

char front() const

front - Get the first character in the string.

size_t find(char C, size_t From=0) const

Search for the first character C in the string.

StringSet - A wrapper for StringMap that provides set-like functionality.

std::pair< typename Base::iterator, bool > insert(StringRef key)

The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.

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.

bool isFunctionTy() const

True if this is an instance of FunctionType.

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.

LLVM_ABI void takeName(Value *V)

Transfer the name from V to this value.

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

void insert_range(Range &&R)

bool contains(const_arg_type_t< ValueT > V) const

Check if the set contains the given element.

bool erase(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.

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

The root is the trivial Path to the root value.

A raw_ostream that writes to a file descriptor.

#define llvm_unreachable(msg)

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

@ C

The default llvm calling convention, compatible with C.

initializer< Ty > init(const Ty &Val)

LLVM_ABI llvm::Expected< Value > parse(llvm::StringRef JSON)

Parses the provided JSON source, or returns a ParseError.

bool fromJSON(const Value &E, std::string &Out, Path P)

@ OF_Text

The file should be opened in text mode on platforms like z/OS that make this distinction.

LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get filename.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})

Log all errors (if any) in E to OS.

static cl::opt< float > ImportHotMultiplier("import-hot-multiplier", cl::init(10.0), cl::Hidden, cl::value_desc("x"), cl::desc("Multiply the `import-instr-limit` threshold for hot callsites"))

static cl::opt< bool > CtxprofMoveRootsToOwnModule("thinlto-move-ctxprof-trees", cl::desc("Move contextual profiling roots and the graphs under them in " "their own module."), cl::Hidden, cl::init(false))

Error createFileError(const Twine &F, Error E)

Concatenate a source file path and/or name with an Error.

std::unordered_set< GlobalValueSummary * > GVSummaryPtrSet

A set of global value summary pointers.

bool internalizeModule(Module &TheModule, std::function< bool(const GlobalValue &)> MustPreserveGV)

Helper function to internalize functions and variables in a Module.

static cl::opt< float > ImportColdMultiplier("import-cold-multiplier", cl::init(0), cl::Hidden, cl::value_desc("N"), cl::desc("Multiply the `import-instr-limit` threshold for cold callsites"))

std::error_code make_error_code(BitcodeError E)

cl::list< GlobalValue::GUID > MoveSymbolGUID

const char * getHotnessName(CalleeInfo::HotnessType HT)

decltype(auto) dyn_cast(const From &Val)

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

static cl::opt< std::string > WorkloadDefinitions("thinlto-workload-def", cl::desc("Pass a workload definition. This is a file containing a JSON " "dictionary. The keys are root functions, the values are lists of " "functions to import in the module defining the root. It is " "assumed -funique-internal-linkage-names was used, to ensure " "local linkage functions have unique names. For example: \n" "{\n" " \"rootFunction_1\": [\"function_to_import_1\", " "\"function_to_import_2\"], \n" " \"rootFunction_2\": [\"function_to_import_3\", " "\"function_to_import_4\"] \n" "}"), cl::Hidden)

Pass a workload description file - an example of workload would be the functions executed to satisfy ...

DenseMap< GlobalValue::GUID, GlobalValueSummary * > GVSummaryMapTy

Map of global value GUID to its summary, used to identify values defined in a particular module,...

cl::opt< std::string > UseCtxProfile("use-ctx-profile", cl::init(""), cl::Hidden, cl::desc("Use the specified contextual profile file"))

static cl::opt< bool > PrintImportFailures("print-import-failures", cl::init(false), cl::Hidden, cl::desc("Print information for functions rejected for importing"))

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

LLVM_ABI bool convertToDeclaration(GlobalValue &GV)

Converts value GV to declaration, or replaces with a declaration if it is an alias.

Definition FunctionImport.cpp:1631

static cl::opt< unsigned > ImportInstrLimit("import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"), cl::desc("Only import functions with less than N instructions"))

Limit on instruction count of imported functions.

LLVM_ABI void renameModuleForThinLTO(Module &M, const ModuleSummaryIndex &Index, bool ClearDSOLocalOnDeclarations, SetVector< GlobalValue * > *GlobalsToImport=nullptr)

Perform in-place global value handling on the given Module for exported local functions renamed and p...

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

static cl::opt< float > ImportHotInstrFactor("import-hot-evolution-factor", cl::init(1.0), cl::Hidden, cl::value_desc("x"), cl::desc("As we import functions called from hot callsite, multiply the " "`import-instr-limit` threshold by this factor " "before processing newly imported functions"))

static cl::opt< bool > PrintImports("print-imports", cl::init(false), cl::Hidden, cl::desc("Print imported functions"))

auto map_range(ContainerTy &&C, FuncTy F)

LLVM_ABI void ComputeCrossModuleImport(const ModuleSummaryIndex &Index, const DenseMap< StringRef, GVSummaryMapTy > &ModuleToDefinedGVSummaries, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing, FunctionImporter::ImportListsTy &ImportLists, DenseMap< StringRef, FunctionImporter::ExportSetTy > &ExportLists)

Compute all the imports and exports for every module in the Index.

Definition FunctionImport.cpp:1218

auto dyn_cast_or_null(const Y &Val)

static cl::opt< float > ImportInstrFactor("import-instr-evolution-factor", cl::init(0.7), cl::Hidden, cl::value_desc("x"), cl::desc("As we import functions, multiply the " "`import-instr-limit` threshold by this factor " "before processing newly imported functions"))

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 sort(IteratorTy Start, IteratorTy End)

LLVM_ABI void computeDeadSymbolsAndUpdateIndirectCalls(ModuleSummaryIndex &Index, const DenseSet< GlobalValue::GUID > &GUIDPreservedSymbols, function_ref< PrevailingType(GlobalValue::GUID)> isPrevailing)

Compute all the symbols that are "dead": i.e these that can't be reached in the graph from any of the...

Definition FunctionImport.cpp:1433

LLVM_ABI raw_ostream & dbgs()

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

auto make_first_range(ContainerTy &&c)

Given a container of pairs, return a range over the first elements.

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

std::map< std::string, GVSummaryMapTy, std::less<> > ModuleToSummariesForIndexTy

Map of a module name to the GUIDs and summaries we will import from that module.

bool hasSingleElement(ContainerTy &&C)

Returns true if the given container only contains a single element.

iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)

Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...

static cl::opt< bool > ImportAllIndex("import-all-index", cl::desc("Import all external functions in index."))

Used when testing importing from distributed indexes via opt.

static cl::opt< int > ImportCutoff("import-cutoff", cl::init(-1), cl::Hidden, cl::value_desc("N"), cl::desc("Only import first N functions if N>=0 (default -1)"))

static cl::opt< bool > ImportDeclaration("import-declaration", cl::init(false), cl::Hidden, cl::desc("If true, import function declaration as fallback if the function " "definition is not imported."))

This is a test-only option.

bool isa(const From &Val)

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

LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

LLVM_ABI void updateIndirectCalls(ModuleSummaryIndex &Index)

Update call edges for indirect calls to local functions added from SamplePGO when needed.

Definition FunctionImport.cpp:1424

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

@ Ref

The access may reference the value stored in memory.

cl::opt< bool > EnableMemProfContextDisambiguation

Enable MemProf context disambiguation for thin link.

LLVM_ABI std::unique_ptr< Module > getLazyIRFileModule(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, bool ShouldLazyLoadMetadata=false)

If the given file holds a bitcode image, return a Module for it which does lazy deserialization of fu...

LLVM_ABI void thinLTOInternalizeModule(Module &TheModule, const GVSummaryMapTy &DefinedGlobals)

Internalize TheModule based on the information recorded in the summaries during global summary-based ...

Definition FunctionImport.cpp:1795

cl::opt< bool > ForceImportAll

LLVM_ABI void gatherImportedSummariesForModule(StringRef ModulePath, const DenseMap< StringRef, GVSummaryMapTy > &ModuleToDefinedGVSummaries, const FunctionImporter::ImportMapTy &ImportList, ModuleToSummariesForIndexTy &ModuleToSummariesForIndex, GVSummaryPtrSet &DecSummaries)

Compute the set of summaries needed for a ThinLTO backend compilation of ModulePath.

Definition FunctionImport.cpp:1563

static cl::opt< std::string > SummaryFile("summary-file", cl::desc("The summary file to use for function importing."))

Summary file to use for function importing when using -function-import from the command line.

std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)

ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy

LLVM_ABI void processImportsFiles(StringRef ModulePath, const ModuleToSummariesForIndexTy &ModuleToSummariesForIndex, function_ref< void(const std::string &)> F)

Call F passing each of the files module ModulePath will import from.

Definition FunctionImport.cpp:1619

static cl::opt< float > ImportCriticalMultiplier("import-critical-multiplier", cl::init(100.0), cl::Hidden, cl::value_desc("x"), cl::desc("Multiply the `import-instr-limit` threshold for critical callsites"))

decltype(auto) cast(const From &Val)

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

PrevailingType

PrevailingType enum used as a return type of callback passed to computeDeadSymbolsAndUpdateIndirectCa...

LLVM_ABI Error errorCodeToError(std::error_code EC)

Helper for converting an std::error_code to a Error.

LLVM_ABI bool UpgradeDebugInfo(Module &M)

Check the debug info version number, if it is out-dated, drop the debug info.

static cl::opt< bool > EnableImportMetadata("enable-import-metadata", cl::init(false), cl::Hidden, cl::desc("Enable import metadata like 'thinlto_src_module' and " "'thinlto_src_file'"))

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.

LLVM_ABI void computeDeadSymbolsWithConstProp(ModuleSummaryIndex &Index, const DenseSet< GlobalValue::GUID > &GUIDPreservedSymbols, function_ref< PrevailingType(GlobalValue::GUID)> isPrevailing, bool ImportEnabled)

Compute dead symbols and run constant propagation in combined index after that.

Definition FunctionImport.cpp:1549

LLVM_ABI Error EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename, const ModuleToSummariesForIndexTy &ModuleToSummariesForIndex)

Emit into OutputFilename the files module ModulePath will import from.

Definition FunctionImport.cpp:1604

static cl::opt< bool > ComputeDead("compute-dead", cl::init(true), cl::Hidden, cl::desc("Compute dead symbols"))

LLVM_ABI Expected< std::unique_ptr< ModuleSummaryIndex > > getModuleSummaryIndexForFile(StringRef Path, bool IgnoreEmptyThinLTOIndexFile=false)

Parse the module summary index out of an IR file and return the module summary index object if found,...

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.

LLVM_ABI void thinLTOFinalizeInModule(Module &TheModule, const GVSummaryMapTy &DefinedGlobals, bool PropagateAttrs)

Based on the information recorded in the summaries during global summary-based analysis:

Definition FunctionImport.cpp:1666

unsigned DefinedFS

Definition FunctionImport.cpp:1158

unsigned Count

Definition FunctionImport.cpp:1159

unsigned NumGVS

Definition FunctionImport.cpp:1157

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