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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

17

52#include

53#include

54

55#ifdef EXPENSIVE_CHECKS

57#endif

58

59#include

60#include

61#include

62

63using namespace llvm;

64

65#define DEBUG_TYPE "attributor"

66#define VERBOSE_DEBUG_TYPE DEBUG_TYPE "-verbose"

67

69 "Determine what attributes are manifested in the IR");

70

71STATISTIC(NumFnDeleted, "Number of function deleted");

73 "Number of functions with exact definitions");

75 "Number of functions without exact definitions");

76STATISTIC(NumFnShallowWrappersCreated, "Number of shallow wrappers created");

78 "Number of abstract attributes timed out before fixpoint");

80 "Number of abstract attributes in a valid fixpoint state");

82 "Number of abstract attributes manifested in IR");

83

84

85

86

87

88

89

90

91

94 cl::desc("Maximal number of fixpoint iterations."),

96

100 cl::desc("Maximal number of callees specialized for "

101 "a call base"),

103

105 "attributor-max-initialization-chain-length", cl::Hidden,

107 "Maximal number of chained initializations (to avoid stack overflows)"),

110

112 "attributor-annotate-decl-cs", cl::Hidden,

113 cl::desc("Annotate call sites of function declarations."), cl::init(false));

114

117

120 cl::desc("Allow the Attributor to create shallow "

121 "wrappers for non-exact definitions."),

123

126 cl::desc("Allow the Attributor to use IP information "

127 "derived from non-exact functions via cloning"),

129

130

131#ifndef NDEBUG

134 cl::desc("Comma separated list of attribute names that are "

135 "allowed to be seeded."),

137

139 "attributor-function-seed-allow-list", cl::Hidden,

140 cl::desc("Comma separated list of function names that are "

141 "allowed to be seeded."),

143#endif

144

147 cl::desc("Dump the dependency graph to dot files."),

149

151 "attributor-depgraph-dot-filename-prefix", cl::Hidden,

152 cl::desc("The prefix used for the CallGraph dot file names."));

153

155 cl::desc("View the dependency graph."),

157

159 cl::desc("Print attribute dependencies"),

161

163 "attributor-enable-call-site-specific-deduction", cl::Hidden,

164 cl::desc("Allow the Attributor to do call site specific analysis"),

166

169 cl::desc("Print Attributor's internal call graph"),

171

174 cl::desc("Try to simplify all loads."),

176

178 "attributor-assume-closed-world", cl::Hidden,

179 cl::desc("Should a closed world be assumed, or not. Default if not set."));

180

181

182

183

188 L = L | R;

189 return L;

190}

195 L = L & R;

196 return L;

197}

198

199

201 Triple T(M.getTargetTriple());

202 return T.isGPU();

203}

204

207

209 if (CB->hasFnAttr(Attribute::NoSync))

210 return true;

211

212

213 if (!CB->isConvergent() && !CB->mayReadOrWriteMemory())

214 return true;

215

217 return true;

218

219 bool IsKnownNoSync;

223 }

224

225 if (I.mayReadOrWriteMemory())

226 return true;

227

229}

230

232 const Value &V, bool ForAnalysisOnly) {

233

234 if (!ForAnalysisOnly)

235 return false;

239}

240

248 if (!GV)

249 return nullptr;

250

251 bool UsedAssumedInformation = false;

252 Constant *Initializer = nullptr;

253 if (A.hasGlobalVariableSimplificationCallback(*GV)) {

254 auto AssumedGV = A.getAssumedInitializerFromCallBack(

255 *GV, &QueryingAA, UsedAssumedInformation);

256 Initializer = *AssumedGV;

257 if (!Initializer)

258 return nullptr;

259 } else {

260 if (!GV->hasLocalLinkage()) {

261

262

263 if (!GV->hasDefinitiveInitializer() || !GV->isConstant())

264 return nullptr;

265 }

266

267

268 assert(!GV->hasLocalLinkage() || GV->hasInitializer());

269

270 if (!Initializer)

271 Initializer = GV->getInitializer();

272 }

273

275 int64_t StorageSize = DL.getTypeStoreSize(&Ty);

276 if (StorageSize != RangePtr->Size)

277 return nullptr;

280 }

281

283}

284

287 return true;

289 return I->getFunction() == Scope;

291 return A->getParent() == Scope;

292 return false;

293}

294

298 return true;

299 const Function *Scope = nullptr;

301 if (CtxI)

304 return A->getParent() == Scope;

306 if (I->getFunction() == Scope) {

309 *Scope))

310 return DT->dominates(I, CtxI);

311

312 if (CtxI && I->getParent() == CtxI->getParent())

314 make_range(I->getIterator(), I->getParent()->end()),

315 [&](const Instruction &AfterI) { return &AfterI == CtxI; });

316 }

317 }

318 return false;

319}

320

322 if (V.getType() == &Ty)

323 return &V;

329 if (C->isNullValue() && !Ty.isPtrOrPtrVectorTy())

331 if (C->getType()->isPointerTy() && Ty.isPointerTy())

333 if (C->getType()->getPrimitiveSizeInBits() >= Ty.getPrimitiveSizeInBits()) {

334 if (C->getType()->isIntegerTy() && Ty.isIntegerTy())

336 if (C->getType()->isFloatingPointTy() && Ty.isFloatingPointTy())

338 }

339 }

340 return nullptr;

341}

342

343std::optional<Value *>

345 const std::optional<Value *> &B,

347 if (A == B)

348 return A;

349 if (B)

350 return A;

351 if (*B == nullptr)

352 return nullptr;

353 if (A)

355 if (*A == nullptr)

356 return nullptr;

357 if (!Ty)

358 Ty = (*A)->getType();

362 return A;

364 return A;

365 return nullptr;

366}

367

368template <bool IsLoad, typename Ty>

372 const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,

373 bool OnlyExact) {

374 LLVM_DEBUG(dbgs() << "Trying to determine the potential copies of " << I

375 << " (only exact: " << OnlyExact << ")\n";);

376

377 Value &Ptr = *I.getPointerOperand();

378

379

380

384

385 const auto *TLI =

386 A.getInfoCache().getTargetLibraryInfoForFunction(*I.getFunction());

387

388 auto Pred = [&](Value &Obj) {

389 LLVM_DEBUG(dbgs() << "Visit underlying object " << Obj << "\n");

391 return true;

393

394

396 Ptr.getType()->getPointerAddressSpace()) &&

397 A.getAssumedSimplified(Ptr, QueryingAA, UsedAssumedInformation,

399 return true;

401 dbgs() << "Underlying object is a valid nullptr, giving up.\n";);

402 return false;

403 }

404

407 LLVM_DEBUG(dbgs() << "Underlying object is not supported yet: " << Obj

408 << "\n";);

409 return false;

410 }

412 if (!GV->hasLocalLinkage() &&

413 !(GV->isConstant() && GV->hasInitializer())) {

414 LLVM_DEBUG(dbgs() << "Underlying object is global with external "

415 "linkage, not supported yet: "

416 << Obj << "\n";);

417 return false;

418 }

419

420 bool NullOnly = true;

421 bool NullRequired = false;

422 auto CheckForNullOnlyAndUndef = [&](std::optional<Value *> V,

423 bool IsExact) {

424 if (!V || *V == nullptr)

425 NullOnly = false;

427 ;

429 NullRequired = !IsExact;

430 else

431 NullOnly = false;

432 };

433

437 if (!AdjV) {

438 LLVM_DEBUG(dbgs() << "Underlying object written but stored value "

439 "cannot be converted to read type: "

441 << "\n";);

442 }

443 return AdjV;

444 };

445

448 return true;

449 if (IsLoad) {

451 return true;

453 return false;

456 if (NewCopies.count(V)) {

458 return true;

459 }

461 if (Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand()))

462 if (NewCopies.count(V)) {

464 return true;

465 }

466 }

467 return false;

468 };

469

472 return true;

474 return true;

475 CheckForNullOnlyAndUndef(Acc.getContent(), IsExact);

476 if (OnlyExact && !IsExact && !NullOnly &&

479 << ", abort!\n");

480 return false;

481 }

482 if (NullRequired && !NullOnly) {

483 LLVM_DEBUG(dbgs() << "Required all `null` accesses due to non exact "

484 "one, however found non-null one: "

486 return false;

487 }

488 if (IsLoad) {

492 if (!V)

493 return false;

495 if (PotentialValueOrigins)

497 return true;

498 }

500 if (SI) {

501 LLVM_DEBUG(dbgs() << "Underlying object written through a non-store "

502 "instruction not supported yet: "

504 return false;

505 }

506 Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand());

507 if (!V)

508 return false;

510 if (PotentialValueOrigins)

512 } else {

515 if (!LI && OnlyExact) {

516 LLVM_DEBUG(dbgs() << "Underlying object read through a non-load "

517 "instruction not supported yet: "

519 return false;

520 }

522 }

523 return true;

524 };

525

526

527

528 bool HasBeenWrittenTo = false;

529

533 if (!PI || !PI->forallInterferingAccesses(

534 A, QueryingAA, I,

535 IsLoad,

536 !IsLoad, CheckAccess,

537 HasBeenWrittenTo, Range, SkipCB)) {

540 << "Failed to verify all interfering accesses for underlying object: "

541 << Obj << "\n");

542 return false;

543 }

544

545 if (IsLoad && !HasBeenWrittenTo && Range.isUnassigned()) {

548 A, QueryingAA, Obj, *I.getType(), TLI, DL, &Range);

549 if (!InitialValue) {

550 LLVM_DEBUG(dbgs() << "Could not determine required initial value of "

551 "underlying object, abort!\n");

552 return false;

553 }

554 CheckForNullOnlyAndUndef(InitialValue, true);

555 if (NullRequired && !NullOnly) {

556 LLVM_DEBUG(dbgs() << "Non exact access but initial value that is not "

557 "null or undef, abort!\n");

558 return false;

559 }

560

561 NewCopies.insert(InitialValue);

562 if (PotentialValueOrigins)

563 NewCopyOrigins.insert(nullptr);

564 }

565

567

568 return true;

569 };

570

573 if (!AAUO || !AAUO->forallUnderlyingObjects(Pred)) {

575 dbgs() << "Underlying objects stored into could not be determined\n";);

576 return false;

577 }

578

579

580

581

582 for (const auto *PI : PIs) {

583 if (!PI->getState().isAtFixpoint())

584 UsedAssumedInformation = true;

586 }

588 if (PotentialValueOrigins)

589 PotentialValueOrigins->insert_range(NewCopyOrigins);

590

591 return true;

592}

593

597 const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,

598 bool OnlyExact) {

600 A, LI, PotentialValues, &PotentialValueOrigins, QueryingAA,

601 UsedAssumedInformation, OnlyExact);

602}

603

606 const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,

607 bool OnlyExact) {

609 A, SI, PotentialCopies, nullptr, QueryingAA, UsedAssumedInformation,

610 OnlyExact);

611}

612

615 bool RequireReadNone, bool &IsKnown) {

616 if (RequireReadNone) {

619 true))

620 return true;

623 true))

624 return true;

625

628 const auto *MemLocAA =

630 if (MemLocAA && MemLocAA->isAssumedReadNone()) {

631 IsKnown = MemLocAA->isKnownReadNone();

632 if (!IsKnown)

634 return true;

635 }

636 }

637

638 const auto *MemBehaviorAA =

640 if (MemBehaviorAA &&

641 (MemBehaviorAA->isAssumedReadNone() ||

642 (!RequireReadNone && MemBehaviorAA->isAssumedReadOnly()))) {

643 IsKnown = RequireReadNone ? MemBehaviorAA->isKnownReadNone()

644 : MemBehaviorAA->isKnownReadOnly();

645 if (!IsKnown)

647 return true;

648 }

649

650 return false;

651}

652

656 false, IsKnown);

657}

663

664static bool

669 std::function<bool(const Function &F)> GoBackwardsCB) {

671 dbgs() << "[AA] isPotentiallyReachable @" << ToFn.getName() << " from "

672 << FromI << " [GBCB: " << bool(GoBackwardsCB) << "][#ExS: "

673 << (ExclusionSet ? std::to_string(ExclusionSet->size()) : "none")

674 << "]\n";

675 if (ExclusionSet)

676 for (auto *ES : *ExclusionSet)

677 dbgs() << *ES << "\n";

678 });

679

680

681

682

683

684

685 if (GoBackwardsCB && &ToFn != FromI.getFunction() &&

686 !GoBackwardsCB(*FromI.getFunction()) && A.getInfoCache().isKernel(ToFn) &&

687 A.getInfoCache().isKernel(*FromI.getFunction())) {

688 LLVM_DEBUG(dbgs() << "[AA] assume kernel cannot be reached from within the "

689 "module; success\n";);

690 return false;

691 }

692

693

694

695

696

697

698 if (!GoBackwardsCB && !ExclusionSet) {

700 << " is not checked backwards and does not have an "

701 "exclusion set, abort\n");

702 return true;

703 }

704

708

709 while (!Worklist.empty()) {

711 if (!Visited.insert(CurFromI).second)

712 continue;

713

715 if (FromFn == &ToFn) {

716 if (!ToI)

717 return true;

718 LLVM_DEBUG(dbgs() << "[AA] check " << *ToI << " from " << *CurFromI

719 << " intraprocedurally\n");

722 bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(

723 A, *CurFromI, *ToI, ExclusionSet);

725 << (Result ? "can potentially " : "cannot ") << "reach "

726 << *ToI << " [Intra]\n");

727 if (Result)

728 return true;

729 }

730

731 bool Result = true;

736 Result = !ToReachabilityAA || ToReachabilityAA->isAssumedReachable(

737 A, EntryI, *ToI, ExclusionSet);

739 << " " << (Result ? "can potentially " : "cannot ")

740 << "reach @" << *ToI << " [ToFn]\n");

741 }

742

743 if (Result) {

744

745

748 Result = !FnReachabilityAA || FnReachabilityAA->instructionCanReach(

749 A, *CurFromI, ToFn, ExclusionSet);

751 << " " << (Result ? "can potentially " : "cannot ")

752 << "reach @" << ToFn.getName() << " [FromFn]\n");

753 if (Result)

754 return true;

755 }

756

757

760 auto ReturnInstCB = [&](Instruction &Ret) {

761 bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(

762 A, *CurFromI, Ret, ExclusionSet);

763 LLVM_DEBUG(dbgs() << "[AA][Ret] " << *CurFromI << " "

764 << (Result ? "can potentially " : "cannot ") << "reach "

765 << Ret << " [Intra]\n");

766 return !Result;

767 };

768

769

770 bool UsedAssumedInformation = false;

771 if (A.checkForAllInstructions(ReturnInstCB, FromFn, &QueryingAA,

772 {Instruction::Ret}, UsedAssumedInformation)) {

773 LLVM_DEBUG(dbgs() << "[AA] No return is reachable, done\n");

774 continue;

775 }

776

777 if (!GoBackwardsCB) {

779 << " is not checked backwards, abort\n");

780 return true;

781 }

782

783

784

785 if (!GoBackwardsCB(*FromFn))

786 continue;

787

788 LLVM_DEBUG(dbgs() << "Stepping backwards to the call sites of @"

789 << FromFn->getName() << "\n");

790

792 CallBase *CB = ACS.getInstruction();

793 if (!CB)

794 return false;

795

797 return false;

798

801 return true;

802 };

803

804 Result = A.checkForAllCallSites(CheckCallSite, *FromFn,

805 true,

806 &QueryingAA, UsedAssumedInformation);

807 if (Result) {

808 LLVM_DEBUG(dbgs() << "[AA] stepping back to call sites from " << *CurFromI

809 << " in @" << FromFn->getName()

810 << " failed, give up\n");

811 return true;

812 }

813

814 LLVM_DEBUG(dbgs() << "[AA] stepped back to call sites from " << *CurFromI

815 << " in @" << FromFn->getName()

816 << " worklist size is: " << Worklist.size() << "\n");

817 }

818 return false;

819}

820

825 std::function<bool(const Function &F)> GoBackwardsCB) {

827 return ::isPotentiallyReachable(A, FromI, &ToI, *ToFn, QueryingAA,

828 ExclusionSet, GoBackwardsCB);

829}

830

