LLVM 24.0.0git
Attributes.cpp
Go to the documentation of this file.
1//===- Attributes.cpp - Implement AttributesList --------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// \file
10// This file implements the Attribute, AttributeImpl, AttrBuilder,
11// AttributeListImpl, and AttributeList classes.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/IR/Attributes.h"
16#include "AttributeImpl.h"
17#include "LLVMContextImpl.h"
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/FoldingSet.h"
20#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/StringRef.h"
25#include "llvm/Config/llvm-config.h"
29#include "llvm/IR/Function.h"
30#include "llvm/IR/LLVMContext.h"
31#include "llvm/IR/Operator.h"
32#include "llvm/IR/Type.h"
35#include "llvm/Support/ModRef.h"
37#include <algorithm>
38#include <cassert>
39#include <cstddef>
40#include <cstdint>
41#include <limits>
42#include <optional>
43#include <string>
44#include <tuple>
45#include <utility>
46
47using namespace llvm;
48
49//===----------------------------------------------------------------------===//
50// Attribute Construction Methods
51//===----------------------------------------------------------------------===//
52
53// allocsize has two integer arguments, but because they're both 32 bits, we can
54// pack them into one 64-bit value, at the cost of making said value
55// nonsensical.
56//
57// In order to do this, we need to reserve one value of the second (optional)
58// allocsize argument to signify "not present."
59static const unsigned AllocSizeNumElemsNotPresent = -1;
60
61static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
62 const std::optional<unsigned> &NumElemsArg) {
63 assert((!NumElemsArg || *NumElemsArg != AllocSizeNumElemsNotPresent) &&
64 "Attempting to pack a reserved value");
65
66 return uint64_t(ElemSizeArg) << 32 |
67 NumElemsArg.value_or(AllocSizeNumElemsNotPresent);
68}
69
70static std::pair<unsigned, std::optional<unsigned>>
72 unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
73 unsigned ElemSizeArg = Num >> 32;
74
75 std::optional<unsigned> NumElemsArg;
76 if (NumElems != AllocSizeNumElemsNotPresent)
77 NumElemsArg = NumElems;
78 return std::make_pair(ElemSizeArg, NumElemsArg);
79}
80
81static uint64_t packVScaleRangeArgs(unsigned MinValue,
82 std::optional<unsigned> MaxValue) {
83 return uint64_t(MinValue) << 32 | MaxValue.value_or(0);
84}
85
86static std::pair<unsigned, std::optional<unsigned>>
88 unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
89 unsigned MinValue = Value >> 32;
90
91 return std::make_pair(MinValue,
92 MaxValue > 0 ? MaxValue : std::optional<unsigned>());
93}
94
96 uint64_t Val) {
97 bool IsIntAttr = Attribute::isIntAttrKind(Kind);
98 assert((IsIntAttr || Attribute::isEnumAttrKind(Kind)) &&
99 "Not an enum or int attribute");
100
101 LLVMContextImpl *pImpl = Context.pImpl;
102 if (!IsIntAttr) {
103 assert(Val == 0 && "Value must be zero for enum attributes");
104 EnumAttributeImpl *&PA = pImpl->EnumAttrs[Kind - Attribute::FirstEnumAttr];
105 if (!PA)
106 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
107 return Attribute(PA);
108 }
109
111 IntAttributeImpl *PA = pImpl->IntAttrs.lookup({Kind, Val}, Token);
112 if (!PA) {
113 // If we didn't find any existing attributes of the same shape then create a
114 // new one and insert it.
115 PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
116 pImpl->IntAttrs.insert(PA, Token);
117 }
118
119 // Return the Attribute that we found or created.
120 return Attribute(PA);
121}
122
123Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
124 LLVMContextImpl *pImpl = Context.pImpl;
126 StringAttributeImpl *PA = pImpl->StringAttrs.lookup({Kind, Val}, Token);
127 if (!PA) {
128 // If we didn't find any existing attributes of the same shape then create a
129 // new one and insert it.
130 void *Mem =
131 pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
132 alignof(StringAttributeImpl));
133 PA = new (Mem) StringAttributeImpl(Kind, Val);
134 pImpl->StringAttrs.insert(PA, Token);
135 }
136
137 // Return the Attribute that we found or created.
138 return Attribute(PA);
139}
140
142 Type *Ty) {
143 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
144 LLVMContextImpl *pImpl = Context.pImpl;
146 TypeAttributeImpl *PA = pImpl->TypeAttrs.lookup({Kind, Ty}, Token);
147 if (!PA) {
148 // If we didn't find any existing attributes of the same shape then create a
149 // new one and insert it.
150 PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
151 pImpl->TypeAttrs.insert(PA, Token);
152 }
153
154 // Return the Attribute that we found or created.
155 return Attribute(PA);
156}
157
159 const ConstantRange &CR) {
161 "Not a ConstantRange attribute");
162 assert(!CR.isFullSet() && "ConstantRange attribute must not be full");
163 LLVMContextImpl *pImpl = Context.pImpl;
165 ID.AddInteger(Kind);
166 CR.getLower().Profile(ID);
167 CR.getUpper().Profile(ID);
168
170 AttributeImpl *PA = pImpl->AttrsSet.lookup(ID, Token);
171
172 if (!PA) {
173 // If we didn't find any existing attributes of the same shape then create a
174 // new one and insert it.
175 PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate())
177 pImpl->AttrsSet.insert(PA, Token);
178 }
179
180 // Return the Attribute that we found or created.
181 return Attribute(PA);
182}
183
187 "Not a ConstantRangeList attribute");
188 LLVMContextImpl *pImpl = Context.pImpl;
190 ID.AddInteger(Kind);
191 ID.AddInteger(Val.size());
192 for (auto &CR : Val) {
193 CR.getLower().Profile(ID);
194 CR.getUpper().Profile(ID);
195 }
196
198 AttributeImpl *PA = pImpl->AttrsSet.lookup(ID, Token);
199
200 if (!PA) {
201 // If we didn't find any existing attributes of the same shape then create a
202 // new one and insert it.
203 // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
204 // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
205 // allocation and record the allocated pointer in
206 // `ConstantRangeListAttributes`. LLVMContext destructor will call the
207 // destructor of the allocated pointer explicitly.
208 void *Mem = pImpl->Alloc.Allocate(
211 PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);
212 pImpl->AttrsSet.insert(PA, Token);
213 pImpl->ConstantRangeListAttributes.push_back(
214 reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));
215 }
216
217 // Return the Attribute that we found or created.
218 return Attribute(PA);
219}
220
222 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
223 return get(Context, Alignment, A.value());
224}
225
227 assert(A <= 0x100 && "Alignment too large.");
228 return get(Context, StackAlignment, A.value());
229}
230
232 uint64_t Bytes) {
233 assert(Bytes && "Bytes must be non-zero.");
234 return get(Context, Dereferenceable, Bytes);
235}
236
238 uint64_t Bytes) {
239 assert(Bytes && "Bytes must be non-zero.");
240 return get(Context, DereferenceableOrNull, Bytes);
241}
242
244 return get(Context, ByVal, Ty);
245}
246
248 return get(Context, StructRet, Ty);
249}
250
252 return get(Context, ByRef, Ty);
253}
254
256 return get(Context, Preallocated, Ty);
257}
258
260 return get(Context, InAlloca, Ty);
261}
262
264 UWTableKind Kind) {
265 return get(Context, UWTable, uint64_t(Kind));
266}
267
269 MemoryEffects ME) {
270 return get(Context, Memory, ME.toIntValue());
271}
272
274 FPClassTest ClassMask) {
275 return get(Context, NoFPClass, ClassMask);
276}
277
279 DeadOnReturnInfo DI) {
280 return get(Context, DeadOnReturn, DI.toIntValue());
281}
282
284 return get(Context, Captures, CI.toIntValue());
285}
286
288Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
289 const std::optional<unsigned> &NumElemsArg) {
290 assert(!(ElemSizeArg == 0 && NumElemsArg == 0) &&
291 "Invalid allocsize arguments -- given allocsize(0, 0)");
292 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
293}
294
296 return get(Context, AllocKind, static_cast<uint64_t>(Kind));
297}
298
300 unsigned MinValue,
301 unsigned MaxValue) {
302 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
303}
304
306 return StringSwitch<Attribute::AttrKind>(AttrName)
307#define GET_ATTR_NAMES
308#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
309 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
310#include "llvm/IR/Attributes.inc"
312}
313
315 switch (AttrKind) {
316#define GET_ATTR_NAMES
317#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
318 case Attribute::ENUM_NAME: \
319 return #DISPLAY_NAME;
320#include "llvm/IR/Attributes.inc"
321 case Attribute::None:
322 return "none";
323 default:
324 llvm_unreachable("invalid Kind");
325 }
326}
327
328//===----------------------------------------------------------------------===//
329// Attribute Accessor Methods
330//===----------------------------------------------------------------------===//
331
333 return pImpl && pImpl->isEnumAttribute();
334}
335
337 return pImpl && pImpl->isIntAttribute();
338}
339
341 return pImpl && pImpl->isStringAttribute();
342}
343
345 return pImpl && pImpl->isTypeAttribute();
346}
347
349 return pImpl && pImpl->isConstantRangeAttribute();
350}
351
353 return pImpl && pImpl->isConstantRangeListAttribute();
354}
355
357 if (!pImpl) return None;
359 "Invalid attribute type to get the kind as an enum!");
360 return pImpl->getKindAsEnum();
361}
362
363uint64_t Attribute::getValueAsInt() const {
364 if (!pImpl) return 0;
366 "Expected the attribute to be an integer attribute!");
367 return pImpl->getValueAsInt();
368}
369
371 if (!pImpl) return false;
373 "Expected the attribute to be a string attribute!");
374 return pImpl->getValueAsBool();
375}
376
378 if (!pImpl) return {};
380 "Invalid attribute type to get the kind as a string!");
381 return pImpl->getKindAsString();
382}
383
385 if (!pImpl) return {};
387 "Invalid attribute type to get the value as a string!");
388 return pImpl->getValueAsString();
389}
390
392 if (!pImpl) return {};
394 "Invalid attribute type to get the value as a type!");
395 return pImpl->getValueAsType();
396}
397
400 "Invalid attribute type to get the value as a ConstantRange!");
401 return pImpl->getValueAsConstantRange();
402}
403
406 "Invalid attribute type to get the value as a ConstantRangeList!");
407 return pImpl->getValueAsConstantRangeList();
408}
409
411 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
412}
413
415 if (!isStringAttribute()) return false;
416 return pImpl && pImpl->hasAttribute(Kind);
417}
418
420 assert(hasAttribute(Attribute::Alignment) &&
421 "Trying to get alignment from non-alignment attribute!");
422 return MaybeAlign(pImpl->getValueAsInt());
423}
424
426 assert(hasAttribute(Attribute::StackAlignment) &&
427 "Trying to get alignment from non-alignment attribute!");
428 return MaybeAlign(pImpl->getValueAsInt());
429}
430
432 assert(hasAttribute(Attribute::Dereferenceable) &&
433 "Trying to get dereferenceable bytes from "
434 "non-dereferenceable attribute!");
435 return pImpl->getValueAsInt();
436}
437
439 assert(hasAttribute(Attribute::DeadOnReturn) &&
440 "Trying to get dead_on_return bytes from"
441 "a parameter without such an attribute!");
442 return DeadOnReturnInfo::createFromIntValue(pImpl->getValueAsInt());
443}
444
446 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
447 "Trying to get dereferenceable bytes from "
448 "non-dereferenceable attribute!");
449 return pImpl->getValueAsInt();
450}
451
452std::pair<unsigned, std::optional<unsigned>>
454 assert(hasAttribute(Attribute::AllocSize) &&
455 "Trying to get allocsize args from non-allocsize attribute");
456 return unpackAllocSizeArgs(pImpl->getValueAsInt());
457}
458
460 assert(hasAttribute(Attribute::VScaleRange) &&
461 "Trying to get vscale args from non-vscale attribute");
462 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
463}
464
465std::optional<unsigned> Attribute::getVScaleRangeMax() const {
466 assert(hasAttribute(Attribute::VScaleRange) &&
467 "Trying to get vscale args from non-vscale attribute");
468 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
469}
470
472 assert(hasAttribute(Attribute::UWTable) &&
473 "Trying to get unwind table kind from non-uwtable attribute");
474 return UWTableKind(pImpl->getValueAsInt());
475}
476
478 assert(hasAttribute(Attribute::AllocKind) &&
479 "Trying to get allockind value from non-allockind attribute");
480 return AllocFnKind(pImpl->getValueAsInt());
481}
482
484 assert(hasAttribute(Attribute::Memory) &&
485 "Can only call getMemoryEffects() on memory attribute");
486 return MemoryEffects::createFromIntValue(pImpl->getValueAsInt());
487}
488
490 assert(hasAttribute(Attribute::Captures) &&
491 "Can only call getCaptureInfo() on captures attribute");
492 return CaptureInfo::createFromIntValue(pImpl->getValueAsInt());
493}
494
496 return DenormalFPEnv::createFromIntValue(pImpl->getValueAsInt());
497}
498
500 assert(hasAttribute(Attribute::NoFPClass) &&
501 "Can only call getNoFPClass() on nofpclass attribute");
502 return static_cast<FPClassTest>(pImpl->getValueAsInt());
503}
504
506 assert(hasAttribute(Attribute::Range) &&
507 "Trying to get range args from non-range attribute");
508 return pImpl->getValueAsConstantRange();
509}
510
512 assert(hasAttribute(Attribute::Initializes) &&
513 "Trying to get initializes attr from non-ConstantRangeList attribute");
514 return pImpl->getValueAsConstantRangeList();
515}
516
517static const char *getModRefStr(ModRefInfo MR) {
518 switch (MR) {
520 return "none";
521 case ModRefInfo::Ref:
522 return "read";
523 case ModRefInfo::Mod:
524 return "write";
526 return "readwrite";
527 }
528 llvm_unreachable("Invalid ModRefInfo");
529}
530
531std::string Attribute::getAsString(bool InAttrGrp) const {
532 if (!pImpl) return {};
533
534 if (isEnumAttribute())
536
537 if (isTypeAttribute()) {
538 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
539 Result += '(';
540 raw_string_ostream OS(Result);
541 getValueAsType()->print(OS, false, true);
542 Result += ')';
543 return Result;
544 }
545
546 // FIXME: These should be output like this:
547 //
548 // align=4
549 // alignstack=8
550 //
551 if (hasAttribute(Attribute::Alignment))
552 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
553 : "align " + Twine(getValueAsInt()))
554 .str();
555
556 auto AttrWithBytesToString = [&](const char *Name) {
557 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
558 : Name + ("(" + Twine(getValueAsInt())) + ")")
559 .str();
560 };
561
562 if (hasAttribute(Attribute::StackAlignment))
563 return AttrWithBytesToString("alignstack");
564
565 if (hasAttribute(Attribute::Dereferenceable))
566 return AttrWithBytesToString("dereferenceable");
567
568 if (hasAttribute(Attribute::DereferenceableOrNull))
569 return AttrWithBytesToString("dereferenceable_or_null");
570
571 if (hasAttribute(Attribute::DeadOnReturn)) {
572 uint64_t DeadBytes = getValueAsInt();
573 if (DeadBytes == std::numeric_limits<uint64_t>::max())
574 return "dead_on_return";
575 return AttrWithBytesToString("dead_on_return");
576 }
577
578 if (hasAttribute(Attribute::AllocSize)) {
579 unsigned ElemSize;
580 std::optional<unsigned> NumElems;
581 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
582
583 return (NumElems
584 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
585 : "allocsize(" + Twine(ElemSize) + ")")
586 .str();
587 }
588
589 if (hasAttribute(Attribute::VScaleRange)) {
590 unsigned MinValue = getVScaleRangeMin();
591 std::optional<unsigned> MaxValue = getVScaleRangeMax();
592 return ("vscale_range(" + Twine(MinValue) + "," +
593 Twine(MaxValue.value_or(0)) + ")")
594 .str();
595 }
596
597 if (hasAttribute(Attribute::UWTable)) {
599 assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
600 return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
601 }
602
603 if (hasAttribute(Attribute::AllocKind)) {
604 AllocFnKind Kind = getAllocKind();
607 parts.push_back("alloc");
609 parts.push_back("realloc");
611 parts.push_back("free");
613 parts.push_back("uninitialized");
615 parts.push_back("zeroed");
617 parts.push_back("aligned");
618 return ("allockind(\"" +
619 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
620 .str();
621 }
622
623 if (hasAttribute(Attribute::Memory)) {
624 std::string Result;
625 raw_string_ostream OS(Result);
626 bool First = true;
627 OS << "memory(";
628
630
631 // Print access kind for "other" as the default access kind. This way it
632 // will apply to any new location kinds that get split out of "other".
634 if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
635 First = false;
636 OS << getModRefStr(OtherMR);
637 }
638
639 bool TargetPrintedForAll = false;
640 for (auto Loc : MemoryEffects::locations()) {
641 ModRefInfo MR = ME.getModRef(Loc);
642 if (MR == OtherMR)
643 continue;
644
645 if (!First && !TargetPrintedForAll)
646 OS << ", ";
647 First = false;
648
649 // isTargetMemLocSameForAll is fine for target location < 3
650 // If more targets are added it should do something like:
651 // memory(target_mem:read, target_mem3:none, target_mem5:write).
653 if (!TargetPrintedForAll) {
654 OS << "target_mem: ";
655 OS << getModRefStr(MR);
656 TargetPrintedForAll = true;
657 }
658 // Only works when target memories are last to be listed in Location.
659 continue;
660 }
661
662 switch (Loc) {
664 OS << "argmem: ";
665 break;
667 OS << "inaccessiblemem: ";
668 break;
670 OS << "errnomem: ";
671 break;
673 llvm_unreachable("This is represented as the default access kind");
675 OS << "target_mem0: ";
676 break;
678 OS << "target_mem1: ";
679 break;
680 }
681 OS << getModRefStr(MR);
682 }
683 OS << ")";
684 return Result;
685 }
686
687 if (hasAttribute(Attribute::Captures)) {
688 std::string Result;
690 return Result;
691 }
692
693 if (hasAttribute(Attribute::DenormalFPEnv)) {
694 std::string Result = "denormal_fpenv(";
695 raw_string_ostream OS(Result);
696
697 struct DenormalFPEnv FPEnv = getDenormalFPEnv();
698 FPEnv.print(OS, /*OmitIfSame=*/true);
699
700 OS << ')';
701 return Result;
702 }
703
704 if (hasAttribute(Attribute::NoFPClass)) {
705 std::string Result = "nofpclass";
706 raw_string_ostream(Result) << getNoFPClass();
707 return Result;
708 }
709
710 if (hasAttribute(Attribute::Range)) {
711 std::string Result;
712 raw_string_ostream OS(Result);
714 OS << "range(";
715 OS << "i" << CR.getBitWidth() << " ";
716 OS << CR.getLower() << ", " << CR.getUpper();
717 OS << ")";
718 return Result;
719 }
720
721 if (hasAttribute(Attribute::Initializes)) {
722 std::string Result;
723 raw_string_ostream OS(Result);
725 OS << "initializes(";
726 CRL.print(OS);
727 OS << ")";
728 return Result;
729 }
730
731 // Convert target-dependent attributes to strings of the form:
732 //
733 // "kind"
734 // "kind" = "value"
735 //
736 if (isStringAttribute()) {
737 std::string Result;
738 {
739 raw_string_ostream OS(Result);
740 OS << '"' << getKindAsString() << '"';
741
742 // Since some attribute strings contain special characters that cannot be
743 // printable, those have to be escaped to make the attribute value
744 // printable as is. e.g. "\01__gnu_mcount_nc"
745 const auto &AttrVal = pImpl->getValueAsString();
746 if (!AttrVal.empty()) {
747 OS << "=\"";
748 printEscapedString(AttrVal, OS);
749 OS << "\"";
750 }
751 }
752 return Result;
753 }
754
755 llvm_unreachable("Unknown attribute");
756}
757
759 assert(isValid() && "invalid Attribute doesn't refer to any context");
760 LLVMContextImpl *pI = C.pImpl;
762 if (pImpl->isEnumAttribute())
763 return pI->EnumAttrs[pImpl->getKindAsEnum() - FirstEnumAttr] == pImpl;
764 if (pImpl->isIntAttribute())
765 return pI->IntAttrs.lookup({pImpl->getKindAsEnum(), pImpl->getValueAsInt()},
766 Token) == pImpl;
767 if (pImpl->isStringAttribute())
768 return pI->StringAttrs.lookup(
769 {pImpl->getKindAsString(), pImpl->getValueAsString()}, Token) ==
770 pImpl;
771 if (pImpl->isTypeAttribute())
772 return pI->TypeAttrs.lookup(
773 {pImpl->getKindAsEnum(), pImpl->getValueAsType()}, Token) ==
774 pImpl;
776 pImpl->Profile(ID);
777 return pI->AttrsSet.lookup(ID, Token) == pImpl;
778}
779
780int Attribute::cmpKind(Attribute A) const {
781 if (!pImpl && !A.pImpl)
782 return 0;
783 if (!pImpl)
784 return 1;
785 if (!A.pImpl)
786 return -1;
787 return pImpl->cmp(*A.pImpl, /*KindOnly=*/true);
788}
789
790bool Attribute::operator<(Attribute A) const {
791 if (!pImpl && !A.pImpl) return false;
792 if (!pImpl) return true;
793 if (!A.pImpl) return false;
794 return *pImpl < *A.pImpl;
795}
796
798 FnAttr = (1 << 0),
799 ParamAttr = (1 << 1),
800 RetAttr = (1 << 2),
802 IntersectAnd = (1 << 3),
803 IntersectMin = (2 << 3),
804 IntersectCustom = (3 << 3),
806 ABIAttr = (1 << 5),
807};
808
809#define GET_ATTR_PROP_TABLE
810#include "llvm/IR/Attributes.inc"
811
813 unsigned Index = Kind - 1;
814 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
815 return AttrPropTable[Index];
816}
817
819 AttributeProperty Prop) {
820 return getAttributeProperties(Kind) & Prop;
821}
822
826
830
834
838
840 AttributeProperty Prop) {
845 "Unknown intersect property");
846 return (getAttributeProperties(Kind) &
848}
849
862
863//===----------------------------------------------------------------------===//
864// AttributeImpl Definition
865//===----------------------------------------------------------------------===//
866
868 if (isStringAttribute()) return false;
869 return getKindAsEnum() == A;
870}
871
873 if (!isStringAttribute()) return false;
874 return getKindAsString() == Kind;
875}
876
882
885 return static_cast<const IntAttributeImpl *>(this)->getValue();
886}
887
889 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
890 return getValueAsString() == "true";
891}
892
895 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
896}
897
900 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
901}
902
905 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
906}
907
910 return static_cast<const ConstantRangeAttributeImpl *>(this)
911 ->getConstantRangeValue();
912}
913
916 return static_cast<const ConstantRangeListAttributeImpl *>(this)
917 ->getConstantRangeListValue();
918}
919
920int AttributeImpl::cmp(const AttributeImpl &AI, bool KindOnly) const {
921 if (this == &AI)
922 return 0;
923
924 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
925 // relative to their enum value) and then strings.
926 if (!isStringAttribute()) {
927 if (AI.isStringAttribute())
928 return -1;
929
930 if (getKindAsEnum() != AI.getKindAsEnum())
931 return getKindAsEnum() < AI.getKindAsEnum() ? -1 : 1;
932 else if (KindOnly)
933 return 0;
934
935 assert(!AI.isEnumAttribute() && "Non-unique attribute");
936 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
937 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
939 "Unclear how to compare range list");
940 // TODO: Is this actually needed?
941 assert(AI.isIntAttribute() && "Only possibility left");
942 if (getValueAsInt() < AI.getValueAsInt())
943 return -1;
944 return getValueAsInt() == AI.getValueAsInt() ? 0 : 1;
945 }
946 if (!AI.isStringAttribute())
947 return 1;
948 if (KindOnly)
950 if (getKindAsString() == AI.getKindAsString())
953}
954
956 return cmp(AI, /*KindOnly=*/false) < 0;
957}
958
959//===----------------------------------------------------------------------===//
960// AttributeSet Definition
961//===----------------------------------------------------------------------===//
962
963AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
965}
966
970
972 Attribute::AttrKind Kind) const {
973 if (hasAttribute(Kind)) return *this;
974 AttrBuilder B(C);
975 B.addAttribute(Kind);
977}
978
980 StringRef Value) const {
981 AttrBuilder B(C);
982 B.addAttribute(Kind, Value);
984}
985
987 const AttributeSet AS) const {
988 if (!hasAttributes())
989 return AS;
990
991 if (!AS.hasAttributes())
992 return *this;
993
994 AttrBuilder B(C, *this);
995 B.merge(AttrBuilder(C, AS));
996 return get(C, B);
997}
998
1000 const AttrBuilder &B) const {
1001 if (!hasAttributes())
1002 return get(C, B);
1003
1004 if (!B.hasAttributes())
1005 return *this;
1006
1007 AttrBuilder Merged(C, *this);
1008 Merged.merge(B);
1009 return get(C, Merged);
1010}
1011
1013 Attribute::AttrKind Kind) const {
1014 if (!hasAttribute(Kind)) return *this;
1015 AttrBuilder B(C, *this);
1016 B.removeAttribute(Kind);
1017 return get(C, B);
1018}
1019
1021 StringRef Kind) const {
1022 if (!hasAttribute(Kind)) return *this;
1023 AttrBuilder B(C, *this);
1024 B.removeAttribute(Kind);
1025 return get(C, B);
1026}
1027
1029 const AttributeMask &Attrs) const {
1030 AttrBuilder B(C, *this);
1031 // If there is nothing to remove, directly return the original set.
1032 if (!B.overlaps(Attrs))
1033 return *this;
1034
1035 B.remove(Attrs);
1036 return get(C, B);
1037}
1038
1039std::optional<AttributeSet>
1041 if (*this == Other)
1042 return *this;
1043
1044 AttrBuilder Intersected(C);
1045 // Iterate over both attr sets at once.
1046 auto ItBegin0 = begin();
1047 auto ItEnd0 = end();
1048 auto ItBegin1 = Other.begin();
1049 auto ItEnd1 = Other.end();
1050
1051 while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {
1052 // Loop through all attributes in both this and Other in sorted order. If
1053 // the attribute is only present in one of the sets, it will be set in
1054 // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.
1055 Attribute Attr0, Attr1;
1056 if (ItBegin1 == ItEnd1)
1057 Attr0 = *ItBegin0++;
1058 else if (ItBegin0 == ItEnd0)
1059 Attr0 = *ItBegin1++;
1060 else {
1061 int Cmp = ItBegin0->cmpKind(*ItBegin1);
1062 if (Cmp == 0) {
1063 Attr0 = *ItBegin0++;
1064 Attr1 = *ItBegin1++;
1065 } else if (Cmp < 0)
1066 Attr0 = *ItBegin0++;
1067 else
1068 Attr0 = *ItBegin1++;
1069 }
1070 assert(Attr0.isValid() && "Iteration should always yield a valid attr");
1071
1072 auto IntersectEq = [&]() {
1073 if (!Attr1.isValid())
1074 return false;
1075 if (Attr0 != Attr1)
1076 return false;
1077 Intersected.addAttribute(Attr0);
1078 return true;
1079 };
1080
1081 // Non-enum assume we must preserve. Handle early so we can unconditionally
1082 // use Kind below.
1083 if (!Attr0.hasKindAsEnum()) {
1084 if (!IntersectEq())
1085 return std::nullopt;
1086 continue;
1087 }
1088
1089 Attribute::AttrKind Kind = Attr0.getKindAsEnum();
1090 // If we don't have both attributes, then fail if the attribute is
1091 // must-preserve or drop it otherwise.
1092 if (!Attr1.isValid()) {
1094 return std::nullopt;
1095 continue;
1096 }
1097
1098 // We have both attributes so apply the intersection rule.
1099 assert(Attr1.hasKindAsEnum() && Kind == Attr1.getKindAsEnum() &&
1100 "Iterator picked up two different attributes in the same iteration");
1101
1102 // Attribute we can intersect with "and"
1103 if (Attribute::intersectWithAnd(Kind)) {
1105 "Invalid attr type of intersectAnd");
1106 Intersected.addAttribute(Kind);
1107 continue;
1108 }
1109
1110 // Attribute we can intersect with "min"
1111 if (Attribute::intersectWithMin(Kind)) {
1113 "Invalid attr type of intersectMin");
1114 uint64_t NewVal = std::min(Attr0.getValueAsInt(), Attr1.getValueAsInt());
1115 Intersected.addRawIntAttr(Kind, NewVal);
1116 continue;
1117 }
1118 // Attribute we can intersect but need a custom rule for.
1120 switch (Kind) {
1121 case Attribute::Alignment:
1122 // If `byval` is present, alignment become must-preserve. This is
1123 // handled below if we have `byval`.
1124 Intersected.addAlignmentAttr(
1125 std::min(Attr0.getAlignment().valueOrOne(),
1126 Attr1.getAlignment().valueOrOne()));
1127 break;
1128 case Attribute::Memory:
1129 Intersected.addMemoryAttr(Attr0.getMemoryEffects() |
1130 Attr1.getMemoryEffects());
1131 break;
1132 case Attribute::Captures:
1133 Intersected.addCapturesAttr(Attr0.getCaptureInfo() |
1134 Attr1.getCaptureInfo());
1135 break;
1136 case Attribute::NoFPClass:
1137 Intersected.addNoFPClassAttr(Attr0.getNoFPClass() &
1138 Attr1.getNoFPClass());
1139 break;
1140 case Attribute::Range: {
1141 ConstantRange Range0 = Attr0.getRange();
1142 ConstantRange Range1 = Attr1.getRange();
1143 ConstantRange NewRange = Range0.unionWith(Range1);
1144 if (!NewRange.isFullSet())
1145 Intersected.addRangeAttr(NewRange);
1146 } break;
1147 default:
1148 llvm_unreachable("Unknown attribute with custom intersection rule");
1149 }
1150 continue;
1151 }
1152
1153 // Attributes with no intersection rule. Only intersect if they are equal.
1154 // Otherwise fail.
1155 if (!IntersectEq())
1156 return std::nullopt;
1157
1158 // Special handling of `byval`. `byval` essentially turns align attr into
1159 // must-preserve
1160 if (Kind == Attribute::ByVal &&
1161 getAttribute(Attribute::Alignment) !=
1162 Other.getAttribute(Attribute::Alignment))
1163 return std::nullopt;
1164 }
1165
1166 return get(C, Intersected);
1167}
1168
1170 return SetNode ? SetNode->getNumAttributes() : 0;
1171}
1172
1174 return SetNode ? SetNode->hasAttribute(Kind) : false;
1175}
1176
1178 return SetNode ? SetNode->hasAttribute(Kind) : false;
1179}
1180
1182 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1183}
1184
1186 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1187}
1188
1190 return SetNode ? SetNode->getAlignment() : std::nullopt;
1191}
1192
1194 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
1195}
1196
1198 return SetNode ? SetNode->getDereferenceableBytes() : 0;
1199}
1200
1202 return SetNode ? SetNode->getDeadOnReturnInfo() : DeadOnReturnInfo(0);
1203}
1204
1206 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
1207}
1208
1210 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
1211}
1212
1214 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
1215}
1216
1218 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
1219}
1220
1222 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
1223}
1224
1226 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
1227}
1228
1230 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
1231}
1232
1233std::optional<std::pair<unsigned, std::optional<unsigned>>>
1235 if (SetNode)
1236 return SetNode->getAllocSizeArgs();
1237 return std::nullopt;
1238}
1239
1241 return SetNode ? SetNode->getVScaleRangeMin() : 1;
1242}
1243
1244std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
1245 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
1246}
1247
1249 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
1250}
1251
1253 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
1254}
1255
1257 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
1258}
1259
1261 return SetNode ? SetNode->getCaptureInfo() : CaptureInfo::all();
1262}
1263
1265 return SetNode ? SetNode->getNoFPClass() : fcNone;
1266}
1267
1268std::string AttributeSet::getAsString(bool InAttrGrp) const {
1269 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
1270}
1271
1273 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1275 return C.pImpl->AttrsSetNodes.lookup(SetNode->getKey(), Token) == SetNode;
1276}
1277
1279 return SetNode ? SetNode->begin() : nullptr;
1280}
1281
1283 return SetNode ? SetNode->end() : nullptr;
1284}
1285
1286#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1288 dbgs() << "AS =\n";
1289 dbgs() << " { ";
1290 dbgs() << getAsString(true) << " }\n";
1291}
1292#endif
1293
1294//===----------------------------------------------------------------------===//
1295// AttributeSetNode Definition
1296//===----------------------------------------------------------------------===//
1297
1298AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1299 : NumAttrs(Attrs.size()) {
1300 // There's memory after the node where we can store the entries in.
1301 llvm::copy(Attrs, getTrailingObjects());
1302
1303 for (const auto &I : *this) {
1304 if (I.isStringAttribute())
1305 StringAttrs.insert({ I.getKindAsString(), I });
1306 else
1307 AvailableAttrs.addAttribute(I.getKindAsEnum());
1308 }
1309}
1310
1312 ArrayRef<Attribute> Attrs) {
1313 SmallVector<Attribute, 8> SortedAttrs(Attrs);
1314 llvm::sort(SortedAttrs);
1315 return getSorted(C, SortedAttrs);
1316}
1317
1318/// Attribute comparator that only compares attribute keys. Enum attributes are
1319/// sorted before string attributes.
1321 bool operator()(Attribute A0, Attribute A1) const {
1322 bool A0IsString = A0.isStringAttribute();
1323 bool A1IsString = A1.isStringAttribute();
1324 if (A0IsString) {
1325 if (A1IsString)
1326 return A0.getKindAsString() < A1.getKindAsString();
1327 else
1328 return false;
1329 }
1330 if (A1IsString)
1331 return true;
1332 return A0.getKindAsEnum() < A1.getKindAsEnum();
1333 }
1335 if (A0.isStringAttribute())
1336 return false;
1337 return A0.getKindAsEnum() < Kind;
1338 }
1339 bool operator()(Attribute A0, StringRef Kind) const {
1340 if (A0.isStringAttribute())
1341 return A0.getKindAsString() < Kind;
1342 return true;
1343 }
1344};
1345
1346#ifndef NDEBUG
1347/// Return true if \p Attrs is known sorted with no duplicate entries.
1349 return adjacent_find(Attrs, [](Attribute A0, Attribute A1) {
1350 return !AttributeComparator()(A0, A1);
1351 }) == Attrs.end();
1352}
1353#endif
1354
1356 ArrayRef<Attribute> SortedAttrs) {
1357 if (SortedAttrs.empty())
1358 return nullptr;
1359
1360 assert(isSortedAndUnique(SortedAttrs) &&
1361 "expected sorted and unique attributes!");
1362
1364 AttributeSetNode *PA = C.pImpl->AttrsSetNodes.lookup(SortedAttrs, Token);
1365
1366 // If we didn't find any existing attributes of the same shape then create a
1367 // new one and insert it.
1368 if (!PA) {
1369 // Coallocate entries after the AttributeSetNode itself.
1370 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1371 PA = new (Mem) AttributeSetNode(SortedAttrs);
1372 C.pImpl->AttrsSetNodes.insert(PA, Token);
1373 }
1374
1375 // Return the AttributeSetNode that we found or created.
1376 return PA;
1377}
1378
1379AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
1380 return getSorted(C, B.attrs());
1381}
1382
1384 return StringAttrs.count(Kind);
1385}
1386
1387std::optional<Attribute>
1388AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1389 // Do a quick presence check.
1390 if (!hasAttribute(Kind))
1391 return std::nullopt;
1392
1393 // Attributes in a set are sorted by enum value, followed by string
1394 // attributes. Binary search the one we want.
1395 const Attribute *I =
1396 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1397 [](Attribute A, Attribute::AttrKind Kind) {
1398 return A.getKindAsEnum() < Kind;
1399 });
1400 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1401 return *I;
1402}
1403
1405 if (auto A = findEnumAttribute(Kind))
1406 return *A;
1407 return {};
1408}
1409
1411 return StringAttrs.lookup(Kind);
1412}
1413
1415 if (auto A = findEnumAttribute(Attribute::Alignment))
1416 return A->getAlignment();
1417 return std::nullopt;
1418}
1419
1421 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1422 return A->getStackAlignment();
1423 return std::nullopt;
1424}
1425
1427 if (auto A = findEnumAttribute(Kind))
1428 return A->getValueAsType();
1429 return nullptr;
1430}
1431
1433 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1434 return A->getDereferenceableBytes();
1435 return 0;
1436}
1437
1439 if (auto A = findEnumAttribute(Attribute::DeadOnReturn))
1440 return A->getDeadOnReturnInfo();
1441 return 0;
1442}
1443
1445 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1446 return A->getDereferenceableOrNullBytes();
1447 return 0;
1448}
1449
1450std::optional<std::pair<unsigned, std::optional<unsigned>>>
1452 if (auto A = findEnumAttribute(Attribute::AllocSize))
1453 return A->getAllocSizeArgs();
1454 return std::nullopt;
1455}
1456
1458 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1459 return A->getVScaleRangeMin();
1460 return 1;
1461}
1462
1463std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1464 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1465 return A->getVScaleRangeMax();
1466 return std::nullopt;
1467}
1468
1470 if (auto A = findEnumAttribute(Attribute::UWTable))
1471 return A->getUWTableKind();
1472 return UWTableKind::None;
1473}
1474
1476 if (auto A = findEnumAttribute(Attribute::AllocKind))
1477 return A->getAllocKind();
1478 return AllocFnKind::Unknown;
1479}
1480
1482 if (auto A = findEnumAttribute(Attribute::Memory))
1483 return A->getMemoryEffects();
1484 return MemoryEffects::unknown();
1485}
1486
1488 if (auto A = findEnumAttribute(Attribute::Captures))
1489 return A->getCaptureInfo();
1490 return CaptureInfo::all();
1491}
1492
1494 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1495 return A->getNoFPClass();
1496 return fcNone;
1497}
1498
1499std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1500 std::string Str;
1501 for (iterator I = begin(), E = end(); I != E; ++I) {
1502 if (I != begin())
1503 Str += ' ';
1504 Str += I->getAsString(InAttrGrp);
1505 }
1506 return Str;
1507}
1508
1509//===----------------------------------------------------------------------===//
1510// AttributeListImpl Definition
1511//===----------------------------------------------------------------------===//
1512
1513/// Map from AttributeList index to the internal array index. Adding one happens
1514/// to work, because -1 wraps around to 0.
1515static unsigned attrIdxToArrayIdx(unsigned Index) {
1516 return Index + 1;
1517}
1518
1520 : NumAttrSets(Sets.size()) {
1521 assert(!Sets.empty() && "pointless AttributeListImpl");
1522
1523 // There's memory after the node where we can store the entries in.
1525
1526 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1527 // summary bitsets.
1528 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1529 if (!I.isStringAttribute())
1530 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1531
1532 for (const auto &Set : Sets)
1533 for (const auto &I : Set)
1534 if (!I.isStringAttribute())
1535 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1536}
1537
1539 unsigned *Index) const {
1540 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1541 return false;
1542
1543 if (Index) {
1544 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1545 if (begin()[I].hasAttribute(Kind)) {
1546 *Index = I - 1;
1547 break;
1548 }
1549 }
1550 }
1551
1552 return true;
1553}
1554
1555
1556#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1558 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1559}
1560#endif
1561
1562//===----------------------------------------------------------------------===//
1563// AttributeList Construction and Mutation Methods
1564//===----------------------------------------------------------------------===//
1565
1566AttributeList AttributeList::getImpl(LLVMContext &C,
1567 ArrayRef<AttributeSet> AttrSets) {
1568 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1569
1570 LLVMContextImpl *pImpl = C.pImpl;
1572 AttributeListImpl *PA = pImpl->AttrsLists.lookup(AttrSets, Token);
1573
1574 // If we didn't find any existing attributes of the same shape then
1575 // create a new one and insert it.
1576 if (!PA) {
1577 // Coallocate entries after the AttributeListImpl itself.
1578 void *Mem = pImpl->Alloc.Allocate(
1580 alignof(AttributeListImpl));
1581 PA = new (Mem) AttributeListImpl(AttrSets);
1582 pImpl->AttrsLists.insert(PA, Token);
1583 }
1584
1585 // Return the AttributesList that we found or created.
1586 return AttributeList(PA);
1587}
1588
1589AttributeList
1590AttributeList::get(LLVMContext &C,
1591 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1592 // If there are no attributes then return a null AttributesList pointer.
1593 if (Attrs.empty())
1594 return {};
1595
1597 "Misordered Attributes list!");
1598 assert(llvm::all_of(Attrs,
1599 [](const std::pair<unsigned, Attribute> &Pair) {
1600 return Pair.second.isValid();
1601 }) &&
1602 "Pointless attribute!");
1603
1604 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1605 // list.
1607 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1608 E = Attrs.end(); I != E; ) {
1609 unsigned Index = I->first;
1611 while (I != E && I->first == Index) {
1612 AttrVec.push_back(I->second);
1613 ++I;
1614 }
1615
1616 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1617 }
1618
1619 return get(C, AttrPairVec);
1620}
1621
1622AttributeList
1623AttributeList::get(LLVMContext &C,
1624 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1625 // If there are no attributes then return a null AttributesList pointer.
1626 if (Attrs.empty())
1627 return {};
1628
1630 "Misordered Attributes list!");
1631 assert(llvm::none_of(Attrs,
1632 [](const std::pair<unsigned, AttributeSet> &Pair) {
1633 return !Pair.second.hasAttributes();
1634 }) &&
1635 "Pointless attribute!");
1636
1637 unsigned MaxIndex = Attrs.back().first;
1638 // If the MaxIndex is FunctionIndex and there are other indices in front
1639 // of it, we need to use the largest of those to get the right size.
1640 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1641 MaxIndex = Attrs[Attrs.size() - 2].first;
1642
1643 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1644 for (const auto &Pair : Attrs)
1645 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1646
1647 return getImpl(C, AttrVec);
1648}
1649
1650AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1651 AttributeSet RetAttrs,
1652 ArrayRef<AttributeSet> ArgAttrs) {
1653 // Scan from the end to find the last argument with attributes. Most
1654 // arguments don't have attributes, so it's nice if we can have fewer unique
1655 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1656 unsigned NumSets = 0;
1657 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1658 if (ArgAttrs[I - 1].hasAttributes()) {
1659 NumSets = I + 2;
1660 break;
1661 }
1662 }
1663 if (NumSets == 0) {
1664 // Check function and return attributes if we didn't have argument
1665 // attributes.
1666 if (RetAttrs.hasAttributes())
1667 NumSets = 2;
1668 else if (FnAttrs.hasAttributes())
1669 NumSets = 1;
1670 }
1671
1672 // If all attribute sets were empty, we can use the empty attribute list.
1673 if (NumSets == 0)
1674 return {};
1675
1677 AttrSets.reserve(NumSets);
1678 // If we have any attributes, we always have function attributes.
1679 AttrSets.push_back(FnAttrs);
1680 if (NumSets > 1)
1681 AttrSets.push_back(RetAttrs);
1682 if (NumSets > 2) {
1683 // Drop the empty argument attribute sets at the end.
1684 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1685 llvm::append_range(AttrSets, ArgAttrs);
1686 }
1687
1688 return getImpl(C, AttrSets);
1689}
1690
1691AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1692 AttributeSet Attrs) {
1693 if (!Attrs.hasAttributes())
1694 return {};
1695 Index = attrIdxToArrayIdx(Index);
1696 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1697 AttrSets[Index] = Attrs;
1698 return getImpl(C, AttrSets);
1699}
1700
1701AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1702 const AttrBuilder &B) {
1703 return get(C, Index, AttributeSet::get(C, B));
1704}
1705
1706AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1709 for (const auto K : Kinds)
1710 Attrs.emplace_back(Index, Attribute::get(C, K));
1711 return get(C, Attrs);
1712}
1713
1714AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1717 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1719 auto VI = Values.begin();
1720 for (const auto K : Kinds)
1721 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1722 return get(C, Attrs);
1723}
1724
1725AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1726 ArrayRef<StringRef> Kinds) {
1728 for (const auto &K : Kinds)
1729 Attrs.emplace_back(Index, Attribute::get(C, K));
1730 return get(C, Attrs);
1731}
1732
1733AttributeList AttributeList::get(LLVMContext &C,
1735 if (Attrs.empty())
1736 return {};
1737 if (Attrs.size() == 1)
1738 return Attrs[0];
1739
1740 unsigned MaxSize = 0;
1741 for (const auto &List : Attrs)
1742 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1743
1744 // If every list was empty, there is no point in merging the lists.
1745 if (MaxSize == 0)
1746 return {};
1747
1748 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1749 for (unsigned I = 0; I < MaxSize; ++I) {
1750 AttrBuilder CurBuilder(C);
1751 for (const auto &List : Attrs)
1752 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1753 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1754 }
1755
1756 return getImpl(C, NewAttrSets);
1757}
1758
1759AttributeList
1760AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1761 Attribute::AttrKind Kind) const {
1763 if (Attrs.hasAttribute(Kind))
1764 return *this;
1765 // TODO: Insert at correct position and avoid sort.
1766 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1767 NewAttrs.push_back(Attribute::get(C, Kind));
1768 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1769}
1770
1771AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1772 StringRef Kind,
1773 StringRef Value) const {
1774 AttrBuilder B(C);
1775 B.addAttribute(Kind, Value);
1776 return addAttributesAtIndex(C, Index, B);
1777}
1778
1779AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
1780 Attribute A) const {
1781 AttrBuilder B(C);
1782 B.addAttribute(A);
1783 return addAttributesAtIndex(C, Index, B);
1784}
1785
1786AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1787 unsigned Index,
1788 AttributeSet Attrs) const {
1789 Index = attrIdxToArrayIdx(Index);
1790 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1791 if (Index >= AttrSets.size())
1792 AttrSets.resize(Index + 1);
1793 AttrSets[Index] = Attrs;
1794
1795 // Remove trailing empty attribute sets.
1796 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1797 AttrSets.pop_back();
1798 if (AttrSets.empty())
1799 return {};
1800 return AttributeList::getImpl(C, AttrSets);
1801}
1802
1803AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
1804 unsigned Index,
1805 const AttrBuilder &B) const {
1806 if (!B.hasAttributes())
1807 return *this;
1808
1809 if (!pImpl)
1810 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1811
1812 AttrBuilder Merged(C, getAttributes(Index));
1813 Merged.merge(B);
1814 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1815}
1816
1817AttributeList
1818AttributeList::addSortedAttributesAtIndex(LLVMContext &C, unsigned Index,
1819 ArrayRef<Attribute> Attrs) const {
1820 if (Attrs.empty())
1821 return *this;
1822 return setAttributesAtIndex(
1823 C, Index, getAttributes(Index).addSortedAttributes(C, Attrs));
1824}
1825
1826AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1827 ArrayRef<unsigned> ArgNos,
1828 Attribute A) const {
1829 assert(llvm::is_sorted(ArgNos));
1830
1831 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1832 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1833 if (MaxIndex >= AttrSets.size())
1834 AttrSets.resize(MaxIndex + 1);
1835
1836 for (unsigned ArgNo : ArgNos) {
1837 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1838 AttrBuilder B(C, AttrSets[Index]);
1839 B.addAttribute(A);
1840 AttrSets[Index] = AttributeSet::get(C, B);
1841 }
1842
1843 return getImpl(C, AttrSets);
1844}
1845
1846AttributeList
1847AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index,
1848 Attribute::AttrKind Kind) const {
1850 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1851 if (Attrs == NewAttrs)
1852 return *this;
1853 return setAttributesAtIndex(C, Index, NewAttrs);
1854}
1855
1856AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
1857 unsigned Index,
1858 StringRef Kind) const {
1860 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1861 if (Attrs == NewAttrs)
1862 return *this;
1863 return setAttributesAtIndex(C, Index, NewAttrs);
1864}
1865
1866AttributeList AttributeList::removeAttributesAtIndex(
1867 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1869 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1870 // If nothing was removed, return the original list.
1871 if (Attrs == NewAttrs)
1872 return *this;
1873 return setAttributesAtIndex(C, Index, NewAttrs);
1874}
1875
1876AttributeList
1877AttributeList::removeAttributesAtIndex(LLVMContext &C,
1878 unsigned WithoutIndex) const {
1879 if (!pImpl)
1880 return {};
1881 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1882 return *this;
1883 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1884}
1885
1886AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
1887 uint64_t Bytes) const {
1888 AttrBuilder B(C);
1889 B.addDereferenceableAttr(Bytes);
1890 return addRetAttributes(C, B);
1891}
1892
1893AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
1894 unsigned Index,
1895 uint64_t Bytes) const {
1896 AttrBuilder B(C);
1897 B.addDereferenceableAttr(Bytes);
1898 return addParamAttributes(C, Index, B);
1899}
1900
1901AttributeList
1902AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
1903 uint64_t Bytes) const {
1904 AttrBuilder B(C);
1905 B.addDereferenceableOrNullAttr(Bytes);
1906 return addParamAttributes(C, Index, B);
1907}
1908
1909AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
1910 const ConstantRange &CR) const {
1911 AttrBuilder B(C);
1912 B.addRangeAttr(CR);
1913 return addRetAttributes(C, B);
1914}
1915
1916AttributeList AttributeList::addAllocSizeParamAttr(
1917 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1918 const std::optional<unsigned> &NumElemsArg) const {
1919 AttrBuilder B(C);
1920 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1921 return addParamAttributes(C, Index, B);
1922}
1923
1924std::optional<AttributeList>
1925AttributeList::intersectWith(LLVMContext &C, AttributeList Other) const {
1926 // Trivial case, the two lists are equal.
1927 if (*this == Other)
1928 return *this;
1929
1931 auto IndexIt =
1932 index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
1933 for (unsigned Idx : IndexIt) {
1934 auto IntersectedAS =
1935 getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
1936 // If any index fails to intersect, fail.
1937 if (!IntersectedAS)
1938 return std::nullopt;
1939 if (!IntersectedAS->hasAttributes())
1940 continue;
1941 IntersectedAttrs.push_back(std::make_pair(Idx, *IntersectedAS));
1942 }
1943
1944 llvm::sort(IntersectedAttrs, llvm::less_first());
1945 return AttributeList::get(C, IntersectedAttrs);
1946}
1947
1948//===----------------------------------------------------------------------===//
1949// AttributeList Accessor Methods
1950//===----------------------------------------------------------------------===//
1951
1952AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const {
1953 return getAttributes(ArgNo + FirstArgIndex);
1954}
1955
1956AttributeSet AttributeList::getRetAttrs() const {
1957 return getAttributes(ReturnIndex);
1958}
1959
1960AttributeSet AttributeList::getFnAttrs() const {
1961 return getAttributes(FunctionIndex);
1962}
1963
1964bool AttributeList::hasAttributeAtIndex(unsigned Index,
1965 Attribute::AttrKind Kind) const {
1966 return getAttributes(Index).hasAttribute(Kind);
1967}
1968
1969bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1970 return getAttributes(Index).hasAttribute(Kind);
1971}
1972
1973bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1974 return getAttributes(Index).hasAttributes();
1975}
1976
1977bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const {
1978 return pImpl && pImpl->hasFnAttribute(Kind);
1979}
1980
1981bool AttributeList::hasFnAttr(StringRef Kind) const {
1982 return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind);
1983}
1984
1985bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1986 unsigned *Index) const {
1987 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1988}
1989
1990Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1991 Attribute::AttrKind Kind) const {
1992 return getAttributes(Index).getAttribute(Kind);
1993}
1994
1995Attribute AttributeList::getAttributeAtIndex(unsigned Index,
1996 StringRef Kind) const {
1997 return getAttributes(Index).getAttribute(Kind);
1998}
1999
2000MaybeAlign AttributeList::getRetAlignment() const {
2001 return getAttributes(ReturnIndex).getAlignment();
2002}
2003
2004MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
2005 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
2006}
2007
2008MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
2009 return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
2010}
2011
2012Type *AttributeList::getParamByValType(unsigned Index) const {
2013 return getAttributes(Index+FirstArgIndex).getByValType();
2014}
2015
2016Type *AttributeList::getParamStructRetType(unsigned Index) const {
2017 return getAttributes(Index + FirstArgIndex).getStructRetType();
2018}
2019
2020Type *AttributeList::getParamByRefType(unsigned Index) const {
2021 return getAttributes(Index + FirstArgIndex).getByRefType();
2022}
2023
2024Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
2025 return getAttributes(Index + FirstArgIndex).getPreallocatedType();
2026}
2027
2028Type *AttributeList::getParamInAllocaType(unsigned Index) const {
2029 return getAttributes(Index + FirstArgIndex).getInAllocaType();
2030}
2031
2032Type *AttributeList::getParamElementType(unsigned Index) const {
2033 return getAttributes(Index + FirstArgIndex).getElementType();
2034}
2035
2036MaybeAlign AttributeList::getFnStackAlignment() const {
2037 return getFnAttrs().getStackAlignment();
2038}
2039
2040MaybeAlign AttributeList::getRetStackAlignment() const {
2041 return getRetAttrs().getStackAlignment();
2042}
2043
2044uint64_t AttributeList::getRetDereferenceableBytes() const {
2045 return getRetAttrs().getDereferenceableBytes();
2046}
2047
2048uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const {
2049 return getParamAttrs(Index).getDereferenceableBytes();
2050}
2051
2052uint64_t AttributeList::getRetDereferenceableOrNullBytes() const {
2053 return getRetAttrs().getDereferenceableOrNullBytes();
2054}
2055
2056DeadOnReturnInfo AttributeList::getDeadOnReturnInfo(unsigned Index) const {
2057 return getParamAttrs(Index).getDeadOnReturnInfo();
2058}
2059
2061AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
2062 return getParamAttrs(Index).getDereferenceableOrNullBytes();
2063}
2064
2065std::optional<ConstantRange>
2066AttributeList::getParamRange(unsigned ArgNo) const {
2067 auto RangeAttr = getParamAttrs(ArgNo).getAttribute(Attribute::Range);
2068 if (RangeAttr.isValid())
2069 return RangeAttr.getRange();
2070 return std::nullopt;
2071}
2072
2073FPClassTest AttributeList::getRetNoFPClass() const {
2074 return getRetAttrs().getNoFPClass();
2075}
2076
2077FPClassTest AttributeList::getParamNoFPClass(unsigned Index) const {
2078 return getParamAttrs(Index).getNoFPClass();
2079}
2080
2081UWTableKind AttributeList::getUWTableKind() const {
2082 return getFnAttrs().getUWTableKind();
2083}
2084
2085AllocFnKind AttributeList::getAllocKind() const {
2086 return getFnAttrs().getAllocKind();
2087}
2088
2089MemoryEffects AttributeList::getMemoryEffects() const {
2090 return getFnAttrs().getMemoryEffects();
2091}
2092
2093std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
2094 return getAttributes(Index).getAsString(InAttrGrp);
2095}
2096
2097AttributeSet AttributeList::getAttributes(unsigned Index) const {
2098 Index = attrIdxToArrayIdx(Index);
2099 if (!pImpl || Index >= getNumAttrSets())
2100 return {};
2101 return pImpl->begin()[Index];
2102}
2103
2104bool AttributeList::hasParentContext(LLVMContext &C) const {
2105 assert(!isEmpty() && "an empty attribute list has no parent context");
2107 return C.pImpl->AttrsLists.lookup(pImpl->getKey(), Token) == pImpl;
2108}
2109
2110AttributeList::iterator AttributeList::begin() const {
2111 return pImpl ? pImpl->begin() : nullptr;
2112}
2113
2114AttributeList::iterator AttributeList::end() const {
2115 return pImpl ? pImpl->end() : nullptr;
2116}
2117
2118//===----------------------------------------------------------------------===//
2119// AttributeList Introspection Methods
2120//===----------------------------------------------------------------------===//
2121
2122unsigned AttributeList::getNumAttrSets() const {
2123 return pImpl ? pImpl->NumAttrSets : 0;
2124}
2125
2126void AttributeList::print(raw_ostream &O) const {
2127 O << "AttributeList[\n";
2128
2129 for (unsigned i : indexes()) {
2130 if (!getAttributes(i).hasAttributes())
2131 continue;
2132 O << " { ";
2133 switch (i) {
2134 case AttrIndex::ReturnIndex:
2135 O << "return";
2136 break;
2137 case AttrIndex::FunctionIndex:
2138 O << "function";
2139 break;
2140 default:
2141 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
2142 }
2143 O << " => " << getAsString(i) << " }\n";
2144 }
2145
2146 O << "]\n";
2147}
2148
2149#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2150LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
2151#endif
2152
2153//===----------------------------------------------------------------------===//
2154// AttrBuilder Method Implementations
2155//===----------------------------------------------------------------------===//
2156
2157AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
2158 append_range(Attrs, AS);
2159 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
2160}
2161
2162void AttrBuilder::clear() { Attrs.clear(); }
2163
2164template <typename K>
2166 Attribute Attr) {
2167 auto It = lower_bound(Attrs, Kind, AttributeComparator());
2168 if (It != Attrs.end() && It->hasAttribute(Kind))
2169 std::swap(*It, Attr);
2170 else
2171 Attrs.insert(It, Attr);
2172}
2173
2174AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
2175 if (Attr.isStringAttribute())
2176 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
2177 else
2178 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
2179 return *this;
2180}
2181
2182AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
2183 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
2184 return *this;
2185}
2186
2187AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
2188 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
2189 return *this;
2190}
2191
2192AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
2193 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
2194 auto It = lower_bound(Attrs, Val, AttributeComparator());
2195 if (It != Attrs.end() && It->hasAttribute(Val))
2196 Attrs.erase(It);
2197 return *this;
2198}
2199
2200AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
2201 auto It = lower_bound(Attrs, A, AttributeComparator());
2202 if (It != Attrs.end() && It->hasAttribute(A))
2203 Attrs.erase(It);
2204 return *this;
2205}
2206
2207std::optional<uint64_t>
2208AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
2209 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
2210 Attribute A = getAttribute(Kind);
2211 if (A.isValid())
2212 return A.getValueAsInt();
2213 return std::nullopt;
2214}
2215
2216AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
2217 uint64_t Value) {
2218 return addAttribute(Attribute::get(Ctx, Kind, Value));
2219}
2220
2221std::optional<std::pair<unsigned, std::optional<unsigned>>>
2222AttrBuilder::getAllocSizeArgs() const {
2223 Attribute A = getAttribute(Attribute::AllocSize);
2224 if (A.isValid())
2225 return A.getAllocSizeArgs();
2226 return std::nullopt;
2227}
2228
2229AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
2230 if (!Align)
2231 return *this;
2232
2233 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
2234 return addRawIntAttr(Attribute::Alignment, Align->value());
2235}
2236
2237AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
2238 // Default alignment, allow the target to define how to align it.
2239 if (!Align)
2240 return *this;
2241
2242 assert(*Align <= 0x100 && "Alignment too large.");
2243 return addRawIntAttr(Attribute::StackAlignment, Align->value());
2244}
2245
2246AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
2247 if (Bytes == 0) return *this;
2248
2249 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
2250}
2251
2252AttrBuilder &AttrBuilder::addDeadOnReturnAttr(DeadOnReturnInfo Info) {
2253 if (Info.isZeroSized())
2254 return *this;
2255
2256 return addRawIntAttr(Attribute::DeadOnReturn, Info.toIntValue());
2257}
2258
2259AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
2260 if (Bytes == 0)
2261 return *this;
2262
2263 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
2264}
2265
2266AttrBuilder &
2267AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
2268 const std::optional<unsigned> &NumElems) {
2269 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
2270}
2271
2272AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
2273 // (0, 0) is our "not present" value, so we need to check for it here.
2274 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
2275 return addRawIntAttr(Attribute::AllocSize, RawArgs);
2276}
2277
2278AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
2279 std::optional<unsigned> MaxValue) {
2280 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
2281}
2282
2283AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
2284 // (0, 0) is not present hence ignore this case
2285 if (RawArgs == 0)
2286 return *this;
2287
2288 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
2289}
2290
2291AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
2292 if (Kind == UWTableKind::None)
2293 return *this;
2294 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
2295}
2296
2297AttrBuilder &AttrBuilder::addMemoryAttr(MemoryEffects ME) {
2298 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
2299}
2300
2301AttrBuilder &AttrBuilder::addCapturesAttr(CaptureInfo CI) {
2302 return addRawIntAttr(Attribute::Captures, CI.toIntValue());
2303}
2304
2305AttrBuilder &AttrBuilder::addDenormalFPEnvAttr(DenormalFPEnv FPEnv) {
2306 return addRawIntAttr(Attribute::DenormalFPEnv, FPEnv.toIntValue());
2307}
2308
2309AttrBuilder &AttrBuilder::addNoFPClassAttr(FPClassTest Mask) {
2310 if (Mask == fcNone)
2311 return *this;
2312
2313 return addRawIntAttr(Attribute::NoFPClass, Mask);
2314}
2315
2316AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
2317 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
2318}
2319
2320Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
2321 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
2322 Attribute A = getAttribute(Kind);
2323 return A.isValid() ? A.getValueAsType() : nullptr;
2324}
2325
2326AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
2327 return addAttribute(Attribute::get(Ctx, Kind, Ty));
2328}
2329
2330AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
2331 return addTypeAttr(Attribute::ByVal, Ty);
2332}
2333
2334AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
2335 return addTypeAttr(Attribute::StructRet, Ty);
2336}
2337
2338AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
2339 return addTypeAttr(Attribute::ByRef, Ty);
2340}
2341
2342AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
2343 return addTypeAttr(Attribute::Preallocated, Ty);
2344}
2345
2346AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
2347 return addTypeAttr(Attribute::InAlloca, Ty);
2348}
2349
2350AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind,
2351 const ConstantRange &CR) {
2352 if (CR.isFullSet())
2353 return *this;
2354
2355 return addAttribute(Attribute::get(Ctx, Kind, CR));
2356}
2357
2358AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) {
2359 return addConstantRangeAttr(Attribute::Range, CR);
2360}
2361
2362AttrBuilder &
2363AttrBuilder::addConstantRangeListAttr(Attribute::AttrKind Kind,
2365 return addAttribute(Attribute::get(Ctx, Kind, Val));
2366}
2367
2368AttrBuilder &AttrBuilder::addInitializesAttr(const ConstantRangeList &CRL) {
2369 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2370}
2371
2372AttrBuilder &AttrBuilder::addFromEquivalentMetadata(const Instruction &I) {
2373 if (I.hasMetadata(LLVMContext::MD_nonnull))
2374 addAttribute(Attribute::NonNull);
2375
2376 if (I.hasMetadata(LLVMContext::MD_noundef))
2377 addAttribute(Attribute::NoUndef);
2378
2379 if (const MDNode *Align = I.getMetadata(LLVMContext::MD_align)) {
2380 ConstantInt *CI = mdconst::extract<ConstantInt>(Align->getOperand(0));
2381 addAlignmentAttr(CI->getZExtValue());
2382 }
2383
2384 if (const MDNode *Dereferenceable =
2385 I.getMetadata(LLVMContext::MD_dereferenceable)) {
2386 ConstantInt *CI =
2387 mdconst::extract<ConstantInt>(Dereferenceable->getOperand(0));
2388 addDereferenceableAttr(CI->getZExtValue());
2389 }
2390
2391 if (const MDNode *DereferenceableOrNull =
2392 I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) {
2393 ConstantInt *CI =
2394 mdconst::extract<ConstantInt>(DereferenceableOrNull->getOperand(0));
2395 addDereferenceableAttr(CI->getZExtValue());
2396 }
2397
2398 if (const MDNode *Range = I.getMetadata(LLVMContext::MD_range))
2399 addRangeAttr(getConstantRangeFromMetadata(*Range));
2400
2401 if (const MDNode *NoFPClass = I.getMetadata(LLVMContext::MD_nofpclass)) {
2402 ConstantInt *CI = mdconst::extract<ConstantInt>(NoFPClass->getOperand(0));
2403 addNoFPClassAttr(static_cast<FPClassTest>(CI->getZExtValue()));
2404 }
2405
2406 return *this;
2407}
2408
2409/// Merge \p B into \p A, both sorted by kind, into \p Merged. An attribute
2410/// in \p B replaces the attribute of the same kind in \p A.
2413 Merged.reserve(A.size() + B.size());
2415 auto *I = A.begin(), *E = A.end();
2416
2417 for (Attribute BAttr : B) {
2418 while (I != E && Less(*I, BAttr))
2419 Merged.push_back(*I++);
2420
2421 if (I != E && !Less(BAttr, *I))
2422 ++I;
2423
2424 Merged.push_back(BAttr);
2425 }
2426
2427 Merged.append(I, E);
2428}
2429
2430AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
2431 if (B.Attrs.empty())
2432 return *this;
2433
2434 if (Attrs.empty()) {
2435 Attrs = B.Attrs;
2436 return *this;
2437 }
2438
2439 // Both lists are already sorted by kind.
2441 mergeSortedAttrs(Attrs, B.Attrs, Merged);
2442 Attrs = std::move(Merged);
2443 return *this;
2444}
2445
2448 ArrayRef<Attribute> Attrs) const {
2449 if (Attrs.empty())
2450 return *this;
2451
2452 assert(isSortedAndUnique(Attrs) &&
2453 "Expected sorted attributes with distinct kinds!");
2454
2456 mergeSortedAttrs(ArrayRef(begin(), end()), Attrs, Merged);
2458}
2459
2460AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
2461 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2462 return *this;
2463}
2464
2465bool AttrBuilder::overlaps(const AttributeMask &AM) const {
2466 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2467}
2468
2469Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
2470 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2471 auto It = lower_bound(Attrs, A, AttributeComparator());
2472 if (It != Attrs.end() && It->hasAttribute(A))
2473 return *It;
2474 return {};
2475}
2476
2477Attribute AttrBuilder::getAttribute(StringRef A) const {
2478 auto It = lower_bound(Attrs, A, AttributeComparator());
2479 if (It != Attrs.end() && It->hasAttribute(A))
2480 return *It;
2481 return {};
2482}
2483
2484std::optional<ConstantRange> AttrBuilder::getRange() const {
2485 const Attribute RangeAttr = getAttribute(Attribute::Range);
2486 if (RangeAttr.isValid())
2487 return RangeAttr.getRange();
2488 return std::nullopt;
2489}
2490
2491bool AttrBuilder::contains(Attribute::AttrKind A) const {
2492 return getAttribute(A).isValid();
2493}
2494
2495bool AttrBuilder::contains(StringRef A) const {
2496 return getAttribute(A).isValid();
2497}
2498
2499bool AttrBuilder::operator==(const AttrBuilder &B) const {
2500 return Attrs == B.Attrs;
2501}
2502
2503//===----------------------------------------------------------------------===//
2504// AttributeFuncs Function Defintions
2505//===----------------------------------------------------------------------===//
2506
2507/// Returns true if this is a type legal for the 'nofpclass' attribute. This
2508/// follows the same type rules as FPMathOperator.
2509bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
2511}
2512
2513/// Which attributes cannot be applied to a type.
2514AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
2515 AttributeSafetyKind ASK) {
2516 AttributeMask Incompatible;
2517
2518 if (!Ty->isIntegerTy()) {
2519 // Attributes that only apply to integers.
2520 if (ASK & ASK_SAFE_TO_DROP)
2521 Incompatible.addAttribute(Attribute::AllocAlign);
2522 }
2523
2524 if (!Ty->isIntegerTy() && !Ty->isByteTy()) {
2525 // Attributes that only apply to integers and bytes.
2526 if (ASK & ASK_UNSAFE_TO_DROP)
2527 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2528 }
2529
2530 if (!Ty->isIntOrIntVectorTy()) {
2531 // Attributes that only apply to integers or vector of integers.
2532 if (ASK & ASK_SAFE_TO_DROP)
2533 Incompatible.addAttribute(Attribute::Range);
2534 } else {
2535 Attribute RangeAttr = AS.getAttribute(Attribute::Range);
2536 if (RangeAttr.isValid() &&
2537 RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())
2538 Incompatible.addAttribute(Attribute::Range);
2539 }
2540
2541 if (!Ty->isPointerTy()) {
2542 // Attributes that only apply to pointers.
2543 if (ASK & ASK_SAFE_TO_DROP)
2544 Incompatible.addAttribute(Attribute::NoAlias)
2545 .addAttribute(Attribute::NonNull)
2546 .addAttribute(Attribute::ReadNone)
2547 .addAttribute(Attribute::ReadOnly)
2548 .addAttribute(Attribute::Dereferenceable)
2549 .addAttribute(Attribute::DereferenceableOrNull)
2550 .addAttribute(Attribute::Writable)
2551 .addAttribute(Attribute::DeadOnUnwind)
2552 .addAttribute(Attribute::Initializes)
2553 .addAttribute(Attribute::Captures)
2554 .addAttribute(Attribute::DeadOnReturn)
2555 .addAttribute(Attribute::NoFree)
2556 .addAttribute(Attribute::NoFreeObj);
2557 if (ASK & ASK_UNSAFE_TO_DROP)
2558 Incompatible.addAttribute(Attribute::Nest)
2559 .addAttribute(Attribute::SwiftError)
2560 .addAttribute(Attribute::Preallocated)
2561 .addAttribute(Attribute::InAlloca)
2562 .addAttribute(Attribute::ByVal)
2563 .addAttribute(Attribute::StructRet)
2564 .addAttribute(Attribute::ByRef)
2565 .addAttribute(Attribute::ElementType)
2566 .addAttribute(Attribute::AllocatedPointer);
2567 }
2568
2569 // Attributes that only apply to pointers or vectors of pointers.
2570 if (!Ty->isPtrOrPtrVectorTy()) {
2571 if (ASK & ASK_SAFE_TO_DROP)
2572 Incompatible.addAttribute(Attribute::Alignment);
2573 }
2574
2575 if (ASK & ASK_SAFE_TO_DROP) {
2576 if (!isNoFPClassCompatibleType(Ty))
2577 Incompatible.addAttribute(Attribute::NoFPClass);
2578 }
2579
2580 // Some attributes can apply to all "values" but there are no `void` values.
2581 if (Ty->isVoidTy()) {
2582 if (ASK & ASK_SAFE_TO_DROP)
2583 Incompatible.addAttribute(Attribute::NoUndef);
2584 }
2585
2586 return Incompatible;
2587}
2588
2589AttributeMask AttributeFuncs::getUBImplyingAttributes() {
2590 AttributeMask AM;
2591 AM.addAttribute(Attribute::NoUndef);
2592 AM.addAttribute(Attribute::Dereferenceable);
2593 AM.addAttribute(Attribute::DereferenceableOrNull);
2594 return AM;
2595}
2596
2597/// Callees with dynamic denormal modes are compatible with any caller mode.
2598static bool denormModeCompatible(DenormalMode CallerMode,
2599 DenormalMode CalleeMode) {
2600 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2601 return true;
2602
2603 // If they don't exactly match, it's OK if the mismatched component is
2604 // dynamic.
2605 if (CalleeMode.Input == CallerMode.Input &&
2606 CalleeMode.Output == DenormalMode::Dynamic)
2607 return true;
2608
2609 if (CalleeMode.Output == CallerMode.Output &&
2610 CalleeMode.Input == DenormalMode::Dynamic)
2611 return true;
2612 return false;
2613}
2614
2615static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2616 DenormalFPEnv CallerEnv = Caller.getDenormalFPEnv();
2617 DenormalFPEnv CalleeEnv = Callee.getDenormalFPEnv();
2618
2619 if (denormModeCompatible(CallerEnv.DefaultMode, CalleeEnv.DefaultMode)) {
2620 DenormalMode CallerModeF32 = CallerEnv.F32Mode;
2621 DenormalMode CalleeModeF32 = CalleeEnv.F32Mode;
2622 if (CallerModeF32 == DenormalMode::getInvalid())
2623 CallerModeF32 = CallerEnv.DefaultMode;
2624 if (CalleeModeF32 == DenormalMode::getInvalid())
2625 CalleeModeF32 = CalleeEnv.DefaultMode;
2626 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2627 }
2628
2629 return false;
2630}
2631
2632static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2633 // Do not inline strictfp function into non-strictfp one. It would require
2634 // conversion of all FP operations in host function to constrained intrinsics.
2635 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2636 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2637}
2638
2639template<typename AttrClass>
2640static bool isEqual(const Function &Caller, const Function &Callee) {
2641 return Caller.getFnAttribute(AttrClass::getKind()) ==
2642 Callee.getFnAttribute(AttrClass::getKind());
2643}
2644
2645static bool isEqual(const Function &Caller, const Function &Callee,
2646 const StringRef &AttrName) {
2647 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2648}
2649
2650/// Compute the logical AND of the attributes of the caller and the
2651/// callee.
2652///
2653/// This function sets the caller's attribute to false if the callee's attribute
2654/// is false.
2655template<typename AttrClass>
2656static void setAND(Function &Caller, const Function &Callee) {
2657 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2658 !AttrClass::isSet(Callee, AttrClass::getKind()))
2659 AttrClass::set(Caller, AttrClass::getKind(), false);
2660}
2661
2662/// Compute the logical OR of the attributes of the caller and the
2663/// callee.
2664///
2665/// This function sets the caller's attribute to true if the callee's attribute
2666/// is true.
2667template<typename AttrClass>
2668static void setOR(Function &Caller, const Function &Callee) {
2669 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2670 AttrClass::isSet(Callee, AttrClass::getKind()))
2671 AttrClass::set(Caller, AttrClass::getKind(), true);
2672}
2673
2674/// If the inlined function had a higher stack protection level than the
2675/// calling function, then bump up the caller's stack protection level.
2676static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2677 // If the calling function has *no* stack protection level (e.g. it was built
2678 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2679 // change it as that could change the program's semantics.
2680 if (!Caller.hasStackProtectorFnAttr())
2681 return;
2682
2683 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2684 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2685 // clutter to the IR.
2686 AttributeMask OldSSPAttr;
2687 OldSSPAttr.addAttribute(Attribute::StackProtect)
2688 .addAttribute(Attribute::StackProtectStrong)
2689 .addAttribute(Attribute::StackProtectReq);
2690
2691 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2692 Caller.removeFnAttrs(OldSSPAttr);
2693 Caller.addFnAttr(Attribute::StackProtectReq);
2694 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2695 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2696 Caller.removeFnAttrs(OldSSPAttr);
2697 Caller.addFnAttr(Attribute::StackProtectStrong);
2698 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2699 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2700 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2701 Caller.addFnAttr(Attribute::StackProtect);
2702}
2703
2704/// If the inlined function required stack probes, then ensure that
2705/// the calling function has those too.
2706static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2707 if (!Caller.hasFnAttribute("probe-stack") &&
2708 Callee.hasFnAttribute("probe-stack")) {
2709 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2710 }
2711}
2712
2713/// If the inlined function defines the size of guard region
2714/// on the stack, then ensure that the calling function defines a guard region
2715/// that is no larger.
2716static void
2718 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2719 if (CalleeAttr.isValid()) {
2720 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2721 if (CallerAttr.isValid()) {
2722 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2723 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2724 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2725
2726 if (CallerStackProbeSize > CalleeStackProbeSize) {
2727 Caller.addFnAttr(CalleeAttr);
2728 }
2729 } else {
2730 Caller.addFnAttr(CalleeAttr);
2731 }
2732 }
2733}
2734
2735/// If the inlined function defines a min legal vector width, then ensure
2736/// the calling function has the same or larger min legal vector width. If the
2737/// caller has the attribute, but the callee doesn't, we need to remove the
2738/// attribute from the caller since we can't make any guarantees about the
2739/// caller's requirements.
2740/// This function is called after the inlining decision has been made so we have
2741/// to merge the attribute this way. Heuristics that would use
2742/// min-legal-vector-width to determine inline compatibility would need to be
2743/// handled as part of inline cost analysis.
2744static void
2746 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2747 if (CallerAttr.isValid()) {
2748 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2749 if (CalleeAttr.isValid()) {
2750 uint64_t CallerVectorWidth, CalleeVectorWidth;
2751 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2752 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2753 if (CallerVectorWidth < CalleeVectorWidth)
2754 Caller.addFnAttr(CalleeAttr);
2755 } else {
2756 // If the callee doesn't have the attribute then we don't know anything
2757 // and must drop the attribute from the caller.
2758 Caller.removeFnAttr("min-legal-vector-width");
2759 }
2760 }
2761}
2762
2763/// If the inlined function has null_pointer_is_valid attribute,
2764/// set this attribute in the caller post inlining.
2765static void
2767 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2768 Caller.addFnAttr(Attribute::NullPointerIsValid);
2769 }
2770}
2771
2772struct EnumAttr {
2773 static bool isSet(const Function &Fn,
2774 Attribute::AttrKind Kind) {
2775 return Fn.hasFnAttribute(Kind);
2776 }
2777
2778 static void set(Function &Fn,
2779 Attribute::AttrKind Kind, bool Val) {
2780 if (Val)
2781 Fn.addFnAttr(Kind);
2782 else
2783 Fn.removeFnAttr(Kind);
2784 }
2785};
2786
2788 static bool isSet(const Function &Fn,
2789 StringRef Kind) {
2790 auto A = Fn.getFnAttribute(Kind);
2791 return A.getValueAsString() == "true";
2792 }
2793
2794 static void set(Function &Fn,
2795 StringRef Kind, bool Val) {
2796 Fn.addFnAttr(Kind, Val ? "true" : "false");
2797 }
2798};
2799
2800#define GET_ATTR_NAMES
2801#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2802 struct ENUM_NAME##Attr : EnumAttr { \
2803 static enum Attribute::AttrKind getKind() { \
2804 return llvm::Attribute::ENUM_NAME; \
2805 } \
2806 };
2807#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2808 struct ENUM_NAME##Attr : StrBoolAttr { \
2809 static StringRef getKind() { return #DISPLAY_NAME; } \
2810 };
2811#include "llvm/IR/Attributes.inc"
2812
2813#define GET_ATTR_COMPAT_FUNC
2814#include "llvm/IR/Attributes.inc"
2815
2816bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2817 const Function &Callee) {
2818 return hasCompatibleFnAttrs(Caller, Callee);
2819}
2820
2821bool AttributeFuncs::isStrictFPInlineCompatible(const Function &Caller,
2822 const Function &Callee) {
2823 return checkStrictFP(Caller, Callee);
2824}
2825
2826bool AttributeFuncs::areOutlineCompatible(const Function &A,
2827 const Function &B) {
2828 return hasCompatibleFnAttrs(A, B);
2829}
2830
2831void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2832 const Function &Callee) {
2833 mergeFnAttrs(Caller, Callee);
2834}
2835
2836void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2837 const Function &ToMerge) {
2838
2839 // We merge functions so that they meet the most general case.
2840 // For example, if the NoNansFPMathAttr is set in one function, but not in
2841 // the other, in the merged function we can say that the NoNansFPMathAttr
2842 // is not set.
2843 // However if we have the SpeculativeLoadHardeningAttr set true in one
2844 // function, but not the other, we make sure that the function retains
2845 // that aspect in the merged function.
2846 mergeFnAttrs(Base, ToMerge);
2847}
2848
2849void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
2850 uint64_t Width) {
2851 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2852 if (Attr.isValid()) {
2853 uint64_t OldWidth;
2854 Attr.getValueAsString().getAsInteger(0, OldWidth);
2855 if (Width > OldWidth)
2856 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2857 }
2858}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
This file defines various helper methods and classes used by LLVMContextImpl for creating and managin...
static void addAttributeImpl(SmallVectorImpl< Attribute > &Attrs, K Kind, Attribute Attr)
static void setAND(Function &Caller, const Function &Callee)
Compute the logical AND of the attributes of the caller and the callee.
static void adjustCallerStackProbes(Function &Caller, const Function &Callee)
If the inlined function required stack probes, then ensure that the calling function has those too.
static std::pair< unsigned, std::optional< unsigned > > unpackVScaleRangeArgs(uint64_t Value)
static void adjustMinLegalVectorWidth(Function &Caller, const Function &Callee)
If the inlined function defines a min legal vector width, then ensure the calling function has the sa...
AttributeProperty
@ RetAttr
@ IntersectPreserve
@ IntersectMin
@ IntersectCustom
@ ParamAttr
@ FnAttr
@ IntersectPropertyMask
@ IntersectAnd
@ ABIAttr
static void adjustCallerStackProbeSize(Function &Caller, const Function &Callee)
If the inlined function defines the size of guard region on the stack, then ensure that the calling f...
static void adjustCallerSSPLevel(Function &Caller, const Function &Callee)
If the inlined function had a higher stack protection level than the calling function,...
static bool checkStrictFP(const Function &Caller, const Function &Callee)
static bool isSortedAndUnique(ArrayRef< Attribute > Attrs)
Return true if Attrs is known sorted with no duplicate entries.
static uint64_t packAllocSizeArgs(unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
static uint64_t packVScaleRangeArgs(unsigned MinValue, std::optional< unsigned > MaxValue)
static bool hasIntersectProperty(Attribute::AttrKind Kind, AttributeProperty Prop)
static unsigned attrIdxToArrayIdx(unsigned Index)
Map from AttributeList index to the internal array index.
static bool denormModeCompatible(DenormalMode CallerMode, DenormalMode CalleeMode)
Callees with dynamic denormal modes are compatible with any caller mode.
static void adjustNullPointerValidAttr(Function &Caller, const Function &Callee)
If the inlined function has null_pointer_is_valid attribute, set this attribute in the caller post in...
static const unsigned AllocSizeNumElemsNotPresent
static std::pair< unsigned, std::optional< unsigned > > unpackAllocSizeArgs(uint64_t Num)
static bool checkDenormMode(const Function &Caller, const Function &Callee)
static unsigned getAttributeProperties(Attribute::AttrKind Kind)
static void setOR(Function &Caller, const Function &Callee)
Compute the logical OR of the attributes of the caller and the callee.
static bool hasAttributeProperty(Attribute::AttrKind Kind, AttributeProperty Prop)
static void mergeSortedAttrs(ArrayRef< Attribute > A, ArrayRef< Attribute > B, SmallVectorImpl< Attribute > &Merged)
Merge B into A, both sorted by kind, into Merged.
static const char * getModRefStr(ModRefInfo MR)
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:682
This file defines a hash set that can be used to remove duplication of nodes in a graph.
static constexpr Value * getValue(Ty &ValueOrUse)
#define I(x, y, z)
Definition MD5.cpp:57
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
LLVM_ABI void Profile(FoldingSetNodeID &id) const
Used to insert APInt objects, or objects that contain APInt objects, into FoldingSets.
Definition APInt.cpp:152
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & back() const
Get the last element.
Definition ArrayRef.h:150
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition ArrayRef.h:218
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class represents a single, uniqued attribute.
int cmp(const AttributeImpl &AI, bool KindOnly) const
Used to sort attributes.
bool isConstantRangeAttribute() const
bool hasAttribute(Attribute::AttrKind A) const
Type * getValueAsType() const
Attribute::AttrKind getKindAsEnum() const
bool operator<(const AttributeImpl &AI) const
Used when sorting the attributes.
uint64_t getValueAsInt() const
bool isIntAttribute() const
bool isTypeAttribute() const
AttributeImpl(AttrEntryKind KindID)
bool getValueAsBool() const
StringRef getKindAsString() const
StringRef getValueAsString() const
bool isEnumAttribute() const
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
bool isConstantRangeListAttribute() const
bool isStringAttribute() const
const ConstantRange & getValueAsConstantRange() const
This class represents a set of attributes that apply to the function, return type,...
bool hasAttrSomewhere(Attribute::AttrKind Kind, unsigned *Index=nullptr) const
Return true if the specified attribute is set for at least one parameter or for the return value.
iterator begin() const
AttributeListImpl(ArrayRef< AttributeSet > Sets)
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
bool contains(Attribute::AttrKind A) const
Return true if the builder has the specified attribute.
MaybeAlign getStackAlignment() const
uint64_t getDereferenceableOrNullBytes() const
std::optional< unsigned > getVScaleRangeMax() const
bool hasAttribute(Attribute::AttrKind Kind) const
Type * getAttributeType(Attribute::AttrKind Kind) const
AllocFnKind getAllocKind() const
CaptureInfo getCaptureInfo() const
unsigned getVScaleRangeMin() const
static AttributeSetNode * getSorted(LLVMContext &C, ArrayRef< Attribute > SortedAttrs)
MaybeAlign getAlignment() const
MemoryEffects getMemoryEffects() const
iterator begin() const
UWTableKind getUWTableKind() const
std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
iterator end() const
DeadOnReturnInfo getDeadOnReturnInfo() const
const Attribute * iterator
uint64_t getDereferenceableBytes() const
std::string getAsString(bool InAttrGrp) const
static AttributeSetNode * get(LLVMContext &C, const AttrBuilder &B)
FPClassTest getNoFPClass() const
Attribute getAttribute(Attribute::AttrKind Kind) const
This class holds the attributes for a particular argument, parameter, function, or return value.
Definition Attributes.h:406
LLVM_ABI AllocFnKind getAllocKind() const
bool hasAttributes() const
Return true if attributes exists in this set.
Definition Attributes.h:484
const Attribute * iterator
Definition Attributes.h:523
LLVM_ABI AttributeSet removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Remove the specified attribute from this set.
LLVM_ABI Type * getInAllocaType() const
LLVM_ABI Type * getByValType() const
LLVM_ABI DeadOnReturnInfo getDeadOnReturnInfo() const
LLVM_ABI AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
LLVM_ABI std::optional< AttributeSet > intersectWith(LLVMContext &C, AttributeSet Other) const
Try to intersect this AttributeSet with Other.
LLVM_ABI Type * getStructRetType() const
LLVM_ABI std::string getAsString(bool InAttrGrp=false) const
LLVM_ABI unsigned getVScaleRangeMin() const
LLVM_ABI std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
LLVM_ABI UWTableKind getUWTableKind() const
LLVM_ABI bool hasParentContext(LLVMContext &C) const
Return true if this attribute set belongs to the LLVMContext.
LLVM_ABI iterator begin() const
LLVM_ABI iterator end() const
LLVM_ABI AttributeSet addSortedAttributes(LLVMContext &C, ArrayRef< Attribute > Attrs) const
Add attributes to the attribute set, replacing attributes of the same kind.
LLVM_ABI AttributeSet removeAttributes(LLVMContext &C, const AttributeMask &AttrsToRemove) const
Remove the specified attributes from this set.
LLVM_ABI std::optional< unsigned > getVScaleRangeMax() const
LLVM_ABI MaybeAlign getStackAlignment() const
LLVM_ABI Attribute getAttribute(Attribute::AttrKind Kind) const
Return the attribute object.
LLVM_ABI Type * getPreallocatedType() const
LLVM_ABI uint64_t getDereferenceableBytes() const
LLVM_ABI MaybeAlign getAlignment() const
LLVM_ABI FPClassTest getNoFPClass() const
LLVM_ABI Type * getElementType() const
LLVM_ABI Type * getByRefType() const
LLVM_ABI CaptureInfo getCaptureInfo() const
AttributeSet()=default
AttributeSet is a trivially copyable value type.
static LLVM_ABI AttributeSet get(LLVMContext &C, const AttrBuilder &B)
LLVM_ABI uint64_t getDereferenceableOrNullBytes() const
LLVM_ABI unsigned getNumAttributes() const
Return the number of attributes in this set.
LLVM_ABI AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:106
LLVM_ABI bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
static LLVM_ABI Attribute getWithStructRetType(LLVMContext &Context, Type *Ty)
static LLVM_ABI bool isABIAttr(AttrKind Kind)
Whether this is an ABI attribute (for returns or arguments).
static LLVM_ABI Attribute::AttrKind getAttrKindFromName(StringRef AttrName)
LLVM_ABI bool isEnumAttribute() const
Return true if the attribute is an Attribute::AttrKind type.
static LLVM_ABI Attribute getWithStackAlignment(LLVMContext &Context, Align Alignment)
LLVM_ABI const ConstantRange & getRange() const
Returns the value of the range attribute.
static LLVM_ABI bool intersectWithCustom(AttrKind Kind)
LLVM_ABI bool isIntAttribute() const
Return true if the attribute is an integer attribute.
static LLVM_ABI Attribute getWithByRefType(LLVMContext &Context, Type *Ty)
LLVM_ABI struct DenormalFPEnv getDenormalFPEnv() const
Returns denormal_fpenv.
LLVM_ABI std::optional< unsigned > getVScaleRangeMax() const
Returns the maximum value for the vscale_range attribute or std::nullopt when unknown.
LLVM_ABI uint64_t getValueAsInt() const
Return the attribute's value as an integer.
LLVM_ABI unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
LLVM_ABI AllocFnKind getAllocKind() const
LLVM_ABI bool isConstantRangeAttribute() const
Return true if the attribute is a ConstantRange attribute.
static LLVM_ABI Attribute getWithAllocKind(LLVMContext &Context, AllocFnKind Kind)
LLVM_ABI StringRef getKindAsString() const
Return the attribute's kind as a string.
static LLVM_ABI Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty)
static LLVM_ABI bool intersectWithMin(AttrKind Kind)
static LLVM_ABI Attribute getWithDeadOnReturnInfo(LLVMContext &Context, DeadOnReturnInfo DI)
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static LLVM_ABI bool canUseAsRetAttr(AttrKind Kind)
static bool isTypeAttrKind(AttrKind Kind)
Definition Attributes.h:145
LLVM_ABI std::string getAsString(bool InAttrGrp=false) const
The Attribute is converted to a string of equivalent mnemonic.
LLVM_ABI uint64_t getDereferenceableOrNullBytes() const
Returns the number of dereferenceable_or_null bytes from the dereferenceable_or_null attribute.
static LLVM_ABI Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)
LLVM_ABI std::pair< unsigned, std::optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute.
static LLVM_ABI Attribute getWithUWTableKind(LLVMContext &Context, UWTableKind Kind)
LLVM_ABI FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
static LLVM_ABI Attribute getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
LLVM_ABI Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
Attribute()=default
LLVM_ABI bool getValueAsBool() const
Return the attribute's value as a boolean.
LLVM_ABI ArrayRef< ConstantRange > getInitializes() const
Returns the value of the initializes attribute.
LLVM_ABI const ConstantRange & getValueAsConstantRange() const
Return the attribute's value as a ConstantRange.
LLVM_ABI uint64_t getDereferenceableBytes() const
Returns the number of dereferenceable bytes from the dereferenceable attribute.
static LLVM_ABI Attribute getWithVScaleRangeArgs(LLVMContext &Context, unsigned MinValue, unsigned MaxValue)
LLVM_ABI MemoryEffects getMemoryEffects() const
Returns memory effects.
LLVM_ABI UWTableKind getUWTableKind() const
static LLVM_ABI Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, uint64_t Bytes)
LLVM_ABI ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool hasKindAsEnum() const
Returns true if the attribute's kind can be represented as an enum (Enum, Integer,...
Definition Attributes.h:272
static LLVM_ABI StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind)
static LLVM_ABI bool canUseAsFnAttr(AttrKind Kind)
static LLVM_ABI bool intersectWithAnd(AttrKind Kind)
static LLVM_ABI Attribute getWithNoFPClass(LLVMContext &Context, FPClassTest Mask)
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition Attributes.h:125
@ None
No attributes have been set.
Definition Attributes.h:127
@ EndAttrKinds
Sentinel value useful for loops.
Definition Attributes.h:130
static bool isConstantRangeAttrKind(AttrKind Kind)
Definition Attributes.h:148
LLVM_ABI bool hasParentContext(LLVMContext &C) const
Return true if this attribute belongs to the LLVMContext.
LLVM_ABI bool isTypeAttribute() const
Return true if the attribute is a type attribute.
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
static LLVM_ABI Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty)
static bool isIntAttrKind(AttrKind Kind)
Definition Attributes.h:142
static bool isConstantRangeListAttrKind(AttrKind Kind)
Definition Attributes.h:151
LLVM_ABI bool isConstantRangeListAttribute() const
Return true if the attribute is a ConstantRangeList attribute.
static LLVM_ABI Attribute getWithByValType(LLVMContext &Context, Type *Ty)
LLVM_ABI bool hasAttribute(AttrKind Val) const
Return true if the attribute is present.
static bool isEnumAttrKind(AttrKind Kind)
Definition Attributes.h:139
static LLVM_ABI Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
static LLVM_ABI bool canUseAsParamAttr(AttrKind Kind)
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:262
LLVM_ABI MaybeAlign getStackAlignment() const
Returns the stack alignment field of an attribute as a byte alignment value.
LLVM_ABI MaybeAlign getAlignment() const
Returns the alignment field of an attribute as a byte alignment value.
LLVM_ABI CaptureInfo getCaptureInfo() const
Returns information from captures attribute.
static LLVM_ABI bool intersectMustPreserve(AttrKind Kind)
LLVM_ABI int cmpKind(Attribute A) const
Used to sort attribute by kind.
LLVM_ABI bool operator<(Attribute A) const
Less-than operator. Useful for sorting the attributes list.
static LLVM_ABI Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
LLVM_ABI DeadOnReturnInfo getDeadOnReturnInfo() const
Returns the number of dead_on_return bytes from the dead_on_return attribute, or std::nullopt if all ...
LLVM_ABI Type * getValueAsType() const
Return the attribute's value as a Type.
Represents which components of the pointer may be captured in which location.
Definition ModRef.h:414
static CaptureInfo createFromIntValue(uint32_t Data)
Definition ModRef.h:485
static CaptureInfo all()
Create CaptureInfo that may capture all components of the pointer.
Definition ModRef.h:430
uint32_t toIntValue() const
Convert CaptureInfo into an encoded integer value (used by captures attribute).
Definition ModRef.h:492
This is the shared class of boolean and integer constants.
Definition Constants.h:87
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
static size_t totalSizeToAlloc(ArrayRef< ConstantRange > Val)
This class represents a list of constant ranges.
ArrayRef< ConstantRange > rangesRef() const
LLVM_ABI void print(raw_ostream &OS) const
Print out the ranges to a stream.
This class represents a range of values.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
const APInt & getUpper() const
Return the upper value for this range.
LLVM_ABI ConstantRange unionWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the union of this range with another range.
uint32_t getBitWidth() const
Get the bit width of this ConstantRange.
static DeadOnReturnInfo createFromIntValue(uint64_t Data)
Definition Attributes.h:80
uint64_t toIntValue() const
Definition Attributes.h:86
A set of classes that contain the value of the attribute object.
static bool isSupportedFloatingPointType(Type *Ty)
Returns true if Ty is a supported floating-point type for phi, select, or call FPMathOperators.
Definition Operator.h:302
Insertion token: a failed lookup fills it in, the matching insert consumes it.
Definition FoldingSet.h:284
This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:162
void AddInteger(signed I)
Definition FoldingSet.h:190
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition Function.cpp:641
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:766
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition Function.cpp:689
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:731
UniquingSet< TypeAttributeImpl > TypeAttrs
EnumAttributeImpl * EnumAttrs[Attribute::NumEnumAttrKinds]
UniquingSet< IntAttributeImpl > IntAttrs
FoldingSet< AttributeImpl > AttrsSet
UniquingSet< StringAttributeImpl > StringAttrs
UniquingSet< AttributeListImpl > AttrsLists
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
Metadata node.
Definition Metadata.h:1081
bool isTargetMemLocSameForAll() const
Whether the target memory locations are all the same.
Definition ModRef.h:289
bool isTargetMemLoc(IRMemLocation Loc) const
Whether location is target memory location.
Definition ModRef.h:279
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition ModRef.h:219
static MemoryEffectsBase createFromIntValue(uint32_t Data)
Definition ModRef.h:208
uint32_t toIntValue() const
Convert MemoryEffectsBase into an encoded integer value (used by memory attribute).
Definition ModRef.h:214
static MemoryEffectsBase unknown()
Definition ModRef.h:123
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static size_t totalSizeToAlloc(StringRef Kind, StringRef Val)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:490
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
int compare(StringRef RHS) const
Compare two strings; the result is negative, zero, or positive if this string is lexicographically le...
Definition StringRef.h:177
A switch()-like statement whose cases are string literals.
static constexpr std::enable_if_t< std::is_same_v< Foo< TrailingTys... >, Foo< Tys... > >, size_t > totalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType< TrailingTys, size_t >::type... Counts)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false, bool NoDetails=false) const
Print the current type.
LLVM Value Representation.
Definition Value.h:75
static constexpr uint64_t MaximumAlignment
Definition Value.h:801
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an std::string.
This class provides various memory handling functions that manipulate MemoryBlock instances.
Definition Memory.h:54
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
LLVM_ABI AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT)
Return the attributes for an intrinsic.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:679
iterator end() const
Definition BasicBlock.h:89
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
AllocFnKind
Definition Attributes.h:54
auto adjacent_find(R &&Range)
Provide wrappers to std::adjacent_find which finds the first pair of adjacent elements that are equal...
Definition STLExtras.h:1834
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
std::string utostr(uint64_t X, bool isNeg=false)
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
Definition ModRef.h:356
LLVM_ABI void printEscapedString(StringRef Name, raw_ostream &Out)
Print each character of the specified string, escaping it if it is not printable or if it is an escap...
LLVM_ABI ConstantRange getConstantRangeFromMetadata(const MDNode &RangeMD)
Parse out a conservative ConstantRange from !range metadata.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
UWTableKind
Definition CodeGen.h:309
@ None
No unwind table requested.
Definition CodeGen.h:310
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1769
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
Definition STLExtras.h:1986
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
Definition ModRef.h:28
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
@ ModRef
The access may reference and may modify the value stored in memory.
Definition ModRef.h:36
@ Mod
The access may modify the value stored in memory.
Definition ModRef.h:34
@ NoModRef
The access neither references nor modifies the value stored in memory.
Definition ModRef.h:30
@ ErrnoMem
Errno memory.
Definition ModRef.h:66
@ ArgMem
Access to memory via argument pointers.
Definition ModRef.h:62
@ TargetMem0
Represents target specific state.
Definition ModRef.h:70
@ Other
Any other memory.
Definition ModRef.h:68
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ InaccessibleMem
Memory that is inaccessible via LLVM IR.
Definition ModRef.h:64
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2068
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1901
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2208
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
Attribute comparator that only compares attribute keys.
bool operator()(Attribute A0, StringRef Kind) const
bool operator()(Attribute A0, Attribute A1) const
bool operator()(Attribute A0, Attribute::AttrKind Kind) const
static void set(Function &Fn, Attribute::AttrKind Kind, bool Val)
static bool isSet(const Function &Fn, Attribute::AttrKind Kind)
static bool isSet(const Function &Fn, StringRef Kind)
static void set(Function &Fn, StringRef Kind, bool Val)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:82
Represents the full denormal controls for a function, including the default mode and the f32 specific...
static constexpr DenormalFPEnv createFromIntValue(uint32_t Data)
LLVM_ABI void print(raw_ostream &OS, bool OmitIfSame=true) const
constexpr uint32_t toIntValue() const
Represent subnormal handling kind for floating point instruction inputs and outputs.
DenormalModeKind Input
Denormal treatment kind for floating point instruction inputs in the default floating-point environme...
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getInvalid()
DenormalModeKind Output
Denormal flushing mode for floating point instruction results in the default floating point environme...
static constexpr DenormalMode getDynamic()
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:111
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:135
Function object to check whether the first component of a container supported by std::get (like std::...
Definition STLExtras.h:1455