LLVM: lib/IR/ModuleSummaryIndex.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

20using namespace llvm;

21

22#define DEBUG_TYPE "module-summary-index"

23

25 "Number of live global variables marked read only");

27 "Number of live global variables marked write only");

28

31 cl::desc("Propagate attributes in index"));

32

35 cl::desc("Import constant global variables with references"));

36

40

42 bool HasProtected = false;

47 HasProtected = true;

48 }

51}

52

54

55

56 return WithDSOLocalPropagation

61 [](const std::unique_ptr &Summary) {

62 return Summary->isDSOLocal();

63 });

64}

65

67

70 [](const std::unique_ptr &Summary) {

71 return Summary->canAutoHide();

72 });

73}

74

75

77

78

79 auto Refs = refs();

80 unsigned RORefCnt = 0, WORefCnt = 0;

81 int I;

82 for (I = Refs.size() - 1; I >= 0 && Refs[I].isWriteOnly(); --I)

83 WORefCnt++;

84 for (; I >= 0 && Refs[I].isReadOnly(); --I)

85 RORefCnt++;

86 return {RORefCnt, WORefCnt};

87}

88

91

93 Flags |= 0x1;

95 Flags |= 0x2;

97 Flags |= 0x8;

99 Flags |= 0x10;

101 Flags |= 0x20;

103 Flags |= 0x40;

105 Flags |= 0x80;

107 Flags |= 0x100;

109 Flags |= 0x200;

111 Flags |= 0x400;

112 return Flags;

113}

114

116 assert(Flags <= 0x7ff && "Unexpected bits in flag");

117

118

119 if (Flags & 0x1)

121

122

123 if (Flags & 0x2)

125

126

127

128

129 if (Flags & 0x8)

131

132

133 if (Flags & 0x10)

135

136

137 if (Flags & 0x20)

139

140

141 if (Flags & 0x40)

143

144

145 if (Flags & 0x80)

147

148

149 if (Flags & 0x100)

151

152

153 if (Flags & 0x200)

155

156

157 if (Flags & 0x400)

159}

160

161

162

165 for (auto &GlobalList : *this) {

166 auto GUID = GlobalList.first;

167 for (auto &GlobSummary : GlobalList.second.getSummaryList()) {

169 if (!Summary)

170

171 continue;

172

173 if (Summary->modulePath() != ModulePath)

174 continue;

175 GVSummaryMap[GUID] = Summary;

176 }

177 }

178}

179

182 bool PerModuleIndex) const {

184 assert(VI && "GlobalValue not found in index");

185 assert((!PerModuleIndex || VI.getSummaryList().size() == 1) &&

186 "Expected a single entry per global value in per-module index");

187 auto &Summary = VI.getSummaryList()[0];

188 return Summary.get();

189}

190

193 if (!VI)

194 return true;

195 const auto &SummaryList = VI.getSummaryList();

196 if (SummaryList.empty())

197 return true;

198 for (auto &I : SummaryList)

200 return true;

201 return false;

202}

203

204static void

207

208

209

210

211

212

213

214

215 for (auto &VI : S->refs()) {

217 if (!VI.getAccessSpecifier()) {

218 if (!MarkedNonReadWriteOnly.insert(VI).second)

219 continue;

220 } else if (MarkedNonReadWriteOnly.contains(VI))

221 continue;

222 for (auto &Ref : VI.getSummaryList())

223

224

226 if (!VI.isReadOnly())

227 GVS->setReadOnly(false);

228 if (!VI.isWriteOnly())

229 GVS->setWriteOnly(false);

230 }

231 }

232}

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

264 return;

266 for (auto &P : *this) {

267 bool IsDSOLocal = true;

268 for (auto &S : P.second.getSummaryList()) {

270

271

272

273

274

275

276

278 P.second.getSummaryList(),

279 [&](const std::unique_ptr &Summary) {

280 return isGlobalValueLive(Summary.get());

281 }));

282

283 break;

284 }

285

286

287

288

289

290

291

292

293

294

296

297

298

300 GUIDPreservedSymbols.count(P.first)) {

301 GVS->setReadOnly(false);

302 GVS->setWriteOnly(false);

303 }

305

306

307 IsDSOLocal &= S->isDSOLocal();

308 }

309 if (!IsDSOLocal)

310

311

312 for (const std::unique_ptr &Summary :

313 P.second.getSummaryList())

314 Summary->setDSOLocal(false);

315 }

319 for (auto &P : *this)

320 if (P.second.getSummaryList().size())