835 std::function<bool(const Function &F)> GoBackwardsCB) {

836 return ::isPotentiallyReachable(A, FromI, nullptr, ToFn, QueryingAA,

837 ExclusionSet, GoBackwardsCB);

838}

839

843 return true;

848 dbgs() << "[AA] Object '" << Obj

849 << "' is thread local; stack objects are thread local.\n");

850 return true;

851 }

852 bool IsKnownNoCapture;

855 IsKnownNoCapture);

856 LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj << "' is "

857 << (IsAssumedNoCapture ? "" : "not") << " thread local; "

858 << (IsAssumedNoCapture ? "non-" : "")

859 << "captured stack object.\n");

860 return IsAssumedNoCapture;

861 }

863 if (GV->isConstant()) {

865 << "' is thread local; constant global\n");

866 return true;

867 }

868 if (GV->isThreadLocal()) {

870 << "' is thread local; thread local global\n");

871 return true;

872 }

873 }

874

875 if (A.getInfoCache().targetIsGPU()) {

876 if (Obj.getType()->getPointerAddressSpace() ==

879 << "' is thread local; GPU local memory\n");

880 return true;

881 }

882 if (Obj.getType()->getPointerAddressSpace() ==

885 << "' is thread local; GPU constant memory\n");

886 return true;

887 }

888 }

889

890 LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj << "' is not thread local\n");

891 return false;

892}

893

896 if (I.mayHaveSideEffects() && I.mayReadFromMemory())

897 return false;

898

900

901 auto AddLocationPtr = [&](std::optional Loc) {

902 if (Loc || Loc->Ptr) {

904 dbgs() << "[AA] Access to unknown location; -> requires barriers\n");

905 return false;

906 }

908 return true;

909 };

910

913 return true;

916 return true;

918 return true;

919

921}

922

927 for (const Value *Ptr : Ptrs) {

928 if (!Ptr) {

929 LLVM_DEBUG(dbgs() << "[AA] nullptr; -> requires barriers\n");

930 return true;

931 }

932

933 auto Pred = [&](Value &Obj) {

935 return true;

936 LLVM_DEBUG(dbgs() << "[AA] Access to '" << Obj << "' via '" << *Ptr

937 << "'; -> requires barrier\n");

938 return false;

939 };

940

943 if (!UnderlyingObjsAA || !UnderlyingObjsAA->forallUnderlyingObjects(Pred))

944 return true;

945 }

946 return false;

947}

948

949

952 return true;

953

954 return Old.getValueAsInt() >= New.getValueAsInt();

955}

956

957

958

959

962 AttrBuilder &AB) {

963

967 return false;

968 AB.addAttribute(Kind);

969 return true;

970 }

974 if (!ForceReplace)

975 return false;

976 }

978 return true;

979 }

982 if (!ForceReplace && Kind == Attribute::Memory) {

985 return false;

986 AB.addMemoryAttr(ME);

987 return true;

988 }

991 return false;

992 }

993 AB.addAttribute(Attr);

994 return true;

995 }

998 if (!ForceReplace && AttrSet.hasAttribute(Kind))

999 return false;

1000 AB.addAttribute(Attr);

1001 return true;

1002 }

1003

1005}

1006

1010

1011

1012

1014 if (ArgNo < 0)

1015 return nullptr;

1016

1017

1018

1019

1020

1021 std::optional<Argument *> CBCandidateArg;

1025 for (const Use *U : CallbackUses) {

1029 continue;

1030

1032

1033

1034

1036 continue;

1037

1039 "ACS mapped into var-args arguments!");

1040 if (CBCandidateArg) {

1041 CBCandidateArg = nullptr;

1042 break;

1043 }

1045 }

1046 }

1047

1048

1049 if (CBCandidateArg && *CBCandidateArg)

1050 return *CBCandidateArg;

1051

1052

1053

1055 if (Callee && Callee->arg_size() > unsigned(ArgNo))

1056 return Callee->getArg(ArgNo);

1057

1058 return nullptr;

1059}

1060

1063 if (getState().isAtFixpoint())

1064 return HasChanged;

1065

1066 LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");

1067

1069

1070 LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this

1071 << "\n");

1072

1073 return HasChanged;

1074}

1075

1080 InfoCache(InfoCache), Configuration(Configuration) {

1082 return;

1083 for (Function *Fn : Functions)

1084 if (Fn->hasAddressTaken(nullptr,

1085 false,

1086 true,

1087 true,

1088 false,

1089 true))

1090 InfoCache.IndirectlyCallableFunctions.push_back(Fn);

1091}

1092

1097 "Did expect a valid position!");

1100 if (!Explorer)

1101 return false;

1102

1104

1107

1108

1109

1110 if (A2K.empty())

1111 return false;

1112

1114 unsigned AttrsSize = Attrs.size();

1116 EEnd = Explorer->end(IRP.getCtxI());

1117 for (const auto &It : A2K)

1119 Attrs.push_back(Attribute::get(Ctx, AK, It.second.Max));

1120 return AttrsSize != Attrs.size();

1121}

1122

1123template

1128 CB) {

1129 if (AttrDescs.empty())

1135 default:

1136 break;

1137 };

1138

1139 AttributeList AL;

1141 auto It = AttrsMap.find(AttrListAnchor);

1142 if (It == AttrsMap.end())

1144 else

1145 AL = It->getSecond();

1146

1149 AttributeSet AS = AL.getAttributes(AttrIdx);

1151 AttrBuilder AB(Ctx);

1152

1154 for (const DescTy &AttrDesc : AttrDescs)

1155 if (CB(AttrDesc, AS, AM, AB))

1157

1160

1161 AL = AL.removeAttributesAtIndex(Ctx, AttrIdx, AM);

1162 AL = AL.addAttributesAtIndex(Ctx, AttrIdx, AB);

1163 AttrsMap[AttrListAnchor] = AL;

1165}

1166

1169 bool IgnoreSubsumingPositions,

1171 bool Implied = false;

1172 bool HasAttr = false;

1175 if (AttrSet.hasAttribute(Kind)) {

1176 Implied |= Kind != ImpliedAttributeKind;

1177 HasAttr = true;

1178 }

1179 return false;

1180 };

1182 updateAttrMapAttribute::AttrKind(EquivIRP, AttrKinds, HasAttrCB);

1183 if (HasAttr)

1184 break;

1185

1186

1187

1188 if (IgnoreSubsumingPositions)

1189 break;

1190 Implied = true;

1191 }

1192 if (!HasAttr) {

1193 Implied = true;

1197 HasAttr = true;

1198 break;

1199 }

1200 }

1201

1202

1203 if (ImpliedAttributeKind != Attribute::None && HasAttr && Implied)

1205 ImpliedAttributeKind)});

1206 return HasAttr;

1207}

1208

1212 bool IgnoreSubsumingPositions) {

1215 AttrBuilder &) {

1216 if (AttrSet.hasAttribute(Kind))

1217 Attrs.push_back(AttrSet.getAttribute(Kind));

1218 return false;

1219 };

1221 updateAttrMapAttribute::AttrKind(EquivIRP, AttrKinds, CollectAttrCB);

1222

1223

1224

1225 if (IgnoreSubsumingPositions)

1226 break;

1227 }

1230}

1231

1236 if (!AttrSet.hasAttribute(Kind))

1237 return false;

1238 AM.addAttribute(Kind);

1239 return true;

1240 };

1241 return updateAttrMapAttribute::AttrKind(IRP, AttrKinds, RemoveAttrCB);

1242}

1243

1248 if (!AttrSet.hasAttribute(Attr))

1249 return false;

1250 AM.addAttribute(Attr);

1251 return true;

1252 };

1253

1254 return updateAttrMap(IRP, Attrs, RemoveAttrCB);

1255}

1256

1259 bool ForceReplace) {

1263 return addIfNotExistent(Ctx, Attr, AttrSet, ForceReplace, AB);

1264 };

1265 return updateAttrMap(IRP, Attrs, AddAttrCB);

1266}

1267

1271

1273 IRPositions.emplace_back(IRP);

1274

1275

1276

1277 auto CanIgnoreOperandBundles = [](const CallBase &CB) {

1280 };

1281

1287 return;

1291 return;

1293 assert(CB && "Expected call site!");

1294

1295

1296 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB))

1299 return;

1301 assert(CB && "Expected call site!");

1302

1303

1304 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {

1305 if (auto *Callee =

1309 for (const Argument &Arg : Callee->args())

1310 if (Arg.hasReturnedAttr()) {

1311 IRPositions.emplace_back(

1313 IRPositions.emplace_back(

1316 }

1317 }

1318 }

1320 return;

1322 assert(CB && "Expected call site!");

1323

1324

1325 if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {

1327 if (Callee) {

1331 }

1332 }

1334 return;

1335 }

1336 }

1337}

1338

1339void IRPosition::verify() {

1340#ifdef EXPENSIVE_CHECKS

1343 assert((CBContext == nullptr) &&

1344 "Invalid position must not have CallBaseContext!");

1346 "Expected a nullptr for an invalid position!");

1347 return;

1350 "Expected specialized kind for argument values!");

1351 return;

1354 "Expected function for a 'returned' position!");

1356 "Associated value mismatch!");

1357 return;

1359 assert((CBContext == nullptr) &&

1360 "'call site returned' position must not have CallBaseContext!");

1362 "Expected call base for 'call site returned' position!");

1364 "Associated value mismatch!");

1365 return;

1367 assert((CBContext == nullptr) &&

1368 "'call site function' position must not have CallBaseContext!");

1370 "Expected call base for 'call site function' position!");

1372 "Associated value mismatch!");

1373 return;

1376 "Expected function for a 'function' position!");

1378 "Associated value mismatch!");

1379 return;

1382 "Expected argument for a 'argument' position!");

1384 "Associated value mismatch!");

1385 return;

1387 assert((CBContext == nullptr) &&

1388 "'call site argument' position must not have CallBaseContext!");

1389 Use *U = getAsUsePtr();

1390 (void)U;

1391 assert(U && "Expected use for a 'call site argument' position!");

1393 "Expected call base user for a 'call site argument' position!");

1395 "Expected call base argument operand for a 'call site argument' "

1396 "position");

1399 "Argument number mismatch!");

1401 return;

1402 }

1403 }

1404#endif

1405}

1406

1407std::optional<Constant *>

1410 bool &UsedAssumedInformation) {

1411

1412

1413

1414 for (auto &CB : SimplificationCallbacks.lookup(IRP)) {

1415 std::optional<Value *> SimplifiedV = CB(IRP, &AA, UsedAssumedInformation);

1416 if (!SimplifiedV)

1417 return std::nullopt;

1420 return nullptr;

1421 }

1423 return C;

1427 UsedAssumedInformation)) {

1428 if (Values.empty())

1429 return std::nullopt;

1432 return C;

1433 }

1434 return nullptr;

1435}

1436

1440

1441

1442

1443 for (auto &CB : SimplificationCallbacks.lookup(IRP))

1444 return CB(IRP, AA, UsedAssumedInformation);

1445

1449 if (Values.empty())

1450 return std::nullopt;

1451 if (AA)

1453 return V;

1456 return nullptr;

1458}

1459

1463 bool &UsedAssumedInformation, bool RecurseForSelectAndPHI) {

1467 while (!Worklist.empty()) {

1469

1470

1471

1472

1473 int NV = Values.size();

1474 const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP);

1475 for (const auto &CB : SimplificationCBs) {

1476 std::optional<Value *> CBResult = CB(IRP, AA, UsedAssumedInformation);

1477 if (!CBResult.has_value())

1478 continue;

1479 Value *V = *CBResult;

1480 if (!V)

1481 return false;

1485 else

1486 return false;

1487 }

1488 if (SimplificationCBs.empty()) {

1489

1490

1491 const auto *PotentialValuesAA =

1493 if (PotentialValuesAA &&

1494 PotentialValuesAA->getAssumedSimplifiedValues(*this, Values, S)) {

1495 UsedAssumedInformation |= !PotentialValuesAA->isAtFixpoint();

1498 } else {

1499

1500 return false;

1501 }

1502 }

1503

1504 if (!RecurseForSelectAndPHI)

1505 break;

1506

1507 for (int I = NV, E = Values.size(); I < E; ++I) {

1508 Value *V = Values[I].getValue();

1510 continue;

1511 if (!Seen.insert(V).second)

1512 continue;

1513

1514 Values[I] = Values[E - 1];

1515

1517 --E;

1518 --I;

1519

1521 }

1522 }

1523 return true;

1524}

1525

1528 bool &UsedAssumedInformation) {

1529 if (!V)

1530 return V;

1532 return V;

1535 CB.arg_size() > Arg->getArgNo())

1536 if (!Arg->hasPointeeInMemoryValueAttr())

1540 return nullptr;

1541}

1542

1544

1545

1546 for (auto &It : AAMap) {

1548 AA->~AbstractAttribute();

1549 }

1550}

1551

1553 const AAIsDead *FnLivenessAA,

1554 bool &UsedAssumedInformation,

1555 bool CheckBBLivenessOnly, DepClassTy DepClass) {

1556 if (!Configuration.UseLiveness)

1557 return false;

1560 return false;

1561 return isAssumedDead(IRP, &AA, FnLivenessAA, UsedAssumedInformation,

1562 CheckBBLivenessOnly, DepClass);

1563}

1564

1567 const AAIsDead *FnLivenessAA,

1568 bool &UsedAssumedInformation,

1569 bool CheckBBLivenessOnly, DepClassTy DepClass) {

1570 if (!Configuration.UseLiveness)

1571 return false;

1573 if (!UserI)

1575 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);

1576

1578

1579

1580 if (CB->isArgOperand(&U)) {

1583 return isAssumedDead(CSArgPos, QueryingAA, FnLivenessAA,

1584 UsedAssumedInformation, CheckBBLivenessOnly,

1585 DepClass);

1586 }

1589 return isAssumedDead(RetPos, QueryingAA, FnLivenessAA,

1590 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);

1592 BasicBlock *IncomingBB = PHI->getIncomingBlock(U);

1594 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);

1596 if (!CheckBBLivenessOnly && SI->getPointerOperand() != U.get()) {

1601 if (QueryingAA)

1604 UsedAssumedInformation = true;

1605 return true;

1606 }

1607 }

1608 }

1609

1611 UsedAssumedInformation, CheckBBLivenessOnly, DepClass);

1612}

1613

1616 const AAIsDead *FnLivenessAA,

1617 bool &UsedAssumedInformation,

1618 bool CheckBBLivenessOnly, DepClassTy DepClass,

1619 bool CheckForDeadStore) {

1620 if (!Configuration.UseLiveness)

1621 return false;

1624

1625 if (ManifestAddedBlocks.contains(I.getParent()))

1626 return false;

1627

1628 const Function &F = *I.getFunction();

1629 if (!FnLivenessAA || FnLivenessAA->getAnchorScope() != &F)

1632

1633

1634 if (!FnLivenessAA || QueryingAA == FnLivenessAA)

1635 return false;

1636

1637

1638 if (CheckBBLivenessOnly ? FnLivenessAA->isAssumedDead(I.getParent())

1640 if (QueryingAA)

1643 UsedAssumedInformation = true;

1644 return true;

1645 }

1646

1647 if (CheckBBLivenessOnly)

1648 return false;

1649

1653

1654

1655 if (!IsDeadAA || QueryingAA == IsDeadAA)

1656 return false;

1657

1659 if (QueryingAA)

1662 UsedAssumedInformation = true;

1663 return true;

1664 }

1665

1667 if (QueryingAA)

1670 UsedAssumedInformation = true;

1671 return true;

1672 }

1673

1674 return false;

1675}

1676

1679 const AAIsDead *FnLivenessAA,

1680 bool &UsedAssumedInformation,

1681 bool CheckBBLivenessOnly, DepClassTy DepClass) {

1682 if (!Configuration.UseLiveness)

1683 return false;

1684

1685

1688 return false;

1689 }

1690

1692 if (CtxI &&

1693 isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,

1694 true,

1696 return true;

1697

1698 if (CheckBBLivenessOnly)

1699 return false;

1700

1701

1707 else

1709

1710

1711 if (!IsDeadAA || QueryingAA == IsDeadAA)

1712 return false;

1713

1715 if (QueryingAA)

1718 UsedAssumedInformation = true;

1719 return true;

1720 }

1721

1722 return false;

1723}

1724

1727 const AAIsDead *FnLivenessAA,

1729 if (!Configuration.UseLiveness)

1730 return false;

1732 if (!FnLivenessAA || FnLivenessAA->getAnchorScope() != &F)

1735

1736

1737 if (!FnLivenessAA || QueryingAA == FnLivenessAA)

1738 return false;

1739

1741 if (QueryingAA)

1743 return true;

1744 }

1745

1746 return false;

1747}

1748

1753 return Pred(Callee);

1754

1757 if (!CallEdgesAA || CallEdgesAA->hasUnknownCallee())

1758 return false;

1759

1760 const auto &Callees = CallEdgesAA->getOptimisticEdges();

1761 return Pred(Callees.getArrayRef());

1762}

1763

1767

1771 bool CheckBBLivenessOnly, DepClassTy LivenessDepClass,

1772 bool IgnoreDroppableUses,

1773 function_ref<bool(const Use &OldU, const Use &NewU)> EquivalentUseCB) {

1774

1775

1777 if (!CB(*this, &QueryingAA))

1778 return false;

1779

1781 return false;

1782

1783

1784 if (V.use_empty())

1785 return true;

1786

1790

1791 auto AddUsers = [&](const Value &V, const Use *OldUse) {

1792 for (const Use &UU : V.uses()) {

1793 if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {

1794 LLVM_DEBUG(dbgs() << "[Attributor] Potential copy was "

1795 "rejected by the equivalence call back: "

1796 << *UU << "!\n");

1797 return false;

1798 }

1799

1801 }

1802 return true;

1803 };

1804

1805 AddUsers(V, nullptr);

1806

1808 << " initial uses to check\n");

1809

1811 const auto *LivenessAA =

1814 : nullptr;

1815

1816 while (!Worklist.empty()) {

1819 continue;

1822 dbgs() << "[Attributor] Check use: " << **U << " in " << Fn->getName()

1823 << "\n";

1824 else

1825 dbgs() << "[Attributor] Check use: " << **U << " in " << *U->getUser()

1826 << "\n";

1827 });

1828 bool UsedAssumedInformation = false;

1829 if (isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,

1830 CheckBBLivenessOnly, LivenessDepClass)) {

1832 dbgs() << "[Attributor] Dead use, skip!\n");

1833 continue;

1834 }

1835 if (IgnoreDroppableUses && U->getUser()->isDroppable()) {

1837 dbgs() << "[Attributor] Droppable user, skip!\n");

1838 continue;

1839 }

1840

1842 if (&SI->getOperandUse(0) == U) {

1843 if (!Visited.insert(U).second)

1844 continue;

1847 *this, *SI, PotentialCopies, QueryingAA, UsedAssumedInformation,

1848 true)) {

1851 << "[Attributor] Value is stored, continue with "

1852 << PotentialCopies.size()

1853 << " potential copies instead!\n");

1854 for (Value *PotentialCopy : PotentialCopies)

1855 if (!AddUsers(*PotentialCopy, U))

1856 return false;

1857 continue;

1858 }

1859 }

1860 }

1861

1862 bool Follow = false;

1863 if (!Pred(*U, Follow))

1864 return false;

1865 if (!Follow)

1866 continue;

1867

1868 User &Usr = *U->getUser();

1869 AddUsers(Usr, nullptr);

1870 }

1871

1872 return true;

1873}

1874

1877 bool RequireAllCallSites,

1878 bool &UsedAssumedInformation) {

1879

1880

1881

1884 if (!AssociatedFunction) {

1885 LLVM_DEBUG(dbgs() << "[Attributor] No function associated with " << IRP

1886 << "\n");

1887 return false;

1888 }

1889

1891 &QueryingAA, UsedAssumedInformation);

1892}

1893

1896 bool RequireAllCallSites,

1898 bool &UsedAssumedInformation,

1899 bool CheckPotentiallyDead) {

1903 << "[Attributor] Function " << Fn.getName()

1904 << " has no internal linkage, hence not all call sites are known\n");

1905 return false;

1906 }

1907

1909 if (!CB(*this, QueryingAA))

1910 return false;

1911

1913 for (unsigned u = 0; u < Uses.size(); ++u) {

1914 const Use &U = *Uses[u];

1917 dbgs() << "[Attributor] Check use: " << Fn->getName() << " in "

1918 << *U.getUser() << "\n";

1919 else

1920 dbgs() << "[Attributor] Check use: " << *U << " in " << *U.getUser()

1921 << "\n";

1922 });

1923 if (!CheckPotentiallyDead &&

1924 isAssumedDead(U, QueryingAA, nullptr, UsedAssumedInformation,

1925 true)) {

1927 dbgs() << "[Attributor] Dead use, skip!\n");

1928 continue;

1929 }

1931 if (CE->isCast() && CE->getType()->isPointerTy()) {

1933 dbgs() << "[Attributor] Use, is constant cast expression, add "

1934 << CE->getNumUses() << " uses of that expression instead!\n";

1935 });

1936 for (const Use &CEU : CE->uses())

1937 Uses.push_back(&CEU);

1938 continue;

1939 }

1940 }

1941

1943 if (!ACS) {

1945 << " has non call site use " << *U.get() << " in "

1946 << *U.getUser() << "\n");

1947 return false;

1948 }

1949

1950 const Use *EffectiveUse =

1952 if (!ACS.isCallee(EffectiveUse)) {

1953 if (!RequireAllCallSites) {

1954 LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser()

1955 << " is not a call of " << Fn.getName()

1956 << ", skip use\n");

1957 continue;

1958 }

1959 LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser()

1960 << " is an invalid use of " << Fn.getName() << "\n");

1961 return false;

1962 }

1963

1964

1965

1966

1968 unsigned MinArgsParams =

1970 for (unsigned u = 0; u < MinArgsParams; ++u) {

1974 dbgs() << "[Attributor] Call site / callee argument type mismatch ["

1975 << u << "@" << Fn.getName() << ": "

1978 return false;

1979 }

1980 }

1981

1982 if (Pred(ACS))

1983 continue;

1984

1985 LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for "

1987 return false;

1988 }

1989

1990 return true;

1991}

1992

1993bool Attributor::shouldPropagateCallBaseContext(const IRPosition &IRP) {

1994

1995

1996

1998}

1999

2003 bool RecurseForSelectAndPHI) {

2004

2007 if (!AssociatedFunction)

2008 return false;

2009

2010 bool UsedAssumedInformation = false;

2014 UsedAssumedInformation, RecurseForSelectAndPHI))

2015 return false;

2016

2018 return Pred(*VAC.getValue());

2019 });

2020}

2021

2026 bool &UsedAssumedInformation, bool CheckBBLivenessOnly = false,

2027 bool CheckPotentiallyDead = false) {

2028 for (unsigned Opcode : Opcodes) {

2029

2030 auto *Insts = OpcodeInstMap.lookup(Opcode);

2031 if (!Insts)

2032 continue;

2033

2035

2036 if (A && !CheckPotentiallyDead &&

2038 UsedAssumedInformation, CheckBBLivenessOnly)) {

2040 dbgs() << "[Attributor] Instruction " << *I

2041 << " is potentially dead, skip!\n";);

2042 continue;

2043 }

2044

2045 if (!Pred(*I))

2046 return false;

2047 }

2048 }

2049 return true;

2050}

2051

2056 bool &UsedAssumedInformation,

2057 bool CheckBBLivenessOnly,

2058 bool CheckPotentiallyDead) {

2059

2061 return false;

2062

2064 const auto *LivenessAA =

2065 CheckPotentiallyDead && QueryingAA

2067 : nullptr;

2068

2069 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);

2071 LivenessAA, Opcodes, UsedAssumedInformation,

2072 CheckBBLivenessOnly, CheckPotentiallyDead))

2073 return false;

2074

2075 return true;

2076}

2077

2081 bool &UsedAssumedInformation,

2082 bool CheckBBLivenessOnly,

2083 bool CheckPotentiallyDead) {

2087 UsedAssumedInformation, CheckBBLivenessOnly,

2088 CheckPotentiallyDead);

2089}

2090

2093 bool &UsedAssumedInformation) {

2094 TimeTraceScope TS("checkForAllReadWriteInstructions");

2095

2096 const Function *AssociatedFunction =

2098 if (!AssociatedFunction)

2099 return false;

2100

2102 const auto *LivenessAA =

2104

2106 InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {

2107

2109 UsedAssumedInformation))

2110 continue;

2111

2112 if (!Pred(*I))

2113 return false;

2114 }

2115

2116 return true;

2117}

2118

2119void Attributor::runTillFixpoint() {

2120 TimeTraceScope TimeScope("Attributor::runTillFixpoint");

2121 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "

2123 << " abstract attributes.\n");

2124

2125

2126

2127

2128 unsigned IterationCounter = 1;

2129 unsigned MaxIterations =

2131

2135

2136 do {

2137

2139 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter

2140 << ", Worklist size: " << Worklist.size() << "\n");

2141

2142

2143

2144

2145 for (unsigned u = 0; u < InvalidAAs.size(); ++u) {

2147

2148

2150 dbgs() << "[Attributor] InvalidAA: " << *InvalidAA

2151 << " has " << InvalidAA->Deps.size()

2152 << " required & optional dependences\n");

2153 for (auto &DepIt : InvalidAA->Deps) {

2157 dbgs() << " - recompute: " << *DepAA);

2158 Worklist.insert(DepAA);

2159 continue;

2160 }

2162 << " - invalidate: " << *DepAA);

2166 InvalidAAs.insert(DepAA);

2167 else

2169 }

2171 }

2172

2173

2174

2175 for (AbstractAttribute *ChangedAA : ChangedAAs) {

2176 for (auto &DepIt : ChangedAA->Deps)

2178 ChangedAA->Deps.clear();

2179 }

2180

2181 LLVM_DEBUG(dbgs() << "[Attributor] #Iteration: " << IterationCounter

2182 << ", Worklist+Dependent size: " << Worklist.size()

2183 << "\n");

2184

2185

2186 ChangedAAs.clear();

2187 InvalidAAs.clear();

2188

2189

2190

2191 for (AbstractAttribute *AA : Worklist) {

2192 const auto &AAState = AA->getState();

2193 if (!AAState.isAtFixpoint())

2195 ChangedAAs.push_back(AA);

2196

2197

2198

2199 if (!AAState.isValidState())

2200 InvalidAAs.insert(AA);

2201 }

2202

2203

2204

2205 ChangedAAs.append(DG.SyntheticRoot.begin() + NumAAs,

2206 DG.SyntheticRoot.end());

2207

2208

2209

2210 Worklist.clear();

2211 Worklist.insert_range(ChangedAAs);

2212 Worklist.insert_range(QueryAAsAwaitingUpdate);

2213 QueryAAsAwaitingUpdate.clear();

2214

2215 } while (!Worklist.empty() && (IterationCounter++ < MaxIterations));

2216

2217 if (IterationCounter > MaxIterations && !Functions.empty()) {

2218 auto Remark = [&](OptimizationRemarkMissed ORM) {

2219 return ORM << "Attributor did not reach a fixpoint after "

2220 << ore::NV("Iterations", MaxIterations) << " iterations.";

2221 };

2222 Function *F = Functions.front();

2224 }

2225

2226 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "

2227 << IterationCounter << "/" << MaxIterations

2228 << " iterations\n");

2229

2230

2231

2232

2233

2234

2235 SmallPtrSet<AbstractAttribute *, 32> Visited;

2236 for (unsigned u = 0; u < ChangedAAs.size(); u++) {

2237 AbstractAttribute *ChangedAA = ChangedAAs[u];

2238 if (!Visited.insert(ChangedAA).second)

2239 continue;

2240

2241 AbstractState &State = ChangedAA->getState();

2244

2245 NumAttributesTimedOut++;

2246 }

2247

2248 for (auto &DepIt : ChangedAA->Deps)

2251 }

2252

2254 if (!Visited.empty())

2255 dbgs() << "\n[Attributor] Finalized " << Visited.size()

2256 << " abstract attributes.\n";

2257 });

2258}

2259

2262 "Non-query AAs should not be required to register for updates!");

2263 QueryAAsAwaitingUpdate.insert(&AA);

2264}

2265

2266ChangeStatus Attributor::manifestAttributes() {

2267 TimeTraceScope TimeScope("Attributor::manifestAttributes");

2269

2270 unsigned NumManifested = 0;

2271 unsigned NumAtFixpoint = 0;

2276

2277

2278

2279

2280

2281 if (!State.isAtFixpoint())

2282 State.indicateOptimisticFixpoint();

2283

2284

2285 if (AA->hasCallBaseContext())

2286 continue;

2287

2288 if (!State.isValidState())

2289 continue;

2290

2291 if (AA->getCtxI() && isRunOn(*AA->getAnchorScope()))

2292 continue;

2293

2294

2295 bool UsedAssumedInformation = false;

2297 true))

2298 continue;

2299

2300

2302 continue;

2303

2306 AA->trackStatistics();

2307 LLVM_DEBUG(dbgs() << "[Attributor] Manifest " << LocalChange << " : " << *AA

2308 << "\n");

2309

2310 ManifestChange = ManifestChange | LocalChange;

2311

2312 NumAtFixpoint++;

2314 }

2315

2316 (void)NumManifested;

2317 (void)NumAtFixpoint;

2318 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested

2319 << " arguments while " << NumAtFixpoint

2320 << " were in a valid fixpoint state\n");

2321

2322 NumAttributesManifested += NumManifested;

2323 NumAttributesValidFixpoint += NumAtFixpoint;

2324

2325 (void)NumFinalAAs;

2328 for (unsigned u = 0; u < NumFinalAAs; ++u)

2329 ++DepIt;

2331 ++u, ++DepIt) {

2332 errs() << "Unexpected abstract attribute: "

2335 ->getIRPosition()

2336 .getAssociatedValue()

2337 << "\n";

2338 }

2339 llvm_unreachable("Expected the final number of abstract attributes to "

2340 "remain unchanged!");

2341 }

2342

2343 for (auto &It : AttrsMap) {

2344 AttributeList &AL = It.getSecond();

2345 const IRPosition &IRP =

2348 : IRPosition::callsite_function(*cast(It.getFirst()));

2350 }

2351

2352 return ManifestChange;

2353}

2354

2355void Attributor::identifyDeadInternalFunctions() {

2356

2357 if (!Configuration.DeleteFns)

2358 return;

2359

2360

2361

2362

2363 const auto *TLI =

2365 ? nullptr

2367 LibFunc LF;

2368

2369

2370

2371

2372

2373

2375 for (Function *F : Functions)

2376 if (F->hasLocalLinkage() && (isModulePass() || !TLI->getLibFunc(*F, LF)))

2378

2379 SmallPtrSet<Function *, 8> LiveInternalFns;

2380 bool FoundLiveInternal = true;

2381 while (FoundLiveInternal) {

2382 FoundLiveInternal = false;

2383 for (Function *&F : InternalFns) {

2384 if (F)

2385 continue;

2386

2387 bool UsedAssumedInformation = false;

2389 [&](AbstractCallSite ACS) {

2391 return ToBeDeletedFunctions.count(Callee) ||

2392 (Functions.count(Callee) && Callee->hasLocalLinkage() &&

2393 !LiveInternalFns.count(Callee));

2394 },

2395 *F, true, nullptr, UsedAssumedInformation)) {

2396 continue;

2397 }

2398

2399 LiveInternalFns.insert(F);

2400 F = nullptr;

2401 FoundLiveInternal = true;

2402 }

2403 }

2404

2405 for (Function *F : InternalFns)

2406 if (F)

2407 ToBeDeletedFunctions.insert(F);

2408}

2409

2411 TimeTraceScope TimeScope("Attributor::cleanupIR");

2412

2413 LLVM_DEBUG(dbgs() << "\n[Attributor] Delete/replace at least "

2414 << ToBeDeletedFunctions.size() << " functions and "

2415 << ToBeDeletedBlocks.size() << " blocks and "

2416 << ToBeDeletedInsts.size() << " instructions and "

2417 << ToBeChangedValues.size() << " values and "

2418 << ToBeChangedUses.size() << " uses. To insert "

2419 << ToBeChangedToUnreachableInsts.size()

2420 << " unreachables.\n"

2421 << "Preserve manifest added " << ManifestAddedBlocks.size()

2422 << " blocks\n");

2423

2426

2427 auto ReplaceUse = [&](Use *U, Value *NewV) {

2428 Value *OldV = U->get();

2429

2430

2431 do {

2432 const auto &Entry = ToBeChangedValues.lookup(NewV);

2434 break;

2435 NewV = get<0>(Entry);

2436 } while (true);

2437

2440 "Cannot replace an instruction outside the current SCC!");

2441

2442

2443

2446 if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))

2447 return;

2448

2449

2451 for (auto &Arg : RI->getFunction()->args())

2452 Arg.removeAttr(Attribute::Returned);

2453 }

2454

2455 LLVM_DEBUG(dbgs() << "Use " << *NewV << " in " << *U->getUser()

2456 << " instead of " << *OldV << "\n");

2457 U->set(NewV);

2458

2460 CGModifiedFunctions.insert(I->getFunction());

2461 if (isa<PHINode>(I) && !ToBeDeletedInsts.count(I) &&

2464 }

2467 if (CB->isArgOperand(U)) {

2468 unsigned Idx = CB->getArgOperandNo(U);

2469 CB->removeParamAttr(Idx, Attribute::NoUndef);

2471 if (Callee && Callee->arg_size() > Idx)

2472 Callee->removeParamAttr(Idx, Attribute::NoUndef);

2473 }

2474 }

2478 ToBeChangedToUnreachableInsts.insert(UserI);

2479 } else {

2480 TerminatorsToFold.push_back(UserI);

2481 }

2482 }

2483 };

2484

2485 for (auto &It : ToBeChangedUses) {

2486 Use *U = It.first;

2487 Value *NewV = It.second;

2488 ReplaceUse(U, NewV);

2489 }

2490

2492 for (auto &It : ToBeChangedValues) {

2493 Value *OldV = It.first;

2494 auto [NewV, Done] = It.second;

2495 Uses.clear();

2496 for (auto &U : OldV->uses())

2497 if (Done || U.getUser()->isDroppable())

2498 Uses.push_back(&U);

2499 for (Use *U : Uses) {

2501 if (isRunOn(*I->getFunction()))

2502 continue;

2503 ReplaceUse(U, NewV);

2504 }

2505 }

2506

2507 for (const auto &V : InvokeWithDeadSuccessor)

2510 "Cannot replace an invoke outside the current SCC!");

2511 bool UnwindBBIsDead = II->hasFnAttr(Attribute::NoUnwind);

2512 bool NormalBBIsDead = II->hasFnAttr(Attribute::NoReturn);

2513 bool Invoke2CallAllowed =

2515 assert((UnwindBBIsDead || NormalBBIsDead) &&

2516 "Invoke does not have dead successors!");

2518 BasicBlock *NormalDestBB = II->getNormalDest();

2519 if (UnwindBBIsDead) {

2521 if (Invoke2CallAllowed) {

2524 }

2525 if (NormalBBIsDead)

2526 ToBeChangedToUnreachableInsts.insert(NormalNextIP);

2527 } else {

2528 assert(NormalBBIsDead && "Broken invariant!");

2531 ToBeChangedToUnreachableInsts.insert(&NormalDestBB->front());

2532 }

2533 }

2534 for (Instruction *I : TerminatorsToFold) {

2536 "Cannot replace a terminator outside the current SCC!");

2537 CGModifiedFunctions.insert(I->getFunction());

2539 }

2540 for (const auto &V : ToBeChangedToUnreachableInsts)

2542 LLVM_DEBUG(dbgs() << "[Attributor] Change to unreachable: " << *I

2543 << "\n");

2545 "Cannot replace an instruction outside the current SCC!");

2546 CGModifiedFunctions.insert(I->getFunction());

2548 }

2549

2550 for (const auto &V : ToBeDeletedInsts) {

2553 isRunOn(*I->getFunction())) &&

2554 "Cannot delete an instruction outside the current SCC!");

2555 I->dropDroppableUses();

2556 CGModifiedFunctions.insert(I->getFunction());

2557 if (I->getType()->isVoidTy())

2561 else

2562 I->eraseFromParent();

2563 }

2564 }

2565

2566 llvm::erase_if(DeadInsts, [&](WeakTrackingVH I) { return I; });

2567

2569 dbgs() << "[Attributor] DeadInsts size: " << DeadInsts.size() << "\n";

2570 for (auto &I : DeadInsts)

2571 if (I)

2572 dbgs() << " - " << *I << "\n";

2573 });

2574

2576

2577 if (unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {

2578 SmallVector<BasicBlock *, 8> ToBeDeletedBBs;

2579 ToBeDeletedBBs.reserve(NumDeadBlocks);

2580 for (BasicBlock *BB : ToBeDeletedBlocks) {

2582 "Cannot delete a block outside the current SCC!");

2583 CGModifiedFunctions.insert(BB->getParent());

2584

2585 if (ManifestAddedBlocks.contains(BB))

2586 continue;

2588 }

2589

2590

2591

2593 }

2594

2595 identifyDeadInternalFunctions();

2596

2597

2598 ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);

2599

2600 for (Function *Fn : CGModifiedFunctions)

2601 if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn))

2602 Configuration.CGUpdater.reanalyzeFunction(*Fn);

2603

2604 for (Function *Fn : ToBeDeletedFunctions) {

2605 if (!Functions.count(Fn))

2606 continue;

2607 Configuration.CGUpdater.removeFunction(*Fn);

2608 }

2609

2610 if (!ToBeChangedUses.empty())

2612

2613 if (!ToBeChangedToUnreachableInsts.empty())

2615

2616 if (!ToBeDeletedFunctions.empty())

2618

2619 if (!ToBeDeletedBlocks.empty())

2621

2622 if (!ToBeDeletedInsts.empty())

2624

2625 if (!InvokeWithDeadSuccessor.empty())

2627

2628 if (!DeadInsts.empty())

2630

2631 NumFnDeleted += ToBeDeletedFunctions.size();

2632

2633 LLVM_DEBUG(dbgs() << "[Attributor] Deleted " << ToBeDeletedFunctions.size()

2634 << " functions after manifest.\n");

2635

2636#ifdef EXPENSIVE_CHECKS

2637 for (Function *F : Functions) {

2638 if (ToBeDeletedFunctions.count(F))

2639 continue;

2641 }

2642#endif

2643

2644 return ManifestChange;

2645}

2646

2649 AttributorCallGraph ACallGraph(*this);

2650

2653

2654 Phase = AttributorPhase::UPDATE;

2655 runTillFixpoint();

2656

2657

2659 DG.dumpGraph();

2660

2662 DG.viewGraph();

2663

2665 DG.print();

2666

2667 Phase = AttributorPhase::MANIFEST;

2668 ChangeStatus ManifestChange = manifestAttributes();

2669

2670 Phase = AttributorPhase::CLEANUP;

2672

2674 ACallGraph.print();

2675

2676 return ManifestChange | CleanupChange;

2677}

2678

2681 return AA.getName().str() +

2682 std::to_string(AA.getIRPosition().getPositionKind());

2683 });

2684 assert(Phase == AttributorPhase::UPDATE &&

2685 "We can update AA only in the update stage!");

2686

2687

2688 DependenceVector DV;

2689 DependenceStack.push_back(&DV);

2690

2691 auto &AAState = AA.getState();

2693 bool UsedAssumedInformation = false;

2695 true))

2696 CS = AA.update(*this);

2697

2698 if (AA.isQueryAA() && DV.empty() && AA.getState().isAtFixpoint()) {

2699

2700

2701

2702

2705 RerunCS = AA.update(*this);

2706

2707

2708

2709

2711 AAState.indicateOptimisticFixpoint();

2712 }

2713

2714 if (!AAState.isAtFixpoint())

2715 rememberDependences();

2716

2717

2718

2719 DependenceVector *PoppedDV = DependenceStack.pop_back_val();

2720 (void)PoppedDV;

2721 assert(PoppedDV == &DV && "Inconsistent usage of the dependence stack!");

2722

2723 return CS;

2724}

2725

2727 assert(F.isDeclaration() && "Cannot create a wrapper around a declaration!");

2728

2729 Module &M = *F.getParent();

2732

2734 Function::Create(FnTy, F.getLinkage(), F.getAddressSpace(), F.getName());

2735 F.setName("");

2736 M.getFunctionList().insert(F.getIterator(), Wrapper);

2737

2739

2740 F.replaceAllUsesWith(Wrapper);

2741 assert(F.use_empty() && "Uses remained after wrapper was created!");

2742

2743

2744

2745 Wrapper->setComdat(F.getComdat());

2746 F.setComdat(nullptr);

2747

2748

2750 F.getAllMetadata(MDs);

2751 for (auto MDIt : MDs)

2752 Wrapper->addMetadata(MDIt.first, *MDIt.second);

2753 Wrapper->setAttributes(F.getAttributes());

2754

2755

2757

2759 Argument *FArgIt = F.arg_begin();

2761 Args.push_back(&Arg);

2762 Arg.setName((FArgIt++)->getName());

2763 }

2764

2767 CI->addFnAttr(Attribute::NoInline);

2769

2770 NumFnShallowWrappersCreated++;

2771}

2772

2774 if (F.isDeclaration() || F.hasLocalLinkage() ||

2776 return false;

2777 return true;

2778}

2779

2782 return nullptr;

2784 return nullptr;

2785

2789

2790 return InternalizedFns[&F];

2791}

2792

2797 return false;

2798

2800

2802 Module &M = *F->getParent();

2804

2805

2808 F->getName() + ".internalized");

2810 auto *NewFArgIt = Copied->arg_begin();

2811 for (auto &Arg : F->args()) {

2812 auto ArgName = Arg.getName();

2813 NewFArgIt->setName(ArgName);

2814 VMap[&Arg] = &(*NewFArgIt++);

2815 }

2817

2818

2821

2822

2823

2826

2827

2829 F->getAllMetadata(MDs);

2830 for (auto MDIt : MDs)

2832 Copied->addMetadata(MDIt.first, *MDIt.second);

2833

2834 M.getFunctionList().insert(F->getIterator(), Copied);

2836 FnMap[F] = Copied;

2837 }

2838

2839

2840

2842 auto &InternalizedFn = FnMap[F];

2843 auto IsNotInternalized = [&](Use &U) -> bool {

2845 return !FnMap.lookup(CB->getCaller());

2846 return false;

2847 };

2848 F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);

2849 }

2850

2851 return true;

2852}

2853

2856

2857 if (!Configuration.RewriteSignatures)

2858 return false;

2859

2862

2863

2864

2868 return false;

2871 return false;

2873 return false;

2874

2876 };

2877

2878

2880 LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite var-args functions\n");

2881 return false;

2882 }

2883

2884

2885 AttributeList FnAttributeList = Fn->getAttributes();

2886 if (FnAttributeList.hasAttrSomewhere(Attribute::Nest) ||

2887 FnAttributeList.hasAttrSomewhere(Attribute::StructRet) ||

2888 FnAttributeList.hasAttrSomewhere(Attribute::InAlloca) ||

2889 FnAttributeList.hasAttrSomewhere(Attribute::Preallocated)) {

2891 dbgs() << "[Attributor] Cannot rewrite due to complex attribute\n");

2892 return false;

2893 }

2894

2895

2896 bool UsedAssumedInformation = false;

2898 UsedAssumedInformation,

2899 true)) {

2900 LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite all call sites\n");

2901 return false;

2902 }

2903

2906 return !CI->isMustTailCall();

2907 return true;

2908 };

2909

2910

2911

2912 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);

2914 nullptr, {Instruction::Call},

2915 UsedAssumedInformation)) {

2916 LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite due to instructions\n");

2917 return false;

2918 }

2919

2920 return true;

2921}

2922

2927 LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in "

2929 << ReplacementTypes.size() << " replacements\n");

2931 "Cannot register an invalid rewrite");

2932

2935 ArgumentReplacementMap[Fn];

2936 if (ARIs.empty())

2938

2939

2940

2941 std::unique_ptr &ARI = ARIs[Arg.getArgNo()];

2942 if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.size()) {

2943 LLVM_DEBUG(dbgs() << "[Attributor] Existing rewrite is preferred\n");

2944 return false;

2945 }

2946

2947

2948

2949 ARI.reset();

2950

2951 LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in "

2953 << ReplacementTypes.size() << " replacements\n");

2954

2955

2957 std::move(CalleeRepairCB),

2958 std::move(ACSRepairCB)));

2959

2960 return true;

2961}

2962

2964 bool Result = true;

2965#ifndef NDEBUG

2971#endif

2972 return Result;

2973}

2974

2975ChangeStatus Attributor::rewriteFunctionSignatures(

2978

2979 for (auto &It : ArgumentReplacementMap) {

2980 Function *OldFn = It.getFirst();

2981

2982

2983 if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))

2984 continue;

2985

2987 It.getSecond();

2989

2992

2993

2994 AttributeList OldFnAttributeList = OldFn->getAttributes();

2996 if (const std::unique_ptr &ARI =

2997 ARIs[Arg.getArgNo()]) {

2998 NewArgumentTypes.append(ARI->ReplacementTypes.begin(),

2999 ARI->ReplacementTypes.end());

3000 NewArgumentAttributes.append(ARI->getNumReplacementArgs(),

3002 } else {

3003 NewArgumentTypes.push_back(Arg.getType());

3004 NewArgumentAttributes.push_back(

3005 OldFnAttributeList.getParamAttrs(Arg.getArgNo()));

3006 }

3007 }

3008

3009 uint64_t LargestVectorWidth = 0;

3010 for (auto *I : NewArgumentTypes)

3012 LargestVectorWidth =

3013 std::max(LargestVectorWidth,

3014 VT->getPrimitiveSizeInBits().getKnownMinValue());

3015

3017 Type *RetTy = OldFnTy->getReturnType();

3018

3019

3020 FunctionType *NewFnTy =

3021 FunctionType::get(RetTy, NewArgumentTypes, OldFnTy->isVarArg());

3022

3025 << *NewFnTy << "\n");

3026

3027

3030 Functions.insert(NewFn);

3034

3035

3038

3039

3040

3041 LLVMContext &Ctx = OldFn->getContext();

3043 Ctx, OldFnAttributeList.getFnAttrs(), OldFnAttributeList.getRetAttrs(),

3044 NewArgumentAttributes));

3045 AttributeFuncs::updateMinLegalVectorWidthAttr(*NewFn, LargestVectorWidth);

3046

3047

3048

3050 int ArgNo = -1;

3052 ++ArgNo;

3053 return T->isPtrOrPtrVectorTy() ||

3055 })) {

3057 }

3058

3059

3060

3061

3063

3064

3065

3067

3068

3069 auto CallSiteReplacementCreator = [&](AbstractCallSite ACS) {

3071 const AttributeList &OldCallAttributeList = OldCB->getAttributes();

3072

3073

3074 SmallVector<Value *, 16> NewArgOperands;

3076 for (unsigned OldArgNum = 0; OldArgNum < ARIs.size(); ++OldArgNum) {

3077 unsigned NewFirstArgNum = NewArgOperands.size();

3078 (void)NewFirstArgNum;

3079 if (const std::unique_ptr &ARI =

3080 ARIs[OldArgNum]) {

3081 if (ARI->ACSRepairCB)

3082 ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);

3083 assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==

3084 NewArgOperands.size() &&

3085 "ACS repair callback did not provide as many operand as new "

3086 "types were registered!");

3087

3088 NewArgOperandAttributes.append(ARI->ReplacementTypes.size(),

3089 AttributeSet());

3090 } else {

3092 NewArgOperandAttributes.push_back(

3093 OldCallAttributeList.getParamAttrs(OldArgNum));

3094 }

3095 }

3096

3097 assert(NewArgOperands.size() == NewArgOperandAttributes.size() &&

3098 "Mismatch # argument operands vs. # argument operand attributes!");

3100 "Mismatch # argument operands vs. # function arguments!");

3101

3104

3105

3106 CallBase *NewCB;

3109 II->getUnwindDest(), NewArgOperands,

3110 OperandBundleDefs, "", OldCB->getIterator());

3111 } else {

3112 auto *NewCI = CallInst::Create(NewFn, NewArgOperands, OperandBundleDefs,

3114 NewCI->setTailCallKind(cast(OldCB)->getTailCallKind());

3115 NewCB = NewCI;

3116 }

3117

3118

3119 NewCB->copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});

3123 Ctx, OldCallAttributeList.getFnAttrs(),

3124 OldCallAttributeList.getRetAttrs(), NewArgOperandAttributes));

3125

3126 AttributeFuncs::updateMinLegalVectorWidthAttr(*NewCB->getCaller(),

3127 LargestVectorWidth);

3128

3129 CallSitePairs.push_back({OldCB, NewCB});

3130 return true;

3131 };

3132

3133

3134 bool UsedAssumedInformation = false;

3136 true, nullptr, UsedAssumedInformation,

3137 true);

3139 assert(Success && "Assumed call site replacement to succeed!");

3140

3141

3144 for (unsigned OldArgNum = 0; OldArgNum < ARIs.size();

3145 ++OldArgNum, ++OldFnArgIt) {

3146 if (const std::unique_ptr &ARI =

3147 ARIs[OldArgNum]) {

3148 if (ARI->CalleeRepairCB)

3149 ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);

3150 if (ARI->ReplacementTypes.empty())

3153 NewFnArgIt += ARI->ReplacementTypes.size();

3154 } else {

3155 NewFnArgIt->takeName(&*OldFnArgIt);

3157 ++NewFnArgIt;

3158 }

3159 }

3160

3161

3162 for (auto &CallSitePair : CallSitePairs) {

3163 CallBase &OldCB = *CallSitePair.first;

3164 CallBase &NewCB = *CallSitePair.second;

3166 "Cannot handle call sites with different types!");

3170 }

3171

3172

3173 Configuration.CGUpdater.replaceFunctionWith(*OldFn, *NewFn);

3174

3175

3176

3177 if (ModifiedFns.remove(OldFn))

3178 ModifiedFns.insert(NewFn);

3179

3181 }

3182

3184}

3185

3186void InformationCache::initializeInformationCache(const Function &CF,

3187 FunctionInfo &FI) {

3188

3189

3190

3192

3193 FI.IsKernel = F.hasFnAttribute("kernel");

3194

3195

3196

3197

3198

3199 DenseMap<const Value *, std::optional> AssumeUsesMap;

3200

3201

3202

3203

3204 auto AddToAssumeUsesMap = [&](const Value &V) -> void {

3205 SmallVector<const Instruction *> Worklist;

3208 while (!Worklist.empty()) {

3210 std::optional &NumUses = AssumeUsesMap[I];

3211 if (!NumUses)

3212 NumUses = I->getNumUses();

3213 NumUses = *NumUses - 1;

3214 if (*NumUses != 0)

3215 continue;

3216 AssumeOnlyValues.insert(I);

3217 for (const Value *Op : I->operands())

3220 }

3221 };

3222

3224 bool IsInterestingOpcode = false;

3225

3226

3227

3228

3229

3230

3231 switch (I.getOpcode()) {

3232 default:

3234 "New call base instruction type needs to be known in the "

3235 "Attributor.");

3236 break;

3237 case Instruction::Call:

3238

3239

3240

3242 AssumeOnlyValues.insert(Assume);

3244 AddToAssumeUsesMap(*Assume->getArgOperand(0));

3246 FI.ContainsMustTailCall = true;

3249 getFunctionInfo(*Callee).CalledViaMustTail = true;

3250 }

3251 [[fallthrough]];

3252 case Instruction::CallBr:

3253 case Instruction::Invoke:

3254 case Instruction::CleanupRet:

3255 case Instruction::CatchSwitch:

3256 case Instruction::AtomicRMW:

3257 case Instruction::AtomicCmpXchg:

3258 case Instruction::Br:

3259 case Instruction::Resume:

3260 case Instruction::Ret:

3261 case Instruction::Load:

3262

3263 case Instruction::Store:

3264

3265 case Instruction::Alloca:

3266 case Instruction::AddrSpaceCast:

3267 IsInterestingOpcode = true;

3268 }

3269 if (IsInterestingOpcode) {

3270 auto *&Insts = FI.OpcodeInstMap[I.getOpcode()];

3271 if (!Insts)

3274 }

3275 if (I.mayReadOrWriteMemory())

3276 FI.RWInsts.push_back(&I);

3277 }

3278

3279 if (F.hasFnAttribute(Attribute::AlwaysInline) &&

3281 InlineableFunctions.insert(&F);

3282}

3283

3284InformationCache::FunctionInfo::~FunctionInfo() {

3285

3286

3287 for (auto &It : OpcodeInstMap)

3288 It.getSecond()->~InstructionVectorTy();

3289}

3290

3293 assert(A.isClosedWorldModule() && "Cannot see all indirect callees!");

3294 return IndirectlyCallableFunctions;

3295}

3296

3298 if (TargetTriple.isGPU())

3299 return 0;

3300 return std::nullopt;

3301}

3302

3307 return;

3308

3309

3310

3311 if (DependenceStack.empty())

3312 return;

3314 return;

3315 DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});

3316}

3317

3318void Attributor::rememberDependences() {

3319 assert(!DependenceStack.empty() && "No dependences to remember!");

3320

3321 for (DepInfo &DI : *DependenceStack.back()) {

3324 "Expected required or optional dependence (1 bit)!");

3325 auto &DepAAs = const_cast<AbstractAttribute &>(*DI.FromAA).Deps;

3327 const_cast<AbstractAttribute *>(DI.ToAA), unsigned(DI.DepClass)));

3328 }

3329}

3330

3331template <Attribute::AttrKind AK, typename AAType>

3332void Attributor::checkAndQueryIRAttr(const IRPosition &IRP, AttributeSet Attrs,

3333 bool SkipHasAttrCheck) {

3334 bool IsKnown;

3335 if (SkipHasAttrCheck || Attrs.hasAttribute(AK))

3336 if (!Configuration.Allowed || Configuration.Allowed->count(&AAType::ID))

3338 IsKnown))

3339 getOrCreateAAFor(IRP);

3340}

3341

3343 if (!VisitedFunctions.insert(&F).second)

3344 return;

3345 if (F.isDeclaration())

3346 return;

3347

3348

3349

3350

3351 InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(F);

3352 if (isModulePass() && !FI.CalledViaMustTail) {

3353 for (const Use &U : F.uses())

3355 if (CB->isCallee(&U) && CB->isMustTailCall())

3356 FI.CalledViaMustTail = true;

3357 }

3358

3361 auto Attrs = F.getAttributes();

3362 auto FnAttrs = Attrs.getFnAttrs();

3363

3364

3365

3366

3368

3369

3370

3372

3373

3376

3377

3378 checkAndQueryIRAttr<Attribute::MustProgress, AAMustProgress>(FPos, FnAttrs);

3379

3380

3381 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(FPos, FnAttrs);

3382

3383

3384 checkAndQueryIRAttr<Attribute::WillReturn, AAWillReturn>(FPos, FnAttrs);

3385

3386

3387 checkAndQueryIRAttr<Attribute::NoSync, AANoSync>(FPos, FnAttrs);

3388

3389

3390

3391

3392 if (IsIPOAmendable) {

3393

3394

3395 checkAndQueryIRAttr<Attribute::NoUnwind, AANoUnwind>(FPos, FnAttrs);

3396

3397

3398 checkAndQueryIRAttr<Attribute::NoReturn, AANoReturn>(FPos, FnAttrs);

3399

3400

3401 checkAndQueryIRAttr<Attribute::NoRecurse, AANoRecurse>(FPos, FnAttrs);

3402

3403

3404 if (Attrs.hasFnAttr(Attribute::Convergent))

3406

3407

3409

3410

3412

3413

3415

3416

3417

3418

3423

3424

3425 Type *ReturnType = F.getReturnType();

3426 if (!ReturnType->isVoidTy()) {

3428 AttributeSet RetAttrs = Attrs.getRetAttrs();

3429

3430

3432

3433

3434 bool UsedAssumedInformation = false;

3437

3438

3439 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(RetPos, RetAttrs);

3440

3441 if (ReturnType->isPointerTy()) {

3442

3443

3445

3446

3447 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(RetPos, RetAttrs);

3448

3449

3450 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(RetPos, RetAttrs);

3451

3452

3453

3455 } else if (AttributeFuncs::isNoFPClassCompatibleType(ReturnType)) {

3457 }

3458 }

3459 }

3460

3461 for (Argument &Arg : F.args()) {

3463 auto ArgNo = Arg.getArgNo();

3464 AttributeSet ArgAttrs = Attrs.getParamAttrs(ArgNo);

3465

3466 if (!IsIPOAmendable) {

3467 if (Arg.getType()->isPointerTy())

3468

3469 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);

3470 continue;

3471 }

3472

3473

3474

3475

3476 bool UsedAssumedInformation = false;

3479

3480

3482

3483

3484 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(ArgPos, ArgAttrs);

3485

3486 if (Arg.getType()->isPointerTy()) {

3487

3488 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(ArgPos, ArgAttrs);

3489

3490

3491 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(ArgPos, ArgAttrs);

3492

3493

3495

3496

3498

3499

3500 checkAndQueryIRAttr<Attribute::Captures, AANoCapture>(

3501 ArgPos, ArgAttrs, true);

3502

3503

3504

3506

3507

3508 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);

3509

3510

3511

3513 } else if (AttributeFuncs::isNoFPClassCompatibleType(Arg.getType())) {

3515 }

3516 }

3517

3518 auto CallSitePred = [&](Instruction &I) -> bool {

3522

3523

3524

3526

3528

3529

3530 if (!Callee) {

3532 return true;

3533 }

3534

3535

3537

3538

3539

3541 !Callee->hasMetadata(LLVMContext::MD_callback))

3542 return true;

3543

3544 if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {

3546 bool UsedAssumedInformation = false;

3549

3550 if (AttributeFuncs::isNoFPClassCompatibleType(Callee->getReturnType()))

3552 }

3553

3554 const AttributeList &CBAttrs = CBFnPos.getAttrList();

3555 for (int I = 0, E = CB.arg_size(); I < E; ++I) {

3556

3558 AttributeSet CBArgAttrs = CBAttrs.getParamAttrs(I);

3559

3560

3562

3563

3564

3565

3566 bool UsedAssumedInformation = false;

3569

3570

3571 checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(CBArgPos, CBArgAttrs);

3572

3573 Type *ArgTy = CB.getArgOperand(I)->getType();

3574

3576 if (AttributeFuncs::isNoFPClassCompatibleType(ArgTy))

3578

3579 continue;

3580 }

3581

3582

3583 checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(CBArgPos, CBArgAttrs);

3584

3585

3586 checkAndQueryIRAttr<Attribute::Captures, AANoCapture>(

3587 CBArgPos, CBArgAttrs, true);

3588

3589

3590 checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(CBArgPos, CBArgAttrs);

3591

3592

3594

3595

3597

3598

3599

3600 if (!CBAttrs.hasParamAttr(I, Attribute::ReadNone))

3602

3603

3604 checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(CBArgPos, CBArgAttrs);

3605 }

3606 return true;

3607 };

3608

3609 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);

3610 [[maybe_unused]] bool Success;

3611 bool UsedAssumedInformation = false;

3613 nullptr, OpcodeInstMap, CallSitePred, nullptr, nullptr,

3614 {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,

3615 (unsigned)Instruction::Call},

3616 UsedAssumedInformation);

3617 assert(Success && "Expected the check call to be successful!");

3618

3619 auto LoadStorePred = [&](Instruction &I) -> bool {

3629 } else {

3637 }

3638 return true;

3639 };

3641 nullptr, OpcodeInstMap, LoadStorePred, nullptr, nullptr,

3642 {(unsigned)Instruction::Load, (unsigned)Instruction::Store},

3643 UsedAssumedInformation);

3644 assert(Success && "Expected the check call to be successful!");

3645

3646

3647 auto AAAllocationInfoPred = [&](Instruction &I) -> bool {

3649 return true;

3650 };

3651

3653 nullptr, OpcodeInstMap, AAAllocationInfoPred, nullptr, nullptr,

3654 {(unsigned)Instruction::Alloca}, UsedAssumedInformation);

3655 assert(Success && "Expected the check call to be successful!");

3656}

3657

3661 return isModulePass() && Configuration.IsClosedWorldModule;

3662}

3663

3664

3665

3666

3670

3672 switch (AP) {

3674 return OS << "inv";

3676 return OS << "flt";

3678 return OS << "fn_ret";

3680 return OS << "cs_ret";

3682 return OS << "fn";

3684 return OS << "cs";

3686 return OS << "arg";

3688 return OS << "cs_arg";

3689 }

3691}

3692

3697

3700 return OS << "}";

3701}

3702

3704 OS << "range-state(" << S.getBitWidth() << ")<";

3706 OS << " / ";

3708 OS << ">";

3709

3710 return OS << static_cast<const AbstractState &>(S);

3711}

3712

3716

3718 AA.print(OS);

3719 return OS;

3720}

3721

3724 OS << "set-state(< {";

3726 OS << "full-set";

3727 else {

3729 OS << It << ", ";

3731 OS << "undef ";

3732 }

3733 OS << "} >)";

3734

3735 return OS;

3736}

3737

3740 OS << "set-state(< {";

3742 OS << "full-set";

3743 else {

3746 OS << "@" << F->getName() << "[" << int(It.second) << "], ";

3747 else

3748 OS << *It.first.getValue() << "[" << int(It.second) << "], ";

3749 }

3751 OS << "undef ";

3752 }

3753 OS << "} >)";

3754

3755 return OS;

3756}

3757

3759 OS << "[";

3761 OS << "] for CtxI ";

3762

3764 OS << "'";

3765 I->print(OS);

3766 OS << "'";

3767 } else

3768 OS << "<>";

3769

3771 << '\n';

3772}

3773

3776

3777 for (const auto &DepAA : Deps) {

3778 auto *AA = DepAA.getPointer();

3779 OS << " updates ";

3780 AA->print(OS);

3781 }

3782

3783 OS << '\n';

3784}

3785

3793 OS << " [" << **Acc.getContent() << "]";

3794 else

3795 OS << " [ ]";

3796 }

3797 return OS;

3798}

3799

3800

3801

3802

3803

3804

3809 bool DeleteFns, bool IsModulePass) {

3810 if (Functions.empty())

3811 return false;

3812

3814 dbgs() << "[Attributor] Run on module with " << Functions.size()

3815 << " functions:\n";

3816 for (Function *Fn : Functions)

3817 dbgs() << " - " << Fn->getName() << "\n";

3818 });

3819

3820

3821

3823 AC.IsModulePass = IsModulePass;

3824 AC.DeleteFns = DeleteFns;

3825

3826

3828 IndirectCalleeTrackingMap;

3830 AC.IndirectCalleeSpecializationCallback =

3834 return false;

3835 auto &Set = IndirectCalleeTrackingMap[&CB];

3836 if (!Set)

3837 Set = std::make_unique<SmallPtrSet<Function *, 8>>();

3839 return Set->contains(&Callee);

3840 Set->insert(&Callee);

3841 return true;

3842 };

3843 }

3844

3846

3847

3850 if (A.isFunctionIPOAmendable(*F))

3852

3853

3854

3855

3856

3858 unsigned FunSize = Functions.size();

3859 for (unsigned u = 0; u < FunSize; u++) {

3861 if (F->isDeclaration() && F->isDefinitionExact() && F->use_empty() &&

3864 assert(NewF && "Could not internalize function.");

3865 Functions.insert(NewF);

3866

3867

3869 for (const Use &U : NewF->uses())

3871 auto *CallerF = CB->getCaller();

3873 }

3874 }

3875 }

3876 }

3877

3879 if (F->hasExactDefinition())

3880 NumFnWithExactDefinition++;

3881 else

3882 NumFnWithoutExactDefinition++;

3883

3884

3885

3886

3887 if (F->hasLocalLinkage()) {

3889 const auto *CB = dyn_cast(U.getUser());

3890 return CB && CB->isCallee(&U) &&

3891 Functions.count(const_cast<Function *>(CB->getCaller()));

3892 }))

3893 continue;

3894 }

3895

3896

3897

3898 A.identifyDefaultAbstractAttributes(*F);

3899 }

3900

3902

3903 LLVM_DEBUG(dbgs() << "[Attributor] Done with " << Functions.size()

3904 << " functions, result: " << Changed << ".\n");

3906}

3907

3913 bool IsModulePass) {

3914 if (Functions.empty())

3915 return false;

3916

3918 dbgs() << "[AttributorLight] Run on module with " << Functions.size()

3919 << " functions:\n";

3920 for (Function *Fn : Functions)

3921 dbgs() << " - " << Fn->getName() << "\n";

3922 });

3923

3924

3925

3927 AC.IsModulePass = IsModulePass;

3928 AC.DeleteFns = false;

3935 AC.Allowed = &Allowed;

3936 AC.UseLiveness = false;

3937

3939

3941 if (F->hasExactDefinition())

3942 NumFnWithExactDefinition++;

3943 else

3944 NumFnWithoutExactDefinition++;

3945

3946

3947

3948

3949 if (AC.UseLiveness && F->hasLocalLinkage()) {

3951 const auto *CB = dyn_cast(U.getUser());

3952 return CB && CB->isCallee(&U) &&

3953 Functions.count(const_cast<Function *>(CB->getCaller()));

3954 }))

3955 continue;

3956 }

3957

3958

3959

3960 A.identifyDefaultAbstractAttributes(*F);

3961 }

3962

3964

3966

3967

3969

3973

3974

3975

3976

3977 for (auto *U : Changed->users()) {

3979 if (Call->getCalledFunction() == Changed)

3980 FAM.invalidate(*Call->getFunction(), FuncPA);

3981 }

3982 }

3983 }

3984 }

3985 LLVM_DEBUG(dbgs() << "[Attributor] Done with " << Functions.size()

3986 << " functions, result: " << Changed << ".\n");

3988}

3989

3991

3993 static std::atomic CallTimes;

3994 std::string Prefix;

3995

3998 else

3999 Prefix = "dep_graph";

4000 std::string Filename =

4001 Prefix + "_" + std::to_string(CallTimes.load()) + ".dot";

4002

4003 outs() << "Dependency graph dump to " << Filename << ".\n";

4004

4005 std::error_code EC;

4006

4008 if (!EC)

4010

4011 CallTimes++;

4012}

4013

4018

4023

4027

4030 InformationCache InfoCache(M, AG, Allocator, nullptr);

4032 true, true)) {

4033

4035 }

4037}

4038

4046

4049 Functions.insert(&N.getFunction());

4050

4051 if (Functions.empty())

4053

4054 Module &M = *Functions.back()->getParent();

4058 InformationCache InfoCache(M, AG, Allocator, &Functions);

4060 false,

4061 false)) {

4062

4065 return PA;

4066 }

4068}

4069

4075

4079

4082 InformationCache InfoCache(M, AG, Allocator, nullptr);

4084 true)) {

4086

4088

4090 return PA;

4091 }

4093}

4094

4102

4105 Functions.insert(&N.getFunction());

4106

4107 if (Functions.empty())

4109

4110 Module &M = *Functions.back()->getParent();

4114 InformationCache InfoCache(M, AG, Allocator, &Functions);

4116 false)) {

4118

4120

4122 return PA;

4123 }

4125}

4126namespace llvm {

4127

4132

4135

4139

4141

4143};

4144

4145template <>

4156

4159

4162 std::string AAString;

4165 return AAString;

4166 }

4167};

4168

4169}

aarch64 falkor hwpf fix Falkor HW Prefetch Fix Late Phase

static unsigned getIntrinsicID(const SDNode *N)

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

amdgpu aa AMDGPU Address space based Alias Analysis Wrapper

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

Expand Atomic instructions

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

static cl::opt< bool > AllowShallowWrappers("attributor-allow-shallow-wrappers", cl::Hidden, cl::desc("Allow the Attributor to create shallow " "wrappers for non-exact definitions."), cl::init(false))

bool canMarkAsVisited(const User *Usr)

Definition Attributor.cpp:1764

#define VERBOSE_DEBUG_TYPE

Definition Attributor.cpp:66

static cl::opt< bool > EnableHeapToStack("enable-heap-to-stack-conversion", cl::init(true), cl::Hidden)

static cl::list< std::string > SeedAllowList("attributor-seed-allow-list", cl::Hidden, cl::desc("Comma separated list of attribute names that are " "allowed to be seeded."), cl::CommaSeparated)

static bool runAttributorOnFunctions(InformationCache &InfoCache, SetVector< Function * > &Functions, AnalysisGetter &AG, CallGraphUpdater &CGUpdater, bool DeleteFns, bool IsModulePass)

}

Definition Attributor.cpp:3805

static bool getPotentialCopiesOfMemoryValue(Attributor &A, Ty &I, SmallSetVector< Value *, 4 > &PotentialCopies, SmallSetVector< Instruction *, 4 > *PotentialValueOrigins, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact)

Definition Attributor.cpp:369

static bool runAttributorLightOnFunctions(InformationCache &InfoCache, SetVector< Function * > &Functions, AnalysisGetter &AG, CallGraphUpdater &CGUpdater, FunctionAnalysisManager &FAM, bool IsModulePass)

Definition Attributor.cpp:3908

static cl::opt< unsigned, true > MaxInitializationChainLengthX("attributor-max-initialization-chain-length", cl::Hidden, cl::desc("Maximal number of chained initializations (to avoid stack overflows)"), cl::location(MaxInitializationChainLength), cl::init(1024))

static cl::opt< unsigned > MaxSpecializationPerCB("attributor-max-specializations-per-call-base", cl::Hidden, cl::desc("Maximal number of callees specialized for " "a call base"), cl::init(UINT32_MAX))

static cl::opt< bool > SimplifyAllLoads("attributor-simplify-all-loads", cl::Hidden, cl::desc("Try to simplify all loads."), cl::init(true))

static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr, AttributeSet AttrSet, bool ForceReplace, AttrBuilder &AB)

Return true if the information provided by Attr was added to the attribute set AttrSet.

Definition Attributor.cpp:960

static cl::opt< bool > ViewDepGraph("attributor-view-dep-graph", cl::Hidden, cl::desc("View the dependency graph."), cl::init(false))

static bool isEqualOrWorse(const Attribute &New, const Attribute &Old)

Return true if New is equal or worse than Old.

Definition Attributor.cpp:950

static cl::opt< bool > AllowDeepWrapper("attributor-allow-deep-wrappers", cl::Hidden, cl::desc("Allow the Attributor to use IP information " "derived from non-exact functions via cloning"), cl::init(false))

static cl::opt< bool > DumpDepGraph("attributor-dump-dep-graph", cl::Hidden, cl::desc("Dump the dependency graph to dot files."), cl::init(false))

static cl::opt< bool > PrintCallGraph("attributor-print-call-graph", cl::Hidden, cl::desc("Print Attributor's internal call graph"), cl::init(false))

static bool checkForAllInstructionsImpl(Attributor *A, InformationCache::OpcodeInstMapTy &OpcodeInstMap, function_ref< bool(Instruction &)> Pred, const AbstractAttribute *QueryingAA, const AAIsDead *LivenessAA, ArrayRef< unsigned > Opcodes, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, bool CheckPotentiallyDead=false)

Definition Attributor.cpp:2022

static cl::opt< bool > PrintDependencies("attributor-print-dep", cl::Hidden, cl::desc("Print attribute dependencies"), cl::init(false))

static bool isAssumedReadOnlyOrReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool RequireReadNone, bool &IsKnown)

Definition Attributor.cpp:613

static cl::opt< std::string > DepGraphDotFileNamePrefix("attributor-depgraph-dot-filename-prefix", cl::Hidden, cl::desc("The prefix used for the CallGraph dot file names."))

static cl::opt< bool > AnnotateDeclarationCallSites("attributor-annotate-decl-cs", cl::Hidden, cl::desc("Annotate call sites of function declarations."), cl::init(false))

static cl::opt< unsigned > SetFixpointIterations("attributor-max-iterations", cl::Hidden, cl::desc("Maximal number of fixpoint iterations."), cl::init(32))

static cl::list< std::string > FunctionSeedAllowList("attributor-function-seed-allow-list", cl::Hidden, cl::desc("Comma separated list of function names that are " "allowed to be seeded."), cl::CommaSeparated)

static cl::opt< bool > EnableCallSiteSpecific("attributor-enable-call-site-specific-deduction", cl::Hidden, cl::desc("Allow the Attributor to do call site specific analysis"), cl::init(false))

static cl::opt< bool > CloseWorldAssumption("attributor-assume-closed-world", cl::Hidden, cl::desc("Should a closed world be assumed, or not. Default if not set."))

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

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...

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

This file provides an implementation of debug counters.

#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)

Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

uint64_t IntrinsicInst * II

FunctionAnalysisManager FAM

This file defines the PointerIntPair class.

static StringRef getName(Value *V)

Remove Loads Into Fake Uses

This file defines the SmallPtrSet class.

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

#define STATISTIC(VARNAME, DESC)

#define DEBUG_WITH_TYPE(TYPE,...)

DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.

void print(OutputBuffer &OB) const

static const fltSemantics & IEEEsingle()

Class for arbitrary precision integers.

CallBase * getInstruction() const

Return the underlying instruction.

bool isCallbackCall() const

Return true if this ACS represents a callback call.

const Use & getCalleeUseForCallback() const

Return the use of the callee value in the underlying instruction.

static LLVM_ABI void getCallbackUses(const CallBase &CB, SmallVectorImpl< const Use * > &CallbackUses)

Add operand uses of CB that represent callback uses into CallbackUses.

bool isCallee(Value::const_user_iterator UI) const

Return true if UI is the use that defines the callee of this ACS.

Value * getCallArgOperand(Argument &Arg) const

Return the operand of the underlying instruction associated with Arg.

int getCallArgOperandNo(Argument &Arg) const

Return the operand index of the underlying instruction associated with Arg.

unsigned getNumArgOperands() const

Return the number of parameters of the callee.

Function * getCalledFunction() const

Return the function being called if this is a direct call, otherwise return null (if it's an indirect...

This templated class represents "all analyses that operate over " (e....

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

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

This class represents an incoming formal argument to a Function.

const Function * getParent() const

unsigned getArgNo() const

Return the index of this formal argument in its containing function.

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

size_t size() const

size - Get the array size.

bool empty() const

empty - Check if the array is empty.

This class stores enough information to efficiently remove some attributes from an existing AttrBuild...

This class holds the attributes for a particular argument, parameter, function, or return value.

LLVM_ABI MemoryEffects getMemoryEffects() const

LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const

Return true if the attribute exists in this set.

LLVM_ABI Attribute getAttribute(Attribute::AttrKind Kind) const

Return the attribute object.

Functions, function parameters, and return types can have attributes to indicate how they should be t...

LLVM_ABI bool isStringAttribute() const

Return true if the attribute is a string (target-dependent) attribute.

LLVM_ABI bool isEnumAttribute() const

Return true if the attribute is an Attribute::AttrKind type.

LLVM_ABI bool isIntAttribute() const

Return true if the attribute is an integer attribute.

LLVM_ABI uint64_t getValueAsInt() const

Return the attribute's value as an integer.

LLVM_ABI bool isConstantRangeAttribute() const

Return true if the attribute is a ConstantRange attribute.

LLVM_ABI StringRef getKindAsString() const

Return the attribute's kind as a string.

static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)

Return a uniquified Attribute object.

LLVM_ABI Attribute::AttrKind getKindAsEnum() const

Return the attribute's kind as an enum (Attribute::AttrKind).

LLVM_ABI MemoryEffects getMemoryEffects() const

Returns memory effects.

LLVM_ABI StringRef getValueAsString() const

Return the attribute's value as a string.

AttrKind

This enumeration lists the attributes that can be associated with parameters, function results,...

@ None

No attributes have been set.

LLVM Basic Block Representation.

const Function * getParent() const

Return the enclosing method, or null if none.

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

const Instruction & front() const

LLVM_ABI const BasicBlock * getUniquePredecessor() const

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

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

Represents analyses that only rely on functions' control flow.

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

void setCallingConv(CallingConv::ID CC)

void addFnAttr(Attribute::AttrKind Kind)

Adds the attribute to the function.

LLVM_ABI void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const

Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.

CallingConv::ID getCallingConv() const

LLVM_ABI bool isMustTailCall() const

Tests if this call site must be tail call optimized.

Value * getCalledOperand() const

void setAttributes(AttributeList A)

Set the attributes for this call.

unsigned arg_size() const

AttributeList getAttributes() const

Return the attributes for this call.

LLVM_ABI Function * getCaller()

Helper to get the caller (the parent function).

Wrapper to unify "old style" CallGraph and "new style" LazyCallGraph.

LLVM_ABI void replaceFunctionWith(Function &OldFn, Function &NewFn)

Replace OldFn in the call graph (and SCC) with NewFn.

LLVM_ABI void reanalyzeFunction(Function &Fn)

After an CGSCC pass changes a function in ways that affect the call graph, this method can be called ...

void initialize(LazyCallGraph &LCG, LazyCallGraph::SCC &SCC, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR)

Initializers for usage outside of a CGSCC pass, inside a CGSCC pass in the old and new pass manager (...

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

static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

void setTailCall(bool IsTc=true)

A constant value that is initialized with an expression using other constant values.

static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)

Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.

static LLVM_ABI Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)

LLVM_ABI void print(raw_ostream &OS) const

Print out the bounds to a stream.

This is an important base class in LLVM.

static LLVM_ABI Constant * getNullValue(Type *Ty)

Constructor to create a '0' constant of arbitrary type.

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

static bool shouldExecute(CounterInfo &Counter)

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

Implements a dense probed hash-table based set.

Analysis pass which computes a DominatorTree.

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

A proxy from a FunctionAnalysisManager to an SCC.

Class to represent function types.

static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)

This static method is the primary way of constructing a FunctionType.

void setSubprogram(DISubprogram *SP)

Set the attached subprogram.

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

void splice(Function::iterator ToIt, Function *FromF)

Transfer all blocks from FromF to this function at ToIt.

const BasicBlock & getEntryBlock() const

FunctionType * getFunctionType() const

Returns the FunctionType for me.

iterator_range< arg_iterator > args()

DISubprogram * getSubprogram() const

Get the attached subprogram.

MemoryEffects getMemoryEffects() const

bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const

check if an attributes is in the list of attributes.

AttributeList getAttributes() const

Return the attribute list for this Function.

void setAttributes(AttributeList Attrs)

Set the attribute list for this Function.

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

Type * getReturnType() const

Returns the type of the ret val.

void setMemoryEffects(MemoryEffects ME)

Argument * getArg(unsigned i) const

bool isVarArg() const

isVarArg - Return true if this function takes a variable number of arguments.

void copyAttributesFrom(const Function *Src)

copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...

bool hasMetadata() const

Return true if this value has any metadata attached to it.

LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)

Add a metadata attachment.

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

bool hasLocalLinkage() const

void setLinkage(LinkageTypes LT)

unsigned getAddressSpace() const

Module * getParent()

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

void setDSOLocal(bool Local)

PointerType * getType() const

Global values are always pointers.

@ DefaultVisibility

The GV is visible.

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.

@ PrivateLinkage

Like Internal, but omit from symbol table.

@ InternalLinkage

Rename collisions when linking (static functions).

LLVM_ABI InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

LLVM_ABI const Function * getFunction() const

Return the function this instruction belongs to.

LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())

Copy metadata from SrcInst to this instruction.

static InvokeInst * Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef< Value * > Args, const Twine &NameStr, InsertPosition InsertBefore=nullptr)

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

A node in the call graph.

An SCC of the call graph.

A lazily constructed view of the call graph of a module.

An instruction for reading from memory.

This is the common base class for memset/memcpy/memmove.

This class wraps the llvm.memcpy/memmove intrinsics.

static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)

bool doesAccessArgPointees() const

Whether this function may access argument memory.

static LLVM_ABI MemoryLocation getForSource(const MemTransferInst *MTI)

Return a location representing the source of a memory transfer.

static LLVM_ABI MemoryLocation getForDest(const MemIntrinsic *MI)

Return a location representing the destination of a memory set or transfer.

static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)

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

const FunctionListType & getFunctionList() const

Get the Module's list of functions (constant).

PointerIntPair - This class implements a pair of a pointer and small integer.

void * getOpaqueValue() const

PointerTy getPointer() const

static LLVM_ABI PoisonValue * get(Type *T)

Static factory methods - Return an 'poison' object of the specified 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.

PreservedAnalyses & preserveSet()

Mark an analysis set as preserved.

PreservedAnalyses & preserve()

Mark an analysis as preserved.

Return a value (possibly void), from a function.

static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)

A vector that has set insertion semantics.

ArrayRef< value_type > getArrayRef() const

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.

void insert_range(Range &&R)

size_type count(const_arg_type key) const

Count the number of elements of a given key in the SetVector.

typename vector_type::const_iterator iterator

void clear()

Completely clear the SetVector.

iterator begin()

Get an iterator to the beginning of the SetVector.

bool insert(const value_type &X)

Insert a new element into the SetVector.

A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...

size_type count(ConstPtrType Ptr) const

count - Return 1 if the specified pointer is in the set, 0 otherwise.

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.

A SetVector that performs no allocations if smaller than a certain size.

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

void reserve(size_type N)

void append(ItTy in_start, ItTy in_end)

Add the specified range to the end of the SmallVector.

void push_back(const T &Elt)

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

An instruction for storing to memory.

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

A visitor class for IR positions.

LLVM_ABI SubsumingPositionIterator(const IRPosition &IRP)

Definition Attributor.cpp:1272

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

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

Triple - Helper class for working with autoconf configuration names.

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

bool isPointerTy() const

True if this is an instance of PointerType.

bool isVoidTy() const

Return true if this is 'void'.

static LLVM_ABI UndefValue * get(Type *T)

Static factory methods - Return an 'undef' object of the specified type.

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.

LLVM_ABI void replaceAllUsesWith(Value *V)

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

LLVM_ABI const Value * stripPointerCasts() const

Strip off pointer casts, all-zero GEPs and address space casts.

LLVM_ABI LLVMContext & getContext() const

All values hold a context through their type.

iterator_range< use_iterator > uses()

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.

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

const ParentTy * getParent() const

self_iterator getIterator()

NodeTy * getNextNode()

Get the next node, or nullptr for the list tail.

iterator insert(iterator where, pointer New)

A raw_ostream that writes to a file descriptor.

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

A raw_ostream that writes to an std::string.

#define llvm_unreachable(msg)

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

Abstract Attribute helper functions.

LLVM_ABI bool isAssumedReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)

Return true if IRP is readnone.

Definition Attributor.cpp:658

LLVM_ABI bool isAssumedReadOnly(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)

Return true if IRP is readonly.

Definition Attributor.cpp:653

LLVM_ABI std::optional< Value * > combineOptionalValuesInAAValueLatice(const std::optional< Value * > &A, const std::optional< Value * > &B, Type *Ty)

Return the combination of A and B such that the result is a possible value of both.

Definition Attributor.cpp:344

LLVM_ABI bool isValidAtPosition(const ValueAndContext &VAC, InformationCache &InfoCache)

Return true if the value of VAC is a valid at the position of VAC, that is a constant,...

Definition Attributor.cpp:295

LLVM_ABI bool isAssumedThreadLocalObject(Attributor &A, Value &Obj, const AbstractAttribute &QueryingAA)

Return true if Obj is assumed to be a thread local object.

Definition Attributor.cpp:840

LLVM_ABI bool isDynamicallyUnique(Attributor &A, const AbstractAttribute &QueryingAA, const Value &V, bool ForAnalysisOnly=true)

Return true if V is dynamically unique, that is, there are no two "instances" of V at runtime with di...

Definition Attributor.cpp:231

LLVM_ABI bool getPotentialCopiesOfStoredValue(Attributor &A, StoreInst &SI, SmallSetVector< Value *, 4 > &PotentialCopies, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)

Collect all potential values of the one stored by SI into PotentialCopies.

Definition Attributor.cpp:604

LLVM_ABI bool isPotentiallyAffectedByBarrier(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)

Return true if I is potentially affected by a barrier.

Definition Attributor.cpp:894

SmallPtrSet< Instruction *, 4 > InstExclusionSetTy

LLVM_ABI bool isGPU(const Module &M)

Return true iff M target a GPU (and we can use GPU AS reasoning).

Definition Attributor.cpp:200

LLVM_ABI Constant * getInitialValueForObj(Attributor &A, const AbstractAttribute &QueryingAA, Value &Obj, Type &Ty, const TargetLibraryInfo *TLI, const DataLayout &DL, RangeTy *RangePtr=nullptr)

Return the initial value of Obj with type Ty if that is a constant.

Definition Attributor.cpp:242

ValueScope

Flags to distinguish intra-procedural queries from potentially inter-procedural queries.

LLVM_ABI bool isValidInScope(const Value &V, const Function *Scope)

Return true if V is a valid value in Scope, that is a constant or an instruction/argument of Scope.

Definition Attributor.cpp:285

LLVM_ABI bool isPotentiallyReachable(Attributor &A, const Instruction &FromI, const Instruction &ToI, const AbstractAttribute &QueryingAA, const AA::InstExclusionSetTy *ExclusionSet=nullptr, std::function< bool(const Function &F)> GoBackwardsCB=nullptr)

Return true if ToI is potentially reachable from FromI without running into any instruction in Exclus...

Definition Attributor.cpp:821

LLVM_ABI bool isNoSyncInst(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)

Return true if I is a nosync instruction.

Definition Attributor.cpp:205

bool hasAssumedIRAttr(Attributor &A, const AbstractAttribute *QueryingAA, const IRPosition &IRP, DepClassTy DepClass, bool &IsKnown, bool IgnoreSubsumingPositions=false, const AAType **AAPtr=nullptr)

Helper to avoid creating an AA for IR Attributes that might already be set.

LLVM_ABI bool getPotentiallyLoadedValues(Attributor &A, LoadInst &LI, SmallSetVector< Value *, 4 > &PotentialValues, SmallSetVector< Instruction *, 4 > &PotentialValueOrigins, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)

Collect all potential values LI could read into PotentialValues.

Definition Attributor.cpp:594

LLVM_ABI Value * getWithType(Value &V, Type &Ty)

Try to convert V to type Ty without introducing new instructions.

Definition Attributor.cpp:321

constexpr char Attrs[]

Key for Kernel::Metadata::mAttrs.

@ C

The default llvm calling convention, compatible with C.

@ BasicBlock

Various leaf nodes.

initializer< Ty > init(const Ty &Val)

LocationClass< Ty > location(Ty &L)

@ Assume

Do not drop type tests (default).

DiagnosticInfoOptimizationBase::Argument NV

NodeAddr< UseNode * > Use

friend class Instruction

Iterator for Instructions in a `BasicBlock.

@ OF_TextWithCRLF

The file should be opened in text mode and use a carriage linefeed '\r '.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

bool all_of(R &&range, UnaryPredicate P)

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

LLVM_ABI Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)

If this is a call to an allocation function that initializes memory to a fixed value,...

Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)

LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())

If the specified value is a trivially dead instruction, delete it.

LLVM_ABI unsigned MaxInitializationChainLength

The value passed to the line option that defines the maximal initialization chain length.

Definition Attributor.cpp:109

LLVM_ABI bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions=false, const TargetLibraryInfo *TLI=nullptr, DomTreeUpdater *DTU=nullptr)

If a terminator instruction is predicated on a constant value, convert it into an unconditional branc...

APInt operator&(APInt a, const APInt &b)

LLVM_ABI void detachDeadBlocks(ArrayRef< BasicBlock * > BBs, SmallVectorImpl< DominatorTree::UpdateType > *Updates, bool KeepOneInputPHIs=false)

Replace contents of every block in BBs with single unreachable instruction.

decltype(auto) dyn_cast(const From &Val)

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

DenseMap< AssumeInst *, MinMax > Assume2KnowledgeMap

A mapping from intrinsics (=llvm.assume calls) to a value range (=knowledge) that is encoded in them.

LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)

Check a function for errors, useful for use when debugging a pass.

LLVM_ABI CallInst * changeToCall(InvokeInst *II, DomTreeUpdater *DTU=nullptr)

This function converts the specified invoke into a normal call.

LLVM_ABI raw_fd_ostream & outs()

This returns a reference to a raw_fd_ostream for standard output.

auto dyn_cast_if_present(const Y &Val)

dyn_cast_if_present - Functionally identical to dyn_cast, except that a null (or none in the case ...

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy

Provide the FunctionAnalysisManager to Module proxy.

LLVM_ABI bool isNoAliasCall(const Value *V)

Return true if this pointer is returned by a noalias function.

MemoryEffectsBase< IRMemLocation > MemoryEffects

Summary of how a function affects memory in the program.

raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")

bool isa_and_nonnull(const Y &Val)

AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager

The CGSCC analysis manager.

LLVM_ABI InlineResult isInlineViable(Function &Callee)

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

auto dyn_cast_or_null(const Y &Val)

bool any_of(R &&range, UnaryPredicate P)

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

LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)

Return true if the result produced by the instruction is not used, and the instruction will return.

LLVM_ABI Constant * ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty, const DataLayout &DL)

If C is a uniform value where all bits are the same (either all zero, all ones, all undef or all pois...

PotentialValuesState< std::pair< AA::ValueAndContext, AA::ValueScope > > PotentialLLVMValuesState

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)

Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...

LLVM_ABI raw_ostream & dbgs()

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

LLVM_ABI bool AreStatisticsEnabled()

Check if statistics are enabled.

LLVM_ABI Constant * ConstantFoldLoadFromConst(Constant *C, Type *Ty, const APInt &Offset, const DataLayout &DL)

Extract value of C at the given Offset reinterpreted as Ty.

class LLVM_GSL_OWNER SmallVector

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

bool isa(const From &Val)

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

@ Success

The lock was released successfully.

LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)

Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

LLVM_ABI BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)

This method introduces at least one new basic block into the function and moves some of the predecess...

PotentialValuesState< APInt > PotentialConstantIntValuesState

bool operator&=(SparseBitVector< ElementSize > *LHS, const SparseBitVector< ElementSize > &RHS)

DWARFExpression::Operation Op

void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)

ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, then cleanup.

raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)

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

ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy

LLVM_ABI void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, CloneFunctionChangeType Changes, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)

Clone OldFunc into NewFunc, transforming the old arguments into references to VMap values.

decltype(auto) cast(const From &Val)

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

void erase_if(Container &C, UnaryPredicate P)

Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...

iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)

LLVM_ABI bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI)

Tests if a value is a call or invoke to a library function that allocates or reallocates memory (eith...

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

Returns true if Element is found in Range.

LLVM_ABI void fillMapFromAssume(AssumeInst &Assume, RetainedKnowledgeMap &Result)

Insert into the map all the informations contained in the operand bundles of the llvm....

bool operator|=(SparseBitVector< ElementSize > &LHS, const SparseBitVector< ElementSize > *RHS)

LLVM_ABI Constant * ConstantFoldCastInstruction(unsigned opcode, Constant *V, Type *DestTy)

@ OPTIONAL

The target may be valid if the source is not.

@ NONE

Do not track a dependence between source and target.

@ REQUIRED

The target cannot be valid if the source is not.

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.

APInt operator|(APInt a, const APInt &b)

BumpPtrAllocatorImpl<> BumpPtrAllocator

The standard BumpPtrAllocator which just uses the default template parameters.

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.

LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)

Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...

static LLVM_ABI const char ID

Unique ID (due to the unique address)

DepSetTy Deps

Set of dependency graph nodes which should be updated if this one is updated.

PointerIntPair< AADepGraphNode *, 1 > DepTy

The data structure for the dependency graph.

LLVM_ABI void viewGraph()

Definition Attributor.cpp:3990

AADepGraphNode SyntheticRoot

There is no root node for the dependency graph.

LLVM_ABI void print()

Print dependency graph.

Definition Attributor.cpp:4014

LLVM_ABI void dumpGraph()

Dump graph to file.

Definition Attributor.cpp:3992

AADepGraphNode * GetEntryNode()

An abstract interface to track if a value leaves it's defining function instance.

bool isAssumedUniqueForAnalysis() const

Return true if we assume that the underlying value is unique in its scope wrt.

An abstract Attribute for computing reachability between functions.

static LLVM_ABI const char ID

Unique ID (due to the unique address)

An abstract interface to determine reachability of point A to B.

static LLVM_ABI const char ID

Unique ID (due to the unique address)

An abstract interface for liveness abstract attribute.

virtual bool isKnownDead() const =0

Returns true if the underlying value is known dead.

virtual bool isAssumedDead() const =0

The query functions are protected such that other attributes need to go through the Attributor interf...

virtual bool isRemovableStore() const

Return true if the underlying value is a store that is known to be removable.

static bool mayCatchAsynchronousExceptions(const Function &F)

Determine if F might catch asynchronous exceptions.

An abstract interface for memory access kind related attributes (readnone/readonly/writeonly).

static LLVM_ABI const char ID

Unique ID (due to the unique address)

An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...

static LLVM_ABI const char ID

Unique ID (due to the unique address)

static LLVM_ABI const char ID

Unique ID (due to the unique address)

static LLVM_ABI const char ID

Unique ID (due to the unique address)

static LLVM_ABI const char ID

Unique ID (due to the unique address)

static LLVM_ABI const char ID

Unique ID (due to the unique address)

static LLVM_ABI const char ID

Unique ID (due to the unique address)

static LLVM_ABI const char ID

Unique ID (due to the unique address)

static LLVM_ABI const char ID

Unique ID (due to the unique address)

static LLVM_ABI bool isNonRelaxedAtomic(const Instruction *I)

Helper function used to determine whether an instruction is non-relaxed atomic.

static LLVM_ABI bool isNoSyncIntrinsic(const Instruction *I)

Helper function specific for intrinsics which are potentially volatile.

static LLVM_ABI const char ID

Unique ID (due to the unique address)

static LLVM_ABI const char ID

Unique ID (due to the unique address)

bool isWrittenValueUnknown() const

Return true if the value written cannot be determined at all.

std::optional< Value * > getContent() const

Return the written value which can be llvm::null if it is not yet determined.

bool isWriteOrAssumption() const

Return true if this is a write access.

bool isRead() const

Return true if this is a read access.

Value * getWrittenValue() const

Return the value writen, if any.

Instruction * getLocalInst() const

Return the instruction that causes the access with respect to the local scope of the associated attri...

Instruction * getRemoteInst() const

Return the actual instruction that causes the access.

bool isWrittenValueYetUndetermined() const

Return true if the value written is not known yet.

AccessKind getKind() const

Return the access kind.

An abstract interface for struct information.

static LLVM_ABI Value * getSingleValue(Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP, SmallVectorImpl< AA::ValueAndContext > &Values)

Extract the single value in Values if any.

An abstract attribute for getting all assumption underlying objects.

static LLVM_ABI const char ID

Unique ID (due to the unique address)

static LLVM_ABI const char ID

Unique ID (due to the unique address)

Helper to represent an access offset and size, with logic to deal with uncertainty and check for over...

bool offsetOrSizeAreUnknown() const

Return true if offset or size are unknown.

const Instruction * getCtxI() const

Base struct for all "concrete attribute" deductions.

ChangeStatus update(Attributor &A)

Hook for the Attributor to trigger an update of the internal state.

Definition Attributor.cpp:1061

friend struct Attributor

}

virtual void printWithDeps(raw_ostream &OS) const

Definition Attributor.cpp:3774

void print(raw_ostream &OS) const

Helper functions, for debug purposes only.

virtual StateType & getState()=0

Return the internal abstract state for inspection.

virtual const std::string getAsStr(Attributor *A) const =0

This function should return the "summarized" assumed state as string.

virtual ChangeStatus updateImpl(Attributor &A)=0

The actual update/transfer function which has to be implemented by the derived classes.

const IRPosition & getIRPosition() const

Return an IR position, see struct IRPosition.

An interface to query the internal state of an abstract attribute.

virtual ChangeStatus indicatePessimisticFixpoint()=0

Indicate that the abstract state should converge to the pessimistic state.

virtual bool isAtFixpoint() const =0

Return if this abstract state is fixed, thus does not need to be updated if information changes as it...

virtual bool isValidState() const =0

Return if this abstract state is in a valid state.

Wrapper for FunctionAnalysisManager.

LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)

Definition Attributor.cpp:4039

void populateAll() const

Force populate the entire call graph.

Configuration for the Attributor.

std::optional< unsigned > MaxFixpointIterations

Maximum number of iterations to run until fixpoint.

LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)

Definition Attributor.cpp:4095

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

Definition Attributor.cpp:4070

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

Definition Attributor.cpp:4019

Helper struct used in the communication between an abstract attribute (AA) that wants to change the s...

std::function< void( const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy

Callee repair callback type.

std::function< void(const ArgumentReplacementInfo &, AbstractCallSite, SmallVectorImpl< Value * > &)> ACSRepairCBTy

Abstract call site (ACS) repair callback type.

The fixpoint analysis framework that orchestrates the attribute deduction.

LLVM_ABI bool registerFunctionSignatureRewrite(Argument &Arg, ArrayRef< Type * > ReplacementTypes, ArgumentReplacementInfo::CalleeRepairCBTy &&CalleeRepairCB, ArgumentReplacementInfo::ACSRepairCBTy &&ACSRepairCB)

Register a rewrite for a function signature.

Definition Attributor.cpp:2923

LLVM_ABI ~Attributor()

Definition Attributor.cpp:1543

LLVM_ABI bool checkForAllCallees(function_ref< bool(ArrayRef< const Function * > Callees)> Pred, const AbstractAttribute &QueryingAA, const CallBase &CB)

Check Pred on all potential Callees of CB.

Definition Attributor.cpp:1749

bool isModulePass() const

Return true if this is a module pass, false otherwise.

LLVM_ABI bool isValidFunctionSignatureRewrite(Argument &Arg, ArrayRef< Type * > ReplacementTypes)

Check if we can rewrite a function signature.

Definition Attributor.cpp:2854

static LLVM_ABI bool isInternalizable(Function &F)

Returns true if the function F can be internalized.

Definition Attributor.cpp:2773

LLVM_ABI ChangeStatus removeAttrs(const IRPosition &IRP, ArrayRef< Attribute::AttrKind > AttrKinds)

Remove all AttrKinds attached to IRP.

Definition Attributor.cpp:1232

void emitRemark(Instruction *I, StringRef RemarkName, RemarkCallBack &&RemarkCB) const

Emit a remark generically.

bool isRunOn(Function &Fn) const

Return true if we derive attributes for Fn.

LLVM_ABI bool isAssumedDead(const AbstractAttribute &AA, const AAIsDead *LivenessAA, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, DepClassTy DepClass=DepClassTy::OPTIONAL)

Return true if AA (or its context instruction) is assumed dead.

Definition Attributor.cpp:1552

LLVM_ABI bool checkForAllInstructions(function_ref< bool(Instruction &)> Pred, const Function *Fn, const AbstractAttribute *QueryingAA, ArrayRef< unsigned > Opcodes, bool &UsedAssumedInformation, bool CheckBBLivenessOnly=false, bool CheckPotentiallyDead=false)

Check Pred on all instructions in Fn with an opcode present in Opcodes.

Definition Attributor.cpp:2052

LLVM_ABI void recordDependence(const AbstractAttribute &FromAA, const AbstractAttribute &ToAA, DepClassTy DepClass)

Explicitly record a dependence from FromAA to ToAA, that is if FromAA changes ToAA should be updated ...

Definition Attributor.cpp:3303

static LLVM_ABI void createShallowWrapper(Function &F)

Create a shallow wrapper for F such that F has internal linkage afterwards.

Definition Attributor.cpp:2726

const AAType * getAAFor(const AbstractAttribute &QueryingAA, const IRPosition &IRP, DepClassTy DepClass)

Lookup an abstract attribute of type AAType at position IRP.

std::optional< Value * > getAssumedSimplified(const IRPosition &IRP, const AbstractAttribute &AA, bool &UsedAssumedInformation, AA::ValueScope S)

If V is assumed simplified, return it, if it is unclear yet, return std::nullopt, otherwise return nu...

static LLVM_ABI Function * internalizeFunction(Function &F, bool Force=false)

Make another copy of the function F such that the copied version has internal linkage afterwards and ...

Definition Attributor.cpp:2780

bool isFunctionIPOAmendable(const Function &F)

Determine whether the function F is IPO amendable.

const AAType * getOrCreateAAFor(IRPosition IRP, const AbstractAttribute *QueryingAA, DepClassTy DepClass, bool ForceUpdate=false, bool UpdateAfterInit=true)

The version of getAAFor that allows to omit a querying abstract attribute.

LLVM_ABI bool checkForAllReadWriteInstructions(function_ref< bool(Instruction &)> Pred, AbstractAttribute &QueryingAA, bool &UsedAssumedInformation)

Check Pred on all Read/Write instructions.

Definition Attributor.cpp:2091

LLVM_ABI bool checkForAllReturnedValues(function_ref< bool(Value &)> Pred, const AbstractAttribute &QueryingAA, AA::ValueScope S=AA::ValueScope::Intraprocedural, bool RecurseForSelectAndPHI=true)

Check Pred on all values potentially returned by the function associated with QueryingAA.

Definition Attributor.cpp:2000

LLVM_ABI bool isClosedWorldModule() const

Return true if the module contains the whole world, thus, no outside functions exist.

Definition Attributor.cpp:3658

LLVM_ABI std::optional< Constant * > getAssumedConstant(const IRPosition &IRP, const AbstractAttribute &AA, bool &UsedAssumedInformation)

If IRP is assumed to be a constant, return it, if it is unclear yet, return std::nullopt,...

Definition Attributor.cpp:1408

LLVM_ABI Attributor(SetVector< Function * > &Functions, InformationCache &InfoCache, AttributorConfig Configuration)

Constructor.

Definition Attributor.cpp:1076

LLVM_ABI void getAttrs(const IRPosition &IRP, ArrayRef< Attribute::AttrKind > AKs, SmallVectorImpl< Attribute > &Attrs, bool IgnoreSubsumingPositions=false)

Return the attributes of any kind in AKs existing in the IR at a position that will affect this one.

Definition Attributor.cpp:1209

InformationCache & getInfoCache()

Return the internal information cache.

LLVM_ABI std::optional< Value * > translateArgumentToCallSiteContent(std::optional< Value * > V, CallBase &CB, const AbstractAttribute &AA, bool &UsedAssumedInformation)

Translate V from the callee context into the call site context.

Definition Attributor.cpp:1526

LLVM_ABI bool checkForAllUses(function_ref< bool(const Use &, bool &)> Pred, const AbstractAttribute &QueryingAA, const Value &V, bool CheckBBLivenessOnly=false, DepClassTy LivenessDepClass=DepClassTy::OPTIONAL, bool IgnoreDroppableUses=true, function_ref< bool(const Use &OldU, const Use &NewU)> EquivalentUseCB=nullptr)

Check Pred on all (transitive) uses of V.

Definition Attributor.cpp:1768

LLVM_ABI ChangeStatus manifestAttrs(const IRPosition &IRP, ArrayRef< Attribute > DeducedAttrs, bool ForceReplace=false)

Attach DeducedAttrs to IRP, if ForceReplace is set we do this even if the same attribute kind was alr...

Definition Attributor.cpp:1257

LLVM_ABI bool hasAttr(const IRPosition &IRP, ArrayRef< Attribute::AttrKind > AKs, bool IgnoreSubsumingPositions=false, Attribute::AttrKind ImpliedAttributeKind=Attribute::None)

Return true if any kind in AKs existing in the IR at a position that will affect this one.

Definition Attributor.cpp:1167

LLVM_ABI void registerForUpdate(AbstractAttribute &AA)

Allows a query AA to request an update if a new query was received.

Definition Attributor.cpp:2260

std::function< bool(Attributor &, const AbstractAttribute *)> VirtualUseCallbackTy

LLVM_ABI void identifyDefaultAbstractAttributes(Function &F)

Determine opportunities to derive 'default' attributes in F and create abstract attribute objects for...

Definition Attributor.cpp:3342

LLVM_ABI bool getAssumedSimplifiedValues(const IRPosition &IRP, const AbstractAttribute *AA, SmallVectorImpl< AA::ValueAndContext > &Values, AA::ValueScope S, bool &UsedAssumedInformation, bool RecurseForSelectAndPHI=true)

Try to simplify IRP and in the scope S.

Definition Attributor.cpp:1460

BumpPtrAllocator & Allocator

The allocator used to allocate memory, e.g. for AbstractAttributes.

LLVM_ABI ChangeStatus run()

Run the analyses until a fixpoint is reached or enforced (timeout).

Definition Attributor.cpp:2647

static LLVM_ABI bool internalizeFunctions(SmallPtrSetImpl< Function * > &FnSet, DenseMap< Function *, Function * > &FnMap)

Make copies of each function in the set FnSet such that the copied version has internal linkage after...

Definition Attributor.cpp:2793

LLVM_ABI bool checkForAllCallSites(function_ref< bool(AbstractCallSite)> Pred, const AbstractAttribute &QueryingAA, bool RequireAllCallSites, bool &UsedAssumedInformation)

Check Pred on all function call sites.

Definition Attributor.cpp:1875

LLVM_ABI bool getAttrsFromAssumes(const IRPosition &IRP, Attribute::AttrKind AK, SmallVectorImpl< Attribute > &Attrs)

Return the attributes of kind AK existing in the IR as operand bundles of an llvm....

Definition Attributor.cpp:1093

bool isKnown(base_t BitsEncoding=BestState) const

Return true if the bits set in BitsEncoding are "known bits".

Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...

static std::string getNodeLabel(const AADepGraphNode *Node, const AADepGraph *DG)

Definition Attributor.cpp:4160

DOTGraphTraits(bool isSimple=false)

Definition Attributor.cpp:4158

DefaultDOTGraphTraits(bool simple=false)

Represent subnormal handling kind for floating point instruction inputs and outputs.

@ Dynamic

Denormals have unknown treatment.

An information struct used to provide DenseMap with the various necessary components for a given valu...

static NodeRef DepGetVal(const DepTy &DT)

Definition Attributor.cpp:4134

PointerIntPair< AADepGraphNode *, 1 > DepTy

Definition Attributor.cpp:4130

static ChildIteratorType child_end(NodeRef N)

Definition Attributor.cpp:4142

static NodeRef getEntryNode(AADepGraphNode *DGN)

Definition Attributor.cpp:4133

mapped_iterator< AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)> ChildIteratorType

Definition Attributor.cpp:4136

PointerIntPair< AADepGraphNode *, 1 > EdgeRef

Definition Attributor.cpp:4131

static ChildIteratorType child_begin(NodeRef N)

Definition Attributor.cpp:4140

AADepGraphNode * NodeRef

Definition Attributor.cpp:4129

AADepGraphNode::DepSetTy::iterator ChildEdgeIteratorType

Definition Attributor.cpp:4138

static NodeRef getEntryNode(AADepGraph *DG)

Definition Attributor.cpp:4147

mapped_iterator< AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)> nodes_iterator

Definition Attributor.cpp:4149

static nodes_iterator nodes_begin(AADepGraph *DG)

Definition Attributor.cpp:4152

static nodes_iterator nodes_end(AADepGraph *DG)

Definition Attributor.cpp:4154

typename AADepGraph *::UnknownGraphTypeError NodeRef

Helper to describe and deal with positions in the LLVM-IR.

Function * getAssociatedFunction() const

Return the associated function, if any.

void setAttrList(const AttributeList &AttrList) const

Update the attributes associated with this function or call site scope.

unsigned getAttrIdx() const

Return the index in the attribute list for this position.

bool hasCallBaseContext() const

Check if the position has any call base context.

static const IRPosition callsite_returned(const CallBase &CB)

Create a position describing the returned value of CB.

static const IRPosition returned(const Function &F, const CallBaseContext *CBContext=nullptr)

Create a position describing the returned value of F.

LLVM_ABI Argument * getAssociatedArgument() const

Return the associated argument, if any.

Definition Attributor.cpp:1007

static const IRPosition value(const Value &V, const CallBaseContext *CBContext=nullptr)

Create a position describing the value of V.

AttributeList getAttrList() const

Return the attributes associated with this function or call site scope.

static const IRPosition inst(const Instruction &I, const CallBaseContext *CBContext=nullptr)

Create a position describing the instruction I.

static const IRPosition callsite_argument(const CallBase &CB, unsigned ArgNo)

Create a position describing the argument of CB at position ArgNo.

static LLVM_ABI const IRPosition TombstoneKey

Kind

The positions we distinguish in the IR.

@ IRP_ARGUMENT

An attribute for a function argument.

@ IRP_RETURNED

An attribute for the function return value.

@ IRP_CALL_SITE

An attribute for a call site (function scope).

@ IRP_CALL_SITE_RETURNED

An attribute for a call site return value.

@ IRP_FUNCTION

An attribute for a function (scope).

@ IRP_FLOAT

A position that is not associated with a spot suitable for attributes.

@ IRP_CALL_SITE_ARGUMENT

An attribute for a call site argument.

@ IRP_INVALID

An invalid position.

Instruction * getCtxI() const

Return the context instruction, if any.

static const IRPosition argument(const Argument &Arg, const CallBaseContext *CBContext=nullptr)

Create a position describing the argument Arg.

static LLVM_ABI const IRPosition EmptyKey

Special DenseMap key values.

static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)

Create a position describing the function scope of F.

const CallBaseContext * getCallBaseContext() const

Get the call base context from the position.

Value & getAssociatedValue() const

Return the value this abstract attribute is associated with.

Value & getAnchorValue() const

Return the value this abstract attribute is anchored with.

Value * getAttrListAnchor() const

Return the value attributes are attached to.

int getCallSiteArgNo() const

Return the call site argument number of the associated value if it is an argument or call site argume...

Kind getPositionKind() const

Return the associated position kind.

static const IRPosition callsite_function(const CallBase &CB)

Create a position describing the function scope of CB.

Function * getAnchorScope() const

Return the Function surrounding the anchor value.

Data structure to hold cached (LLVM-IR) information.

friend struct Attributor

Give the Attributor access to the members so Attributor::identifyDefaultAbstractAttributes(....

bool stackIsAccessibleByOtherThreads()

Return true if the stack (llvm::Alloca) can be accessed by other threads.

MustBeExecutedContextExplorer * getMustBeExecutedContextExplorer()

Return MustBeExecutedContextExplorer.

TargetLibraryInfo * getTargetLibraryInfoForFunction(const Function &F)

Return TargetLibraryInfo for function F.

LLVM_ABI std::optional< unsigned > getFlatAddressSpace() const

Return the flat address space if the associated target has.

Definition Attributor.cpp:3297

DenseMap< unsigned, InstructionVectorTy * > OpcodeInstMapTy

A map type from opcodes to instructions with this opcode.

const RetainedKnowledgeMap & getKnowledgeMap() const

Return the map conaining all the knowledge we have from llvm.assumes.

LLVM_ABI ArrayRef< Function * > getIndirectlyCallableFunctions(Attributor &A) const

Return all functions that might be called indirectly, only valid for closed world modules (see isClos...

Definition Attributor.cpp:3292

SmallVector< Instruction *, 8 > InstructionVectorTy

A vector type to hold instructions.

AP::Result * getAnalysisResultForFunction(const Function &F, bool CachedOnly=false)

Return the analysis result from a pass AP for function F.

State for an integer range.

ConstantRange getKnown() const

Return the known state encoding.

ConstantRange getAssumed() const

Return the assumed state encoding.

uint32_t getBitWidth() const

Return associated values' bit width.

A "must be executed context" for a given program point PP is the set of instructions,...

iterator & end()

Return an universal end iterator.

bool findInContextOf(const Instruction *I, const Instruction *PP)

Helper to look for I in the context of PP.

iterator & begin(const Instruction *PP)

Return an iterator to explore the context around PP.

bool undefIsContained() const

Returns whether this state contains an undef value or not.

bool isValidState() const override

See AbstractState::isValidState(...)

const SetTy & getAssumedSet() const

Return this set.