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 (.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,
348 return A;
349 if ()
350 return A;
351 if (*B == nullptr)
352 return nullptr;
353 if ()
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 () {
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(
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 && .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 = .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 (.mayHaveSideEffects() &&
.mayReadFromMemory())
897 return false;
898
900
901 auto AddLocationPtr = [&](std::optional Loc) {
902 if ( ||
->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) {
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() && (*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 ()
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) {
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 ((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) {
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 || .getUser()->isDroppable())
2498 Uses.push_back(&U);
2499 for (Use *U : Uses) {
2501 if ((*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 (->getType()->isVoidTy())
2561 else
2562 I->eraseFromParent();
2563 }
2564 }
2565
2566 llvm::erase_if(DeadInsts, [&](WeakTrackingVH I) { return ; });
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 (.isQueryAA() && DV.empty() &&
.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(.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 ->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 || .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 (() && !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 (.isFunctionIPOAmendable(*F))
3852
3853
3854
3855
3856
3858 unsigned FunSize = Functions.size();
3859 for (unsigned u = 0; u < FunSize; u++) {
3861 if (->isDeclaration() &&
->isDefinitionExact() &&
->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.