322 P.second.getSummaryList()[0]->getBaseObject()))

324 if (GVS->maybeReadOnly())

325 ReadOnlyLiveGVars++;

326 if (GVS->maybeWriteOnly())

327 WriteOnlyLiveGVars++;

328 }

329}

330

332 bool AnalyzeRefs) const {

333 bool CanImportDecl;

335}

336

338 bool AnalyzeRefs,

339 bool &CanImportDecl) const {

340 auto HasRefsPreventingImport = [this](const GlobalVarSummary *GVS) {

341

342

343

344

345

346

347

348

349

350

351

352

353

354

357 };

359

360 const bool nonInterposable =

363

364

365

366 CanImportDecl = (nonInterposable && eligibleToImport);

367

368

369

370

371

372

373 return nonInterposable && eligibleToImport &&

374 (!AnalyzeRefs || !HasRefsPreventingImport(GVS));

375}

376

377

378

383 I.isAtEnd(); ++I) {

384 O << "SCC (" << utostr(I->size()) << " node" << (I->size() == 1 ? "" : "s")

385 << ") {\n";

388 if (V.getSummaryList().size())

390 O << " " << (F == nullptr ? "External" : "") << " " << utostr(V.getGUID())

391 << (I.hasCycle() ? " (has cycle)" : "") << "\n";

392 }

393 O << "}\n";

394 }

395}

396

397namespace {

398struct Attributes {

401 void addComment(const Twine &Comment);

402 std::string getAsString() const;

403

404 std::vectorstd::string Attrs;

405 std::string Comments;

406};

407

408struct Edge {

410 int Hotness;

413};

414}

415

416void Attributes::add(const Twine &Name, const Twine &Value,

417 const Twine &Comment) {

418 std::string A = Name.str();

419 A += "=\"";

421 A += "\"";

423 addComment(Comment);

424}

425

426void Attributes::addComment(const Twine &Comment) {

427 if (Comment.isTriviallyEmpty()) {

428 if (Comments.empty())

429 Comments = " // ";

430 else

431 Comments += ", ";

432 Comments += Comment.str();

433 }

434}

435

436std::string Attributes::getAsString() const {

437 if (Attrs.empty())

438 return "";

439

440 std::string Ret = "[";

441 for (auto &A : Attrs)

442 Ret += A + ",";

443 Ret.pop_back();

444 Ret += "];";

445 Ret += Comments;

446 return Ret;

447}

448

450 switch (LT) {

452 return "extern";

454 return "av_ext";

456 return "linkonce";

458 return "linkonce_odr";

460 return "weak";

462 return "weak_odr";

464 return "appending";

466 return "internal";

468 return "private";

470 return "extern_weak";

472 return "common";

473 }

474

475 return "";

476}

477

479 auto FlagValue = [](unsigned V) { return V ? '1' : '0'; };

480 char FlagRep[] = {FlagValue(F.ReadNone),

481 FlagValue(F.ReadOnly),

482 FlagValue(F.NoRecurse),

483 FlagValue(F.ReturnDoesNotAlias),

484 FlagValue(F.NoInline),

485 FlagValue(F.AlwaysInline),

486 FlagValue(F.NoUnwind),

487 FlagValue(F.MayThrow),

488 FlagValue(F.HasUnknownCall),

489 FlagValue(F.MustBeUnreachable),

490 0};

491

492 return FlagRep;

493}

494

495

498 if (!FS)

499 return "";

500

501 return std::string("inst: ") + std::to_string(FS->instCount()) +

503}

504

506 return std::string("@") + std::to_string(Id);

507}

508

510 return VI.name().empty() ? getNodeVisualName(VI.getGUID()) : VI.name().str();

511}

512

516

518 std::string Label =

520 if (!Attrs.empty())

521 Label += std::string(" (") + Attrs + ")";

522 Label += "}";

523

524 return Label;

525}

526

527

528

529

532 auto StrId = std::to_string(Id);

533 OS << " " << StrId << " [label=\"";

534

535 if (VI) {

537 } else {

539 }

540 OS << "\"]; // defined externally\n";

541}

542

545 return GVS->maybeReadOnly();

546 return false;

547}

548

551 return GVS->maybeWriteOnly();

552 return false;

553}

554

557 return GVS->isConstant();

558 return false;

559}

560

564 std::vector CrossModuleEdges;

566 using GVSOrderedMapTy = std::map<GlobalValue::GUID, GlobalValueSummary *>;

567 std::map<StringRef, GVSOrderedMapTy> ModuleToDefinedGVS;

569

570

571

572

573 std::vector ModulePaths;

575 ModulePaths.push_back(ModPath);

578 for (auto &ModPath : ModulePaths)

580

581

582

584 return ModId == (uint64_t)-1 ? std::to_string(Id)

585 : std::string("M") + std::to_string(ModId) +

586 "_" + std::to_string(Id);

587 };

588

591 int TypeOrHotness) {

592

593

594

595

596

597 TypeOrHotness += 4;

598 static const char *EdgeAttrs[] = {

599 " [style=dotted]; // alias",

600 " [style=dashed]; // ref",

601 " [style=dashed,color=forestgreen]; // const-ref",

602 " [style=dashed,color=violetred]; // writeOnly-ref",

603 " // call (hotness : Unknown)",

604 " [color=blue]; // call (hotness : Cold)",

605 " // call (hotness : None)",

606 " [color=brown]; // call (hotness : Hot)",

607 " [style=bold,color=red]; // call (hotness : Critical)"};

608

609 assert(static_cast<size_t>(TypeOrHotness) < std::size(EdgeAttrs));

610 OS << Pfx << NodeId(SrcMod, SrcId) << " -> " << NodeId(DstMod, DstId)

611 << EdgeAttrs[TypeOrHotness] << "\n";

612 };

613

614 OS << "digraph Summary {\n";

615 for (auto &ModIt : ModuleToDefinedGVS) {

616

617

618 assert(ModuleIdMap.count(ModIt.first) || ModuleIdMap.empty());

619 auto ModId = ModuleIdMap.empty() ? 0 : ModuleIdMap[ModIt.first];

620 OS << " // Module: " << ModIt.first << "\n";

621 OS << " subgraph cluster_" << std::to_string(ModId) << " {\n";

622 OS << " style = filled;\n";

623 OS << " color = lightgrey;\n";

625 OS << " node [style=filled,fillcolor=lightblue];\n";

626

627 auto &GVSMap = ModIt.second;

629 if (!GVSMap.count(IdTo)) {

630 CrossModuleEdges.push_back({ModId, Hotness, IdFrom, IdTo});

631 return;

632 }

633 DrawEdge(" ", ModId, IdFrom, ModId, IdTo, Hotness);

634 };

635

636 for (auto &SummaryIt : GVSMap) {

637 NodeMap[SummaryIt.first].push_back(ModId);

638 auto Flags = SummaryIt.second->flags();

639 Attributes A;

641 A.add("shape", "record", "function");

643 A.add("style", "dotted,filled", "alias");

644 A.add("shape", "box");

645 } else {

646 A.add("shape", "Mrecord", "variable");

648 A.addComment("immutable");

650 A.addComment("writeOnly");

652 A.addComment("constant");

653 }

654 if (Flags.Visibility)

655 A.addComment("visibility");

656 if (Flags.DSOLocal)

657 A.addComment("dsoLocal");

658 if (Flags.CanAutoHide)

659 A.addComment("canAutoHide");

661 A.addComment("definition");

663 A.addComment("declaration");

664 if (GUIDPreservedSymbols.count(SummaryIt.first))

665 A.addComment("preserved");

666

668 A.add("label", getNodeLabel(VI, SummaryIt.second));

669 if (!Flags.Live)

670 A.add("fillcolor", "red", "dead");

671 else if (Flags.NotEligibleToImport)

672 A.add("fillcolor", "yellow", "not eligible to import");

673

674 OS << " " << NodeId(ModId, SummaryIt.first) << " " << A.getAsString()

675 << "\n";

676 }

677 OS << " // Edges:\n";

678

679 for (auto &SummaryIt : GVSMap) {

680 auto *GVS = SummaryIt.second;

681 for (auto &R : GVS->refs())

682 Draw(SummaryIt.first, R.getGUID(),

683 R.isWriteOnly() ? -1 : (R.isReadOnly() ? -2 : -3));

684

686 Draw(SummaryIt.first, AS->getAliaseeGUID(), -4);

687 continue;

688 }

689

691 for (auto &CGEdge : FS->calls())

692 Draw(SummaryIt.first, CGEdge.first.getGUID(),

693 static_cast<int>(CGEdge.second.Hotness));

694 }

695 OS << " }\n";

696 }

697

698 OS << " // Cross-module edges:\n";

699 for (auto &E : CrossModuleEdges) {

700 auto &ModList = NodeMap[E.Dst];

701 if (ModList.empty()) {

703

704

705 ModList.push_back(-1);

706 }

707 for (auto DstMod : ModList)

708

709

710

711

712

713 if (DstMod != E.SrcMod)

714 DrawEdge(" ", E.SrcMod, E.Src, DstMod, E.Dst, E.Hotness);

715 }

716

717 OS << "}";

718}

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

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

#define LLVM_DUMP_METHOD

Mark debug helper function definitions like dump() that should not be stripped from debug builds.

static std::string getNodeVisualName(GlobalValue::GUID Id)

Definition ModuleSummaryIndex.cpp:505

static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)

Definition ModuleSummaryIndex.cpp:513

static std::string getSummaryAttributes(GlobalValueSummary *GVS)

Definition ModuleSummaryIndex.cpp:496

static cl::opt< bool > ImportConstantsWithRefs("import-constants-with-refs", cl::init(true), cl::Hidden, cl::desc("Import constant global variables with references"))

static std::string fflagsToString(FunctionSummary::FFlags F)

Definition ModuleSummaryIndex.cpp:478

static bool hasWriteOnlyFlag(const GlobalValueSummary *S)

Definition ModuleSummaryIndex.cpp:549

static void propagateAttributesToRefs(GlobalValueSummary *S, DenseSet< ValueInfo > &MarkedNonReadWriteOnly)

Definition ModuleSummaryIndex.cpp:205

static std::string linkageToString(GlobalValue::LinkageTypes LT)

Definition ModuleSummaryIndex.cpp:449

static void defineExternalNode(raw_ostream &OS, const char *Pfx, const ValueInfo &VI, GlobalValue::GUID Id)

Definition ModuleSummaryIndex.cpp:530

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

static bool hasReadOnlyFlag(const GlobalValueSummary *S)

Definition ModuleSummaryIndex.cpp:543

static bool hasConstantFlag(const GlobalValueSummary *S)

Definition ModuleSummaryIndex.cpp:555

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

This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...

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

#define STATISTIC(VARNAME, DESC)

std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)

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.

Function summary information to aid decisions and implementation of importing.

static LLVM_ABI FunctionSummary ExternalNode

A dummy node to reference external functions that aren't in the index.

static FunctionSummary makeDummyFunctionSummary(SmallVectorImpl< FunctionSummary::EdgeTy > &&Edges)

Create an empty FunctionSummary (with specified call edges).

LLVM_ABI std::pair< unsigned, unsigned > specialRefCounts() const

Definition ModuleSummaryIndex.cpp:76

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

GlobalValueSummary * getBaseObject()

If this is an alias summary, returns the summary of the aliased object (a global variable or function...

ArrayRef< ValueInfo > refs() const

Return the list of values referenced by this global value definition.

GlobalValue::LinkageTypes linkage() const

Return linkage type recorded for this global value.

bool notEligibleToImport() const

Return true if this global value can't be imported.

uint64_t GUID

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

VisibilityTypes

An enumeration for the kinds of visibility of global values.

@ DefaultVisibility

The GV is visible.

@ HiddenVisibility

The GV is hidden.

@ ProtectedVisibility

The GV is protected.

static bool isInterposableLinkage(LinkageTypes Linkage)

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

LinkageTypes

An enumeration for the kinds of linkage for global values.

@ PrivateLinkage

Like Internal, but omit from symbol table.

@ CommonLinkage

Tentative definitions.

@ InternalLinkage

Rename collisions when linking (static functions).

@ LinkOnceAnyLinkage

Keep one copy of function when linking (inline)

@ WeakODRLinkage

Same, but only replaced by something equivalent.

@ ExternalLinkage

Externally visible function.

@ WeakAnyLinkage

Keep one copy of named function when linking (weak)

@ AppendingLinkage

Special purpose, only applies to global arrays.

@ AvailableExternallyLinkage

Available for inspection, not emission.

@ ExternalWeakLinkage

ExternalWeak linkage description.

@ LinkOnceODRLinkage

Same, but only replaced by something equivalent.

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

bool withAttributePropagation() const

bool withInternalizeAndPromote() const

bool withGlobalValueDeadStripping() const

bool withWholeProgramVisibility() const

LLVM_ABI bool isGUIDLive(GlobalValue::GUID GUID) const

Definition ModuleSummaryIndex.cpp:191

bool isReadOnly(const GlobalVarSummary *GVS) const

LLVM_ABI void setFlags(uint64_t Flags)

Definition ModuleSummaryIndex.cpp:115

bool isWriteOnly(const GlobalVarSummary *GVS) const

void setPartiallySplitLTOUnits()

ValueInfo getValueInfo(const GlobalValueSummaryMapTy::value_type &R) const

Return a ValueInfo for the index value_type (convenient when iterating index).

void setEnableSplitLTOUnit()

bool partiallySplitLTOUnits() const

LLVM_ABI void collectDefinedFunctionsForModule(StringRef ModulePath, GVSummaryMapTy &GVSummaryMap) const

Collect for the given module the list of functions it defines (GUID -> Summary).

Definition ModuleSummaryIndex.cpp:163

LLVM_ABI void dumpSCCs(raw_ostream &OS)

Print out strongly connected components for debugging.

Definition ModuleSummaryIndex.cpp:380

bool isGlobalValueLive(const GlobalValueSummary *GVS) const

bool enableSplitLTOUnit() const

void setWithSupportsHotColdNew()

LLVM_ABI void propagateAttributes(const DenseSet< GlobalValue::GUID > &PreservedSymbols)

Do the access attribute and DSOLocal propagation in combined index.

Definition ModuleSummaryIndex.cpp:261

void setSkipModuleByDistributedBackend()

void setWithAttributePropagation()

const StringMap< ModuleHash > & modulePaths() const

Table of modules, containing module hash and id.

bool withSupportsHotColdNew() const

void collectDefinedGVSummariesPerModule(Map &ModuleToDefinedGVSummaries) const

Collect for each module the list of Summaries it defines (GUID -> Summary).

bool withDSOLocalPropagation() const

LLVM_ABI void exportToDot(raw_ostream &OS, const DenseSet< GlobalValue::GUID > &GUIDPreservedSymbols) const

Export summary to dot file for GraphViz.

Definition ModuleSummaryIndex.cpp:561

bool hasUnifiedLTO() const

void setWithDSOLocalPropagation()

void setWithInternalizeAndPromote()

bool skipModuleByDistributedBackend() const

LLVM_ABI uint64_t getFlags() const

Definition ModuleSummaryIndex.cpp:89

GlobalValueSummary * getGlobalValueSummary(const GlobalValue &GV, bool PerModuleIndex=true) const

Returns the first GlobalValueSummary for GV, asserting that there is only one if PerModuleIndex.

void setWithGlobalValueDeadStripping()

void setWithWholeProgramVisibility()

LLVM_ABI bool canImportGlobalVar(const GlobalValueSummary *S, bool AnalyzeRefs) const

Checks if we can import global variable from another module.

Definition ModuleSummaryIndex.cpp:331

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

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

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

LLVM Value Representation.

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

bool contains(const_arg_type_t< ValueT > V) const

Check if the set contains the given element.

size_type count(const_arg_type_t< ValueT > V) const

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

This class implements an extremely fast bulk output stream that can only output to a stream.

Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.

constexpr char Attrs[]

Key for Kernel::Metadata::mAttrs.

initializer< Ty > init(const Ty &Val)

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.

bool all_of(R &&range, UnaryPredicate P)

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

decltype(auto) dyn_cast(const From &Val)

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

DenseMap< GlobalValue::GUID, GlobalValueSummary * > GVSummaryMapTy

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

scc_iterator< T > scc_begin(const T &G)

Construct the begin iterator for a deduced graph type T.

std::string utostr(uint64_t X, bool isNeg=false)

auto dyn_cast_or_null(const Y &Val)

iterator_range< pointee_iterator< WrappedIteratorT > > make_pointee_range(RangeT &&Range)

void sort(IteratorTy Start, IteratorTy End)

bool none_of(R &&Range, UnaryPredicate P)

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

LLVM_ABI bool AreStatisticsEnabled()

Check if statistics are enabled.

bool isa(const From &Val)

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

@ Ref

The access may reference the value stored in memory.

decltype(auto) cast(const From &Val)

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

Flags specific to function summaries.

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

LLVM_ABI GlobalValue::VisibilityTypes getELFVisibility() const

Returns the most constraining visibility among summaries.

Definition ModuleSummaryIndex.cpp:41

ArrayRef< std::unique_ptr< GlobalValueSummary > > getSummaryList() const

LLVM_ABI bool canAutoHide() const

Checks if all copies are eligible for auto-hiding (have flag set).

Definition ModuleSummaryIndex.cpp:66

LLVM_ABI bool isDSOLocal(bool WithDSOLocalPropagation=false) const

Checks if all summaries are DSO local (have the flag set).

Definition ModuleSummaryIndex.cpp:53