LLVM 20.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;
103 ID.AddInteger(Kind);
104 if (IsIntAttr)
105 ID.AddInteger(Val);
106 else
107 assert(Val == 0 && "Value must be zero for enum attributes");
108
109 void *InsertPoint;
110 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
111
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 if (!IsIntAttr)
116 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
117 else
118 PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
119 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
120 }
121
122 // Return the Attribute that we found or created.
123 return Attribute(PA);
124}
125
127 LLVMContextImpl *pImpl = Context.pImpl;
129 ID.AddString(Kind);
130 if (!Val.empty()) ID.AddString(Val);
131
132 void *InsertPoint;
133 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
134
135 if (!PA) {
136 // If we didn't find any existing attributes of the same shape then create a
137 // new one and insert it.
138 void *Mem =
140 alignof(StringAttributeImpl));
141 PA = new (Mem) StringAttributeImpl(Kind, Val);
142 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
143 }
144
145 // Return the Attribute that we found or created.
146 return Attribute(PA);
147}
148
150 Type *Ty) {
151 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
152 LLVMContextImpl *pImpl = Context.pImpl;
154 ID.AddInteger(Kind);
155 ID.AddPointer(Ty);
156
157 void *InsertPoint;
158 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
159
160 if (!PA) {
161 // If we didn't find any existing attributes of the same shape then create a
162 // new one and insert it.
163 PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
164 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
165 }
166
167 // Return the Attribute that we found or created.
168 return Attribute(PA);
169}
170
172 const ConstantRange &CR) {
174 "Not a ConstantRange attribute");
175 assert(!CR.isFullSet() && "ConstantRange attribute must not be full");
176 LLVMContextImpl *pImpl = Context.pImpl;
178 ID.AddInteger(Kind);
179 CR.getLower().Profile(ID);
180 CR.getUpper().Profile(ID);
181
182 void *InsertPoint;
183 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
184
185 if (!PA) {
186 // If we didn't find any existing attributes of the same shape then create a
187 // new one and insert it.
188 PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate())
190 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
191 }
192
193 // Return the Attribute that we found or created.
194 return Attribute(PA);
195}
196
200 "Not a ConstantRangeList attribute");
201 LLVMContextImpl *pImpl = Context.pImpl;
203 ID.AddInteger(Kind);
204 ID.AddInteger(Val.size());
205 for (auto &CR : Val) {
206 CR.getLower().Profile(ID);
207 CR.getUpper().Profile(ID);
208 }
209
210 void *InsertPoint;
211 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
212
213 if (!PA) {
214 // If we didn't find any existing attributes of the same shape then create a
215 // new one and insert it.
216 // ConstantRangeListAttributeImpl is a dynamically sized class and cannot
217 // use SpecificBumpPtrAllocator. Instead, we use normal Alloc for
218 // allocation and record the allocated pointer in
219 // `ConstantRangeListAttributes`. LLVMContext destructor will call the
220 // destructor of the allocated pointer explicitly.
221 void *Mem = pImpl->Alloc.Allocate(
224 PA = new (Mem) ConstantRangeListAttributeImpl(Kind, Val);
225 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
226 pImpl->ConstantRangeListAttributes.push_back(
227 reinterpret_cast<ConstantRangeListAttributeImpl *>(PA));
228 }
229
230 // Return the Attribute that we found or created.
231 return Attribute(PA);
232}
233
235 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.");
236 return get(Context, Alignment, A.value());
237}
238
240 assert(A <= 0x100 && "Alignment too large.");
241 return get(Context, StackAlignment, A.value());
242}
243
245 uint64_t Bytes) {
246 assert(Bytes && "Bytes must be non-zero.");
247 return get(Context, Dereferenceable, Bytes);
248}
249
251 uint64_t Bytes) {
252 assert(Bytes && "Bytes must be non-zero.");
253 return get(Context, DereferenceableOrNull, Bytes);
254}
255
257 return get(Context, ByVal, Ty);
258}
259
261 return get(Context, StructRet, Ty);
262}
263
265 return get(Context, ByRef, Ty);
266}
267
269 return get(Context, Preallocated, Ty);
270}
271
273 return get(Context, InAlloca, Ty);
274}
275
277 UWTableKind Kind) {
278 return get(Context, UWTable, uint64_t(Kind));
279}
280
282 MemoryEffects ME) {
283 return get(Context, Memory, ME.toIntValue());
284}
285
287 FPClassTest ClassMask) {
288 return get(Context, NoFPClass, ClassMask);
289}
290
292Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
293 const std::optional<unsigned> &NumElemsArg) {
294 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
295 "Invalid allocsize arguments -- given allocsize(0, 0)");
296 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
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
330#define GET_ATTR_NAMES
331#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
332#include "llvm/IR/Attributes.inc"
333 .Default(false);
334}
335
336//===----------------------------------------------------------------------===//
337// Attribute Accessor Methods
338//===----------------------------------------------------------------------===//
339
341 return pImpl && pImpl->isEnumAttribute();
342}
343
345 return pImpl && pImpl->isIntAttribute();
346}
347
349 return pImpl && pImpl->isStringAttribute();
350}
351
353 return pImpl && pImpl->isTypeAttribute();
354}
355
357 return pImpl && pImpl->isConstantRangeAttribute();
358}
359
361 return pImpl && pImpl->isConstantRangeListAttribute();
362}
363
365 if (!pImpl) return None;
367 "Invalid attribute type to get the kind as an enum!");
368 return pImpl->getKindAsEnum();
369}
370
372 if (!pImpl) return 0;
374 "Expected the attribute to be an integer attribute!");
375 return pImpl->getValueAsInt();
376}
377
379 if (!pImpl) return false;
381 "Expected the attribute to be a string attribute!");
382 return pImpl->getValueAsBool();
383}
384
386 if (!pImpl) return {};
388 "Invalid attribute type to get the kind as a string!");
389 return pImpl->getKindAsString();
390}
391
393 if (!pImpl) return {};
395 "Invalid attribute type to get the value as a string!");
396 return pImpl->getValueAsString();
397}
398
400 if (!pImpl) return {};
402 "Invalid attribute type to get the value as a type!");
403 return pImpl->getValueAsType();
404}
405
408 "Invalid attribute type to get the value as a ConstantRange!");
409 return pImpl->getValueAsConstantRange();
410}
411
414 "Invalid attribute type to get the value as a ConstantRangeList!");
415 return pImpl->getValueAsConstantRangeList();
416}
417
419 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
420}
421
423 if (!isStringAttribute()) return false;
424 return pImpl && pImpl->hasAttribute(Kind);
425}
426
428 assert(hasAttribute(Attribute::Alignment) &&
429 "Trying to get alignment from non-alignment attribute!");
430 return MaybeAlign(pImpl->getValueAsInt());
431}
432
434 assert(hasAttribute(Attribute::StackAlignment) &&
435 "Trying to get alignment from non-alignment attribute!");
436 return MaybeAlign(pImpl->getValueAsInt());
437}
438
440 assert(hasAttribute(Attribute::Dereferenceable) &&
441 "Trying to get dereferenceable bytes from "
442 "non-dereferenceable attribute!");
443 return pImpl->getValueAsInt();
444}
445
447 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
448 "Trying to get dereferenceable bytes from "
449 "non-dereferenceable attribute!");
450 return pImpl->getValueAsInt();
451}
452
453std::pair<unsigned, std::optional<unsigned>>
455 assert(hasAttribute(Attribute::AllocSize) &&
456 "Trying to get allocsize args from non-allocsize attribute");
457 return unpackAllocSizeArgs(pImpl->getValueAsInt());
458}
459
461 assert(hasAttribute(Attribute::VScaleRange) &&
462 "Trying to get vscale args from non-vscale attribute");
463 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
464}
465
466std::optional<unsigned> Attribute::getVScaleRangeMax() const {
467 assert(hasAttribute(Attribute::VScaleRange) &&
468 "Trying to get vscale args from non-vscale attribute");
469 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
470}
471
473 assert(hasAttribute(Attribute::UWTable) &&
474 "Trying to get unwind table kind from non-uwtable attribute");
475 return UWTableKind(pImpl->getValueAsInt());
476}
477
479 assert(hasAttribute(Attribute::AllocKind) &&
480 "Trying to get allockind value from non-allockind attribute");
481 return AllocFnKind(pImpl->getValueAsInt());
482}
483
485 assert(hasAttribute(Attribute::Memory) &&
486 "Can only call getMemoryEffects() on memory attribute");
488}
489
491 assert(hasAttribute(Attribute::Captures) &&
492 "Can only call getCaptureInfo() on captures attribute");
494}
495
497 assert(hasAttribute(Attribute::NoFPClass) &&
498 "Can only call getNoFPClass() on nofpclass attribute");
499 return static_cast<FPClassTest>(pImpl->getValueAsInt());
500}
501
503 assert(hasAttribute(Attribute::Range) &&
504 "Trying to get range args from non-range attribute");
505 return pImpl->getValueAsConstantRange();
506}
507
509 assert(hasAttribute(Attribute::Initializes) &&
510 "Trying to get initializes attr from non-ConstantRangeList attribute");
511 return pImpl->getValueAsConstantRangeList();
512}
513
514static const char *getModRefStr(ModRefInfo MR) {
515 switch (MR) {
517 return "none";
518 case ModRefInfo::Ref:
519 return "read";
520 case ModRefInfo::Mod:
521 return "write";
523 return "readwrite";
524 }
525 llvm_unreachable("Invalid ModRefInfo");
526}
527
528std::string Attribute::getAsString(bool InAttrGrp) const {
529 if (!pImpl) return {};
530
531 if (isEnumAttribute())
533
534 if (isTypeAttribute()) {
535 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
536 Result += '(';
537 raw_string_ostream OS(Result);
538 getValueAsType()->print(OS, false, true);
539 OS.flush();
540 Result += ')';
541 return Result;
542 }
543
544 // FIXME: These should be output like this:
545 //
546 // align=4
547 // alignstack=8
548 //
549 if (hasAttribute(Attribute::Alignment))
550 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
551 : "align " + Twine(getValueAsInt()))
552 .str();
553
554 auto AttrWithBytesToString = [&](const char *Name) {
555 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
556 : Name + ("(" + Twine(getValueAsInt())) + ")")
557 .str();
558 };
559
560 if (hasAttribute(Attribute::StackAlignment))
561 return AttrWithBytesToString("alignstack");
562
563 if (hasAttribute(Attribute::Dereferenceable))
564 return AttrWithBytesToString("dereferenceable");
565
566 if (hasAttribute(Attribute::DereferenceableOrNull))
567 return AttrWithBytesToString("dereferenceable_or_null");
568
569 if (hasAttribute(Attribute::AllocSize)) {
570 unsigned ElemSize;
571 std::optional<unsigned> NumElems;
572 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
573
574 return (NumElems
575 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
576 : "allocsize(" + Twine(ElemSize) + ")")
577 .str();
578 }
579
580 if (hasAttribute(Attribute::VScaleRange)) {
581 unsigned MinValue = getVScaleRangeMin();
582 std::optional<unsigned> MaxValue = getVScaleRangeMax();
583 return ("vscale_range(" + Twine(MinValue) + "," +
584 Twine(MaxValue.value_or(0)) + ")")
585 .str();
586 }
587
588 if (hasAttribute(Attribute::UWTable)) {
590 assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
591 return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
592 }
593
594 if (hasAttribute(Attribute::AllocKind)) {
595 AllocFnKind Kind = getAllocKind();
598 parts.push_back("alloc");
600 parts.push_back("realloc");
602 parts.push_back("free");
604 parts.push_back("uninitialized");
606 parts.push_back("zeroed");
608 parts.push_back("aligned");
609 return ("allockind(\"" +
610 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
611 .str();
612 }
613
614 if (hasAttribute(Attribute::Memory)) {
615 std::string Result;
616 raw_string_ostream OS(Result);
617 bool First = true;
618 OS << "memory(";
619
621
622 // Print access kind for "other" as the default access kind. This way it
623 // will apply to any new location kinds that get split out of "other".
625 if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
626 First = false;
627 OS << getModRefStr(OtherMR);
628 }
629
630 for (auto Loc : MemoryEffects::locations()) {
631 ModRefInfo MR = ME.getModRef(Loc);
632 if (MR == OtherMR)
633 continue;
634
635 if (!First)
636 OS << ", ";
637 First = false;
638
639 switch (Loc) {
641 OS << "argmem: ";
642 break;
644 OS << "inaccessiblemem: ";
645 break;
647 llvm_unreachable("This is represented as the default access kind");
648 }
649 OS << getModRefStr(MR);
650 }
651 OS << ")";
652 OS.flush();
653 return Result;
654 }
655
656 if (hasAttribute(Attribute::Captures)) {
657 std::string Result;
658 raw_string_ostream OS(Result);
659 OS << getCaptureInfo();
660 return Result;
661 }
662
663 if (hasAttribute(Attribute::NoFPClass)) {
664 std::string Result = "nofpclass";
665 raw_string_ostream OS(Result);
666 OS << getNoFPClass();
667 return Result;
668 }
669
670 if (hasAttribute(Attribute::Range)) {
671 std::string Result;
672 raw_string_ostream OS(Result);
674 OS << "range(";
675 OS << "i" << CR.getBitWidth() << " ";
676 OS << CR.getLower() << ", " << CR.getUpper();
677 OS << ")";
678 OS.flush();
679 return Result;
680 }
681
682 if (hasAttribute(Attribute::Initializes)) {
683 std::string Result;
684 raw_string_ostream OS(Result);
686 OS << "initializes(";
687 CRL.print(OS);
688 OS << ")";
689 OS.flush();
690 return Result;
691 }
692
693 // Convert target-dependent attributes to strings of the form:
694 //
695 // "kind"
696 // "kind" = "value"
697 //
698 if (isStringAttribute()) {
699 std::string Result;
700 {
701 raw_string_ostream OS(Result);
702 OS << '"' << getKindAsString() << '"';
703
704 // Since some attribute strings contain special characters that cannot be
705 // printable, those have to be escaped to make the attribute value
706 // printable as is. e.g. "\01__gnu_mcount_nc"
707 const auto &AttrVal = pImpl->getValueAsString();
708 if (!AttrVal.empty()) {
709 OS << "=\"";
710 printEscapedString(AttrVal, OS);
711 OS << "\"";
712 }
713 }
714 return Result;
715 }
716
717 llvm_unreachable("Unknown attribute");
718}
719
721 assert(isValid() && "invalid Attribute doesn't refer to any context");
723 pImpl->Profile(ID);
724 void *Unused;
725 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
726}
727
729 if (!pImpl && !A.pImpl)
730 return 0;
731 if (!pImpl)
732 return 1;
733 if (!A.pImpl)
734 return -1;
735 return pImpl->cmp(*A.pImpl, /*KindOnly=*/true);
736}
737
739 if (!pImpl && !A.pImpl) return false;
740 if (!pImpl) return true;
741 if (!A.pImpl) return false;
742 return *pImpl < *A.pImpl;
743}
744
746 ID.AddPointer(pImpl);
747}
748
750 FnAttr = (1 << 0),
751 ParamAttr = (1 << 1),
752 RetAttr = (1 << 2),
754 IntersectAnd = (1 << 3),
755 IntersectMin = (2 << 3),
756 IntersectCustom = (3 << 3),
758};
759
760#define GET_ATTR_PROP_TABLE
761#include "llvm/IR/Attributes.inc"
762
764 unsigned Index = Kind - 1;
765 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
766 return AttrPropTable[Index];
767}
768
770 AttributeProperty Prop) {
771 return getAttributeProperties(Kind) & Prop;
772}
773
775 return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
776}
777
779 return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
780}
781
783 return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
784}
785
787 AttributeProperty Prop) {
788 assert((Prop == AttributeProperty::IntersectPreserve ||
789 Prop == AttributeProperty::IntersectAnd ||
790 Prop == AttributeProperty::IntersectMin ||
791 Prop == AttributeProperty::IntersectCustom) &&
792 "Unknown intersect property");
793 return (getAttributeProperties(Kind) &
794 AttributeProperty::IntersectPropertyMask) == Prop;
795}
796
798 return hasIntersectProperty(Kind, AttributeProperty::IntersectPreserve);
799}
801 return hasIntersectProperty(Kind, AttributeProperty::IntersectAnd);
802}
804 return hasIntersectProperty(Kind, AttributeProperty::IntersectMin);
805}
807 return hasIntersectProperty(Kind, AttributeProperty::IntersectCustom);
808}
809
810//===----------------------------------------------------------------------===//
811// AttributeImpl Definition
812//===----------------------------------------------------------------------===//
813
815 if (isStringAttribute()) return false;
816 return getKindAsEnum() == A;
817}
818
820 if (!isStringAttribute()) return false;
821 return getKindAsString() == Kind;
822}
823
827 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
828}
829
832 return static_cast<const IntAttributeImpl *>(this)->getValue();
833}
834
836 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
837 return getValueAsString() == "true";
838}
839
842 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
843}
844
847 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
848}
849
852 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
853}
854
857 return static_cast<const ConstantRangeAttributeImpl *>(this)
858 ->getConstantRangeValue();
859}
860
863 return static_cast<const ConstantRangeListAttributeImpl *>(this)
864 ->getConstantRangeListValue();
865}
866
867int AttributeImpl::cmp(const AttributeImpl &AI, bool KindOnly) const {
868 if (this == &AI)
869 return 0;
870
871 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
872 // relative to their enum value) and then strings.
873 if (!isStringAttribute()) {
874 if (AI.isStringAttribute())
875 return -1;
876
877 if (getKindAsEnum() != AI.getKindAsEnum())
878 return getKindAsEnum() < AI.getKindAsEnum() ? -1 : 1;
879 else if (KindOnly)
880 return 0;
881
882 assert(!AI.isEnumAttribute() && "Non-unique attribute");
883 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
884 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
886 "Unclear how to compare range list");
887 // TODO: Is this actually needed?
888 assert(AI.isIntAttribute() && "Only possibility left");
889 if (getValueAsInt() < AI.getValueAsInt())
890 return -1;
891 return getValueAsInt() == AI.getValueAsInt() ? 0 : 1;
892 }
893 if (!AI.isStringAttribute())
894 return 1;
895 if (KindOnly)
897 if (getKindAsString() == AI.getKindAsString())
900}
901
903 return cmp(AI, /*KindOnly=*/false) < 0;
904}
905
906//===----------------------------------------------------------------------===//
907// AttributeSet Definition
908//===----------------------------------------------------------------------===//
909
912}
913
915 return AttributeSet(AttributeSetNode::get(C, Attrs));
916}
917
919 Attribute::AttrKind Kind) const {
920 if (hasAttribute(Kind)) return *this;
921 AttrBuilder B(C);
922 B.addAttribute(Kind);
924}
925
927 StringRef Value) const {
928 AttrBuilder B(C);
929 B.addAttribute(Kind, Value);
931}
932
934 const AttributeSet AS) const {
935 if (!hasAttributes())
936 return AS;
937
938 if (!AS.hasAttributes())
939 return *this;
940
941 AttrBuilder B(C, *this);
942 B.merge(AttrBuilder(C, AS));
943 return get(C, B);
944}
945
947 Attribute::AttrKind Kind) const {
948 if (!hasAttribute(Kind)) return *this;
949 AttrBuilder B(C, *this);
950 B.removeAttribute(Kind);
951 return get(C, B);
952}
953
955 StringRef Kind) const {
956 if (!hasAttribute(Kind)) return *this;
957 AttrBuilder B(C, *this);
958 B.removeAttribute(Kind);
959 return get(C, B);
960}
961
963 const AttributeMask &Attrs) const {
964 AttrBuilder B(C, *this);
965 // If there is nothing to remove, directly return the original set.
966 if (!B.overlaps(Attrs))
967 return *this;
968
969 B.remove(Attrs);
970 return get(C, B);
971}
972
973std::optional<AttributeSet>
975 if (*this == Other)
976 return *this;
977
978 AttrBuilder Intersected(C);
979 // Iterate over both attr sets at once.
980 auto ItBegin0 = begin();
981 auto ItEnd0 = end();
982 auto ItBegin1 = Other.begin();
983 auto ItEnd1 = Other.end();
984
985 while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {
986 // Loop through all attributes in both this and Other in sorted order. If
987 // the attribute is only present in one of the sets, it will be set in
988 // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.
989 Attribute Attr0, Attr1;
990 if (ItBegin1 == ItEnd1)
991 Attr0 = *ItBegin0++;
992 else if (ItBegin0 == ItEnd0)
993 Attr0 = *ItBegin1++;
994 else {
995 int Cmp = ItBegin0->cmpKind(*ItBegin1);
996 if (Cmp == 0) {
997 Attr0 = *ItBegin0++;
998 Attr1 = *ItBegin1++;
999 } else if (Cmp < 0)
1000 Attr0 = *ItBegin0++;
1001 else
1002 Attr0 = *ItBegin1++;
1003 }
1004 assert(Attr0.isValid() && "Iteration should always yield a valid attr");
1005
1006 auto IntersectEq = [&]() {
1007 if (!Attr1.isValid())
1008 return false;
1009 if (Attr0 != Attr1)
1010 return false;
1011 Intersected.addAttribute(Attr0);
1012 return true;
1013 };
1014
1015 // Non-enum assume we must preserve. Handle early so we can unconditionally
1016 // use Kind below.
1017 if (!Attr0.hasKindAsEnum()) {
1018 if (!IntersectEq())
1019 return std::nullopt;
1020 continue;
1021 }
1022
1023 Attribute::AttrKind Kind = Attr0.getKindAsEnum();
1024 // If we don't have both attributes, then fail if the attribute is
1025 // must-preserve or drop it otherwise.
1026 if (!Attr1.isValid()) {
1028 return std::nullopt;
1029 continue;
1030 }
1031
1032 // We have both attributes so apply the intersection rule.
1033 assert(Attr1.hasKindAsEnum() && Kind == Attr1.getKindAsEnum() &&
1034 "Iterator picked up two different attributes in the same iteration");
1035
1036 // Attribute we can intersect with "and"
1037 if (Attribute::intersectWithAnd(Kind)) {
1039 "Invalid attr type of intersectAnd");
1040 Intersected.addAttribute(Kind);
1041 continue;
1042 }
1043
1044 // Attribute we can intersect with "min"
1045 if (Attribute::intersectWithMin(Kind)) {
1047 "Invalid attr type of intersectMin");
1048 uint64_t NewVal = std::min(Attr0.getValueAsInt(), Attr1.getValueAsInt());
1049 Intersected.addRawIntAttr(Kind, NewVal);
1050 continue;
1051 }
1052 // Attribute we can intersect but need a custom rule for.
1054 switch (Kind) {
1055 case Attribute::Alignment:
1056 // If `byval` is present, alignment become must-preserve. This is
1057 // handled below if we have `byval`.
1058 Intersected.addAlignmentAttr(
1059 std::min(Attr0.getAlignment().valueOrOne(),
1060 Attr1.getAlignment().valueOrOne()));
1061 break;
1062 case Attribute::Memory:
1063 Intersected.addMemoryAttr(Attr0.getMemoryEffects() |
1064 Attr1.getMemoryEffects());
1065 break;
1066 case Attribute::Captures:
1067 Intersected.addCapturesAttr(Attr0.getCaptureInfo() |
1068 Attr1.getCaptureInfo());
1069 break;
1070 case Attribute::NoFPClass:
1071 Intersected.addNoFPClassAttr(Attr0.getNoFPClass() &
1072 Attr1.getNoFPClass());
1073 break;
1074 case Attribute::Range: {
1075 ConstantRange Range0 = Attr0.getRange();
1076 ConstantRange Range1 = Attr1.getRange();
1077 ConstantRange NewRange = Range0.unionWith(Range1);
1078 if (!NewRange.isFullSet())
1079 Intersected.addRangeAttr(NewRange);
1080 } break;
1081 default:
1082 llvm_unreachable("Unknown attribute with custom intersection rule");
1083 }
1084 continue;
1085 }
1086
1087 // Attributes with no intersection rule. Only intersect if they are equal.
1088 // Otherwise fail.
1089 if (!IntersectEq())
1090 return std::nullopt;
1091
1092 // Special handling of `byval`. `byval` essentially turns align attr into
1093 // must-preserve
1094 if (Kind == Attribute::ByVal &&
1095 getAttribute(Attribute::Alignment) !=
1096 Other.getAttribute(Attribute::Alignment))
1097 return std::nullopt;
1098 }
1099
1100 return get(C, Intersected);
1101}
1102
1104 return SetNode ? SetNode->getNumAttributes() : 0;
1105}
1106
1108 return SetNode ? SetNode->hasAttribute(Kind) : false;
1109}
1110
1112 return SetNode ? SetNode->hasAttribute(Kind) : false;
1113}
1114
1116 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1117}
1118
1120 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1121}
1122
1124 return SetNode ? SetNode->getAlignment() : std::nullopt;
1125}
1126
1128 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
1129}
1130
1132 return SetNode ? SetNode->getDereferenceableBytes() : 0;
1133}
1134
1136 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
1137}
1138
1140 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
1141}
1142
1144 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
1145}
1146
1148 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
1149}
1150
1152 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
1153}
1154
1156 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
1157}
1158
1160 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
1161}
1162
1163std::optional<std::pair<unsigned, std::optional<unsigned>>>
1165 if (SetNode)
1166 return SetNode->getAllocSizeArgs();
1167 return std::nullopt;
1168}
1169
1171 return SetNode ? SetNode->getVScaleRangeMin() : 1;
1172}
1173
1174std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
1175 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
1176}
1177
1179 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
1180}
1181
1183 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
1184}
1185
1187 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
1188}
1189
1191 return SetNode ? SetNode->getCaptureInfo() : CaptureInfo::all();
1192}
1193
1195 return SetNode ? SetNode->getNoFPClass() : fcNone;
1196}
1197
1198std::string AttributeSet::getAsString(bool InAttrGrp) const {
1199 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
1200}
1201
1203 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1205 SetNode->Profile(ID);
1206 void *Unused;
1207 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1208}
1209
1211 return SetNode ? SetNode->begin() : nullptr;
1212}
1213
1215 return SetNode ? SetNode->end() : nullptr;
1216}
1217
1218#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1220 dbgs() << "AS =\n";
1221 dbgs() << " { ";
1222 dbgs() << getAsString(true) << " }\n";
1223}
1224#endif
1225
1226//===----------------------------------------------------------------------===//
1227// AttributeSetNode Definition
1228//===----------------------------------------------------------------------===//
1229
1230AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1231 : NumAttrs(Attrs.size()) {
1232 // There's memory after the node where we can store the entries in.
1233 llvm::copy(Attrs, getTrailingObjects<Attribute>());
1234
1235 for (const auto &I : *this) {
1236 if (I.isStringAttribute())
1237 StringAttrs.insert({ I.getKindAsString(), I });
1238 else
1239 AvailableAttrs.addAttribute(I.getKindAsEnum());
1240 }
1241}
1242
1244 ArrayRef<Attribute> Attrs) {
1245 SmallVector<Attribute, 8> SortedAttrs(Attrs);
1246 llvm::sort(SortedAttrs);
1247 return getSorted(C, SortedAttrs);
1248}
1249
1250AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1251 ArrayRef<Attribute> SortedAttrs) {
1252 if (SortedAttrs.empty())
1253 return nullptr;
1254
1255 // Build a key to look up the existing attributes.
1256 LLVMContextImpl *pImpl = C.pImpl;
1258
1259 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1260 for (const auto &Attr : SortedAttrs)
1261 Attr.Profile(ID);
1262
1263 void *InsertPoint;
1264 AttributeSetNode *PA =
1265 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1266
1267 // If we didn't find any existing attributes of the same shape then create a
1268 // new one and insert it.
1269 if (!PA) {
1270 // Coallocate entries after the AttributeSetNode itself.
1271 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1272 PA = new (Mem) AttributeSetNode(SortedAttrs);
1273 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1274 }
1275
1276 // Return the AttributeSetNode that we found or created.
1277 return PA;
1278}
1279
1281 return getSorted(C, B.attrs());
1282}
1283
1285 return StringAttrs.count(Kind);
1286}
1287
1288std::optional<Attribute>
1289AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1290 // Do a quick presence check.
1291 if (!hasAttribute(Kind))
1292 return std::nullopt;
1293
1294 // Attributes in a set are sorted by enum value, followed by string
1295 // attributes. Binary search the one we want.
1296 const Attribute *I =
1297 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1298 [](Attribute A, Attribute::AttrKind Kind) {
1299 return A.getKindAsEnum() < Kind;
1300 });
1301 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1302 return *I;
1303}
1304
1306 if (auto A = findEnumAttribute(Kind))
1307 return *A;
1308 return {};
1309}
1310
1312 return StringAttrs.lookup(Kind);
1313}
1314
1316 if (auto A = findEnumAttribute(Attribute::Alignment))
1317 return A->getAlignment();
1318 return std::nullopt;
1319}
1320
1322 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1323 return A->getStackAlignment();
1324 return std::nullopt;
1325}
1326
1328 if (auto A = findEnumAttribute(Kind))
1329 return A->getValueAsType();
1330 return nullptr;
1331}
1332
1334 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1335 return A->getDereferenceableBytes();
1336 return 0;
1337}
1338
1340 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1341 return A->getDereferenceableOrNullBytes();
1342 return 0;
1343}
1344
1345std::optional<std::pair<unsigned, std::optional<unsigned>>>
1347 if (auto A = findEnumAttribute(Attribute::AllocSize))
1348 return A->getAllocSizeArgs();
1349 return std::nullopt;
1350}
1351
1353 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1354 return A->getVScaleRangeMin();
1355 return 1;
1356}
1357
1358std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1359 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1360 return A->getVScaleRangeMax();
1361 return std::nullopt;
1362}
1363
1365 if (auto A = findEnumAttribute(Attribute::UWTable))
1366 return A->getUWTableKind();
1367 return UWTableKind::None;
1368}
1369
1371 if (auto A = findEnumAttribute(Attribute::AllocKind))
1372 return A->getAllocKind();
1373 return AllocFnKind::Unknown;
1374}
1375
1377 if (auto A = findEnumAttribute(Attribute::Memory))
1378 return A->getMemoryEffects();
1379 return MemoryEffects::unknown();
1380}
1381
1383 if (auto A = findEnumAttribute(Attribute::Captures))
1384 return A->getCaptureInfo();
1385 return CaptureInfo::all();
1386}
1387
1389 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1390 return A->getNoFPClass();
1391 return fcNone;
1392}
1393
1394std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1395 std::string Str;
1396 for (iterator I = begin(), E = end(); I != E; ++I) {
1397 if (I != begin())
1398 Str += ' ';
1399 Str += I->getAsString(InAttrGrp);
1400 }
1401 return Str;
1402}
1403
1404//===----------------------------------------------------------------------===//
1405// AttributeListImpl Definition
1406//===----------------------------------------------------------------------===//
1407
1408/// Map from AttributeList index to the internal array index. Adding one happens
1409/// to work, because -1 wraps around to 0.
1410static unsigned attrIdxToArrayIdx(unsigned Index) {
1411 return Index + 1;
1412}
1413
1415 : NumAttrSets(Sets.size()) {
1416 assert(!Sets.empty() && "pointless AttributeListImpl");
1417
1418 // There's memory after the node where we can store the entries in.
1419 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
1420
1421 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1422 // summary bitsets.
1423 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1424 if (!I.isStringAttribute())
1425 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1426
1427 for (const auto &Set : Sets)
1428 for (const auto &I : Set)
1429 if (!I.isStringAttribute())
1430 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1431}
1432
1434 Profile(ID, ArrayRef(begin(), end()));
1435}
1436
1439 for (const auto &Set : Sets)
1440 ID.AddPointer(Set.SetNode);
1441}
1442
1444 unsigned *Index) const {
1445 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1446 return false;
1447
1448 if (Index) {
1449 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1450 if (begin()[I].hasAttribute(Kind)) {
1451 *Index = I - 1;
1452 break;
1453 }
1454 }
1455 }
1456
1457 return true;
1458}
1459
1460
1461#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1463 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1464}
1465#endif
1466
1467//===----------------------------------------------------------------------===//
1468// AttributeList Construction and Mutation Methods
1469//===----------------------------------------------------------------------===//
1470
1471AttributeList AttributeList::getImpl(LLVMContext &C,
1472 ArrayRef<AttributeSet> AttrSets) {
1473 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1474
1475 LLVMContextImpl *pImpl = C.pImpl;
1477 AttributeListImpl::Profile(ID, AttrSets);
1478
1479 void *InsertPoint;
1480 AttributeListImpl *PA =
1481 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1482
1483 // If we didn't find any existing attributes of the same shape then
1484 // create a new one and insert it.
1485 if (!PA) {
1486 // Coallocate entries after the AttributeListImpl itself.
1487 void *Mem = pImpl->Alloc.Allocate(
1488 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1489 alignof(AttributeListImpl));
1490 PA = new (Mem) AttributeListImpl(AttrSets);
1491 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1492 }
1493
1494 // Return the AttributesList that we found or created.
1495 return AttributeList(PA);
1496}
1497
1500 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1501 // If there are no attributes then return a null AttributesList pointer.
1502 if (Attrs.empty())
1503 return {};
1504
1506 "Misordered Attributes list!");
1507 assert(llvm::all_of(Attrs,
1508 [](const std::pair<unsigned, Attribute> &Pair) {
1509 return Pair.second.isValid();
1510 }) &&
1511 "Pointless attribute!");
1512
1513 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1514 // list.
1516 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1517 E = Attrs.end(); I != E; ) {
1518 unsigned Index = I->first;
1520 while (I != E && I->first == Index) {
1521 AttrVec.push_back(I->second);
1522 ++I;
1523 }
1524
1525 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1526 }
1527
1528 return get(C, AttrPairVec);
1529}
1530
1533 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1534 // If there are no attributes then return a null AttributesList pointer.
1535 if (Attrs.empty())
1536 return {};
1537
1539 "Misordered Attributes list!");
1540 assert(llvm::none_of(Attrs,
1541 [](const std::pair<unsigned, AttributeSet> &Pair) {
1542 return !Pair.second.hasAttributes();
1543 }) &&
1544 "Pointless attribute!");
1545
1546 unsigned MaxIndex = Attrs.back().first;
1547 // If the MaxIndex is FunctionIndex and there are other indices in front
1548 // of it, we need to use the largest of those to get the right size.
1549 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1550 MaxIndex = Attrs[Attrs.size() - 2].first;
1551
1552 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1553 for (const auto &Pair : Attrs)
1554 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1555
1556 return getImpl(C, AttrVec);
1557}
1558
1560 AttributeSet RetAttrs,
1561 ArrayRef<AttributeSet> ArgAttrs) {
1562 // Scan from the end to find the last argument with attributes. Most
1563 // arguments don't have attributes, so it's nice if we can have fewer unique
1564 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1565 unsigned NumSets = 0;
1566 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1567 if (ArgAttrs[I - 1].hasAttributes()) {
1568 NumSets = I + 2;
1569 break;
1570 }
1571 }
1572 if (NumSets == 0) {
1573 // Check function and return attributes if we didn't have argument
1574 // attributes.
1575 if (RetAttrs.hasAttributes())
1576 NumSets = 2;
1577 else if (FnAttrs.hasAttributes())
1578 NumSets = 1;
1579 }
1580
1581 // If all attribute sets were empty, we can use the empty attribute list.
1582 if (NumSets == 0)
1583 return {};
1584
1586 AttrSets.reserve(NumSets);
1587 // If we have any attributes, we always have function attributes.
1588 AttrSets.push_back(FnAttrs);
1589 if (NumSets > 1)
1590 AttrSets.push_back(RetAttrs);
1591 if (NumSets > 2) {
1592 // Drop the empty argument attribute sets at the end.
1593 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1594 llvm::append_range(AttrSets, ArgAttrs);
1595 }
1596
1597 return getImpl(C, AttrSets);
1598}
1599
1601 AttributeSet Attrs) {
1602 if (!Attrs.hasAttributes())
1603 return {};
1604 Index = attrIdxToArrayIdx(Index);
1605 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1606 AttrSets[Index] = Attrs;
1607 return getImpl(C, AttrSets);
1608}
1609
1611 const AttrBuilder &B) {
1612 return get(C, Index, AttributeSet::get(C, B));
1613}
1614
1618 for (const auto K : Kinds)
1619 Attrs.emplace_back(Index, Attribute::get(C, K));
1620 return get(C, Attrs);
1621}
1622
1625 ArrayRef<uint64_t> Values) {
1626 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1628 auto VI = Values.begin();
1629 for (const auto K : Kinds)
1630 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1631 return get(C, Attrs);
1632}
1633
1635 ArrayRef<StringRef> Kinds) {
1637 for (const auto &K : Kinds)
1638 Attrs.emplace_back(Index, Attribute::get(C, K));
1639 return get(C, Attrs);
1640}
1641
1644 if (Attrs.empty())
1645 return {};
1646 if (Attrs.size() == 1)
1647 return Attrs[0];
1648
1649 unsigned MaxSize = 0;
1650 for (const auto &List : Attrs)
1651 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1652
1653 // If every list was empty, there is no point in merging the lists.
1654 if (MaxSize == 0)
1655 return {};
1656
1657 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1658 for (unsigned I = 0; I < MaxSize; ++I) {
1659 AttrBuilder CurBuilder(C);
1660 for (const auto &List : Attrs)
1661 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1662 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1663 }
1664
1665 return getImpl(C, NewAttrSets);
1666}
1667
1670 Attribute::AttrKind Kind) const {
1671 AttributeSet Attrs = getAttributes(Index);
1672 if (Attrs.hasAttribute(Kind))
1673 return *this;
1674 // TODO: Insert at correct position and avoid sort.
1675 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1676 NewAttrs.push_back(Attribute::get(C, Kind));
1677 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1678}
1679
1681 StringRef Kind,
1682 StringRef Value) const {
1683 AttrBuilder B(C);
1684 B.addAttribute(Kind, Value);
1685 return addAttributesAtIndex(C, Index, B);
1686}
1687
1689 Attribute A) const {
1690 AttrBuilder B(C);
1691 B.addAttribute(A);
1692 return addAttributesAtIndex(C, Index, B);
1693}
1694
1695AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1696 unsigned Index,
1697 AttributeSet Attrs) const {
1698 Index = attrIdxToArrayIdx(Index);
1699 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1700 if (Index >= AttrSets.size())
1701 AttrSets.resize(Index + 1);
1702 AttrSets[Index] = Attrs;
1703
1704 // Remove trailing empty attribute sets.
1705 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1706 AttrSets.pop_back();
1707 if (AttrSets.empty())
1708 return {};
1709 return AttributeList::getImpl(C, AttrSets);
1710}
1711
1713 unsigned Index,
1714 const AttrBuilder &B) const {
1715 if (!B.hasAttributes())
1716 return *this;
1717
1718 if (!pImpl)
1719 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1720
1721 AttrBuilder Merged(C, getAttributes(Index));
1722 Merged.merge(B);
1723 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1724}
1725
1727 ArrayRef<unsigned> ArgNos,
1728 Attribute A) const {
1729 assert(llvm::is_sorted(ArgNos));
1730
1731 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1732 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1733 if (MaxIndex >= AttrSets.size())
1734 AttrSets.resize(MaxIndex + 1);
1735
1736 for (unsigned ArgNo : ArgNos) {
1737 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1738 AttrBuilder B(C, AttrSets[Index]);
1739 B.addAttribute(A);
1740 AttrSets[Index] = AttributeSet::get(C, B);
1741 }
1742
1743 return getImpl(C, AttrSets);
1744}
1745
1748 Attribute::AttrKind Kind) const {
1749 AttributeSet Attrs = getAttributes(Index);
1750 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1751 if (Attrs == NewAttrs)
1752 return *this;
1753 return setAttributesAtIndex(C, Index, NewAttrs);
1754}
1755
1757 unsigned Index,
1758 StringRef Kind) const {
1759 AttributeSet Attrs = getAttributes(Index);
1760 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1761 if (Attrs == NewAttrs)
1762 return *this;
1763 return setAttributesAtIndex(C, Index, NewAttrs);
1764}
1765
1767 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1768 AttributeSet Attrs = getAttributes(Index);
1769 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1770 // If nothing was removed, return the original list.
1771 if (Attrs == NewAttrs)
1772 return *this;
1773 return setAttributesAtIndex(C, Index, NewAttrs);
1774}
1775
1778 unsigned WithoutIndex) const {
1779 if (!pImpl)
1780 return {};
1781 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1782 return *this;
1783 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1784}
1785
1787 uint64_t Bytes) const {
1788 AttrBuilder B(C);
1789 B.addDereferenceableAttr(Bytes);
1790 return addRetAttributes(C, B);
1791}
1792
1794 unsigned Index,
1795 uint64_t Bytes) const {
1796 AttrBuilder B(C);
1797 B.addDereferenceableAttr(Bytes);
1798 return addParamAttributes(C, Index, B);
1799}
1800
1803 uint64_t Bytes) const {
1804 AttrBuilder B(C);
1805 B.addDereferenceableOrNullAttr(Bytes);
1806 return addParamAttributes(C, Index, B);
1807}
1808
1810 const ConstantRange &CR) const {
1811 AttrBuilder B(C);
1812 B.addRangeAttr(CR);
1813 return addRetAttributes(C, B);
1814}
1815
1817 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1818 const std::optional<unsigned> &NumElemsArg) const {
1819 AttrBuilder B(C);
1820 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1821 return addParamAttributes(C, Index, B);
1822}
1823
1824std::optional<AttributeList>
1826 // Trivial case, the two lists are equal.
1827 if (*this == Other)
1828 return *this;
1829
1831 auto IndexIt =
1832 index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
1833 for (unsigned Idx : IndexIt) {
1834 auto IntersectedAS =
1835 getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
1836 // If any index fails to intersect, fail.
1837 if (!IntersectedAS)
1838 return std::nullopt;
1839 if (!IntersectedAS->hasAttributes())
1840 continue;
1841 IntersectedAttrs.push_back(std::make_pair(Idx, *IntersectedAS));
1842 }
1843
1844 llvm::sort(IntersectedAttrs, llvm::less_first());
1845 return AttributeList::get(C, IntersectedAttrs);
1846}
1847
1848//===----------------------------------------------------------------------===//
1849// AttributeList Accessor Methods
1850//===----------------------------------------------------------------------===//
1851
1853 return getAttributes(ArgNo + FirstArgIndex);
1854}
1855
1857 return getAttributes(ReturnIndex);
1858}
1859
1862}
1863
1865 Attribute::AttrKind Kind) const {
1866 return getAttributes(Index).hasAttribute(Kind);
1867}
1868
1869bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1870 return getAttributes(Index).hasAttribute(Kind);
1871}
1872
1873bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1874 return getAttributes(Index).hasAttributes();
1875}
1876
1878 return pImpl && pImpl->hasFnAttribute(Kind);
1879}
1880
1883}
1884
1886 unsigned *Index) const {
1887 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1888}
1889
1891 Attribute::AttrKind Kind) const {
1892 return getAttributes(Index).getAttribute(Kind);
1893}
1894
1896 StringRef Kind) const {
1897 return getAttributes(Index).getAttribute(Kind);
1898}
1899
1902}
1903
1905 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1906}
1907
1910}
1911
1914}
1915
1918}
1919
1921 return getAttributes(Index + FirstArgIndex).getByRefType();
1922}
1923
1926}
1927
1930}
1931
1933 return getAttributes(Index + FirstArgIndex).getElementType();
1934}
1935
1937 return getFnAttrs().getStackAlignment();
1938}
1939
1941 return getRetAttrs().getStackAlignment();
1942}
1943
1946}
1947
1949 return getParamAttrs(Index).getDereferenceableBytes();
1950}
1951
1954}
1955
1959}
1960
1961std::optional<ConstantRange>
1962AttributeList::getParamRange(unsigned ArgNo) const {
1963 auto RangeAttr = getParamAttrs(ArgNo).getAttribute(Attribute::Range);
1964 if (RangeAttr.isValid())
1965 return RangeAttr.getRange();
1966 return std::nullopt;
1967}
1968
1970 return getRetAttrs().getNoFPClass();
1971}
1972
1974 return getParamAttrs(Index).getNoFPClass();
1975}
1976
1978 return getFnAttrs().getUWTableKind();
1979}
1980
1982 return getFnAttrs().getAllocKind();
1983}
1984
1986 return getFnAttrs().getMemoryEffects();
1987}
1988
1989std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1990 return getAttributes(Index).getAsString(InAttrGrp);
1991}
1992
1994 Index = attrIdxToArrayIdx(Index);
1995 if (!pImpl || Index >= getNumAttrSets())
1996 return {};
1997 return pImpl->begin()[Index];
1998}
1999
2001 assert(!isEmpty() && "an empty attribute list has no parent context");
2003 pImpl->Profile(ID);
2004 void *Unused;
2005 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
2006}
2007
2009 return pImpl ? pImpl->begin() : nullptr;
2010}
2011
2013 return pImpl ? pImpl->end() : nullptr;
2014}
2015
2016//===----------------------------------------------------------------------===//
2017// AttributeList Introspection Methods
2018//===----------------------------------------------------------------------===//
2019
2021 return pImpl ? pImpl->NumAttrSets : 0;
2022}
2023
2025 O << "AttributeList[\n";
2026
2027 for (unsigned i : indexes()) {
2028 if (!getAttributes(i).hasAttributes())
2029 continue;
2030 O << " { ";
2031 switch (i) {
2033 O << "return";
2034 break;
2036 O << "function";
2037 break;
2038 default:
2039 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
2040 }
2041 O << " => " << getAsString(i) << " }\n";
2042 }
2043
2044 O << "]\n";
2045}
2046
2047#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2049#endif
2050
2051//===----------------------------------------------------------------------===//
2052// AttrBuilder Method Implementations
2053//===----------------------------------------------------------------------===//
2054
2056 append_range(Attrs, AS);
2057 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
2058}
2059
2060void AttrBuilder::clear() { Attrs.clear(); }
2061
2062/// Attribute comparator that only compares attribute keys. Enum attributes are
2063/// sorted before string attributes.
2065 bool operator()(Attribute A0, Attribute A1) const {
2066 bool A0IsString = A0.isStringAttribute();
2067 bool A1IsString = A1.isStringAttribute();
2068 if (A0IsString) {
2069 if (A1IsString)
2070 return A0.getKindAsString() < A1.getKindAsString();
2071 else
2072 return false;
2073 }
2074 if (A1IsString)
2075 return true;
2076 return A0.getKindAsEnum() < A1.getKindAsEnum();
2077 }
2079 if (A0.isStringAttribute())
2080 return false;
2081 return A0.getKindAsEnum() < Kind;
2082 }
2083 bool operator()(Attribute A0, StringRef Kind) const {
2084 if (A0.isStringAttribute())
2085 return A0.getKindAsString() < Kind;
2086 return true;
2087 }
2088};
2089
2090template <typename K>
2092 Attribute Attr) {
2093 auto It = lower_bound(Attrs, Kind, AttributeComparator());
2094 if (It != Attrs.end() && It->hasAttribute(Kind))
2095 std::swap(*It, Attr);
2096 else
2097 Attrs.insert(It, Attr);
2098}
2099
2101 if (Attr.isStringAttribute())
2102 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
2103 else
2104 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
2105 return *this;
2106}
2107
2109 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
2110 return *this;
2111}
2112
2114 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
2115 return *this;
2116}
2117
2119 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
2120 auto It = lower_bound(Attrs, Val, AttributeComparator());
2121 if (It != Attrs.end() && It->hasAttribute(Val))
2122 Attrs.erase(It);
2123 return *this;
2124}
2125
2127 auto It = lower_bound(Attrs, A, AttributeComparator());
2128 if (It != Attrs.end() && It->hasAttribute(A))
2129 Attrs.erase(It);
2130 return *this;
2131}
2132
2133std::optional<uint64_t>
2135 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
2136 Attribute A = getAttribute(Kind);
2137 if (A.isValid())
2138 return A.getValueAsInt();
2139 return std::nullopt;
2140}
2141
2143 uint64_t Value) {
2144 return addAttribute(Attribute::get(Ctx, Kind, Value));
2145}
2146
2147std::optional<std::pair<unsigned, std::optional<unsigned>>>
2149 Attribute A = getAttribute(Attribute::AllocSize);
2150 if (A.isValid())
2151 return A.getAllocSizeArgs();
2152 return std::nullopt;
2153}
2154
2156 if (!Align)
2157 return *this;
2158
2159 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
2160 return addRawIntAttr(Attribute::Alignment, Align->value());
2161}
2162
2164 // Default alignment, allow the target to define how to align it.
2165 if (!Align)
2166 return *this;
2167
2168 assert(*Align <= 0x100 && "Alignment too large.");
2169 return addRawIntAttr(Attribute::StackAlignment, Align->value());
2170}
2171
2173 if (Bytes == 0) return *this;
2174
2175 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
2176}
2177
2179 if (Bytes == 0)
2180 return *this;
2181
2182 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
2183}
2184
2187 const std::optional<unsigned> &NumElems) {
2188 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
2189}
2190
2192 // (0, 0) is our "not present" value, so we need to check for it here.
2193 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
2194 return addRawIntAttr(Attribute::AllocSize, RawArgs);
2195}
2196
2198 std::optional<unsigned> MaxValue) {
2199 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
2200}
2201
2203 // (0, 0) is not present hence ignore this case
2204 if (RawArgs == 0)
2205 return *this;
2206
2207 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
2208}
2209
2211 if (Kind == UWTableKind::None)
2212 return *this;
2213 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
2214}
2215
2217 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
2218}
2219
2221 return addRawIntAttr(Attribute::Captures, CI.toIntValue());
2222}
2223
2225 if (Mask == fcNone)
2226 return *this;
2227
2228 return addRawIntAttr(Attribute::NoFPClass, Mask);
2229}
2230
2232 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
2233}
2234
2236 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
2237 Attribute A = getAttribute(Kind);
2238 return A.isValid() ? A.getValueAsType() : nullptr;
2239}
2240
2242 return addAttribute(Attribute::get(Ctx, Kind, Ty));
2243}
2244
2246 return addTypeAttr(Attribute::ByVal, Ty);
2247}
2248
2250 return addTypeAttr(Attribute::StructRet, Ty);
2251}
2252
2254 return addTypeAttr(Attribute::ByRef, Ty);
2255}
2256
2258 return addTypeAttr(Attribute::Preallocated, Ty);
2259}
2260
2262 return addTypeAttr(Attribute::InAlloca, Ty);
2263}
2264
2266 const ConstantRange &CR) {
2267 if (CR.isFullSet())
2268 return *this;
2269
2270 return addAttribute(Attribute::get(Ctx, Kind, CR));
2271}
2272
2274 return addConstantRangeAttr(Attribute::Range, CR);
2275}
2276
2280 return addAttribute(Attribute::get(Ctx, Kind, Val));
2281}
2282
2284 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2285}
2286
2288 // TODO: Could make this O(n) as we're merging two sorted lists.
2289 for (const auto &I : B.attrs())
2290 addAttribute(I);
2291
2292 return *this;
2293}
2294
2296 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2297 return *this;
2298}
2299
2301 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2302}
2303
2305 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2306 auto It = lower_bound(Attrs, A, AttributeComparator());
2307 if (It != Attrs.end() && It->hasAttribute(A))
2308 return *It;
2309 return {};
2310}
2311
2313 auto It = lower_bound(Attrs, A, AttributeComparator());
2314 if (It != Attrs.end() && It->hasAttribute(A))
2315 return *It;
2316 return {};
2317}
2318
2319std::optional<ConstantRange> AttrBuilder::getRange() const {
2320 const Attribute RangeAttr = getAttribute(Attribute::Range);
2321 if (RangeAttr.isValid())
2322 return RangeAttr.getRange();
2323 return std::nullopt;
2324}
2325
2327 return getAttribute(A).isValid();
2328}
2329
2331 return getAttribute(A).isValid();
2332}
2333
2335 return Attrs == B.Attrs;
2336}
2337
2338//===----------------------------------------------------------------------===//
2339// AttributeFuncs Function Defintions
2340//===----------------------------------------------------------------------===//
2341
2342/// Returns true if this is a type legal for the 'nofpclass' attribute. This
2343/// follows the same type rules as FPMathOperator.
2346}
2347
2348/// Which attributes cannot be applied to a type.
2350 AttributeSafetyKind ASK) {
2351 AttributeMask Incompatible;
2352
2353 if (!Ty->isIntegerTy()) {
2354 // Attributes that only apply to integers.
2355 if (ASK & ASK_SAFE_TO_DROP)
2356 Incompatible.addAttribute(Attribute::AllocAlign);
2357 if (ASK & ASK_UNSAFE_TO_DROP)
2358 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2359 }
2360
2361 if (!Ty->isIntOrIntVectorTy()) {
2362 // Attributes that only apply to integers or vector of integers.
2363 if (ASK & ASK_SAFE_TO_DROP)
2364 Incompatible.addAttribute(Attribute::Range);
2365 } else {
2366 Attribute RangeAttr = AS.getAttribute(Attribute::Range);
2367 if (RangeAttr.isValid() &&
2368 RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())
2369 Incompatible.addAttribute(Attribute::Range);
2370 }
2371
2372 if (!Ty->isPointerTy()) {
2373 // Attributes that only apply to pointers.
2374 if (ASK & ASK_SAFE_TO_DROP)
2375 Incompatible.addAttribute(Attribute::NoAlias)
2376 .addAttribute(Attribute::NoCapture)
2377 .addAttribute(Attribute::NonNull)
2378 .addAttribute(Attribute::ReadNone)
2379 .addAttribute(Attribute::ReadOnly)
2380 .addAttribute(Attribute::Dereferenceable)
2381 .addAttribute(Attribute::DereferenceableOrNull)
2382 .addAttribute(Attribute::Writable)
2383 .addAttribute(Attribute::DeadOnUnwind)
2384 .addAttribute(Attribute::Initializes)
2385 .addAttribute(Attribute::Captures);
2386 if (ASK & ASK_UNSAFE_TO_DROP)
2387 Incompatible.addAttribute(Attribute::Nest)
2388 .addAttribute(Attribute::SwiftError)
2389 .addAttribute(Attribute::Preallocated)
2390 .addAttribute(Attribute::InAlloca)
2391 .addAttribute(Attribute::ByVal)
2392 .addAttribute(Attribute::StructRet)
2393 .addAttribute(Attribute::ByRef)
2394 .addAttribute(Attribute::ElementType)
2395 .addAttribute(Attribute::AllocatedPointer);
2396 }
2397
2398 // Attributes that only apply to pointers or vectors of pointers.
2399 if (!Ty->isPtrOrPtrVectorTy()) {
2400 if (ASK & ASK_SAFE_TO_DROP)
2401 Incompatible.addAttribute(Attribute::Alignment);
2402 }
2403
2404 if (ASK & ASK_SAFE_TO_DROP) {
2406 Incompatible.addAttribute(Attribute::NoFPClass);
2407 }
2408
2409 // Some attributes can apply to all "values" but there are no `void` values.
2410 if (Ty->isVoidTy()) {
2411 if (ASK & ASK_SAFE_TO_DROP)
2412 Incompatible.addAttribute(Attribute::NoUndef);
2413 }
2414
2415 return Incompatible;
2416}
2417
2419 AttributeMask AM;
2420 AM.addAttribute(Attribute::NoUndef);
2421 AM.addAttribute(Attribute::Dereferenceable);
2422 AM.addAttribute(Attribute::DereferenceableOrNull);
2423 return AM;
2424}
2425
2426/// Callees with dynamic denormal modes are compatible with any caller mode.
2427static bool denormModeCompatible(DenormalMode CallerMode,
2428 DenormalMode CalleeMode) {
2429 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2430 return true;
2431
2432 // If they don't exactly match, it's OK if the mismatched component is
2433 // dynamic.
2434 if (CalleeMode.Input == CallerMode.Input &&
2435 CalleeMode.Output == DenormalMode::Dynamic)
2436 return true;
2437
2438 if (CalleeMode.Output == CallerMode.Output &&
2439 CalleeMode.Input == DenormalMode::Dynamic)
2440 return true;
2441 return false;
2442}
2443
2444static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2445 DenormalMode CallerMode = Caller.getDenormalModeRaw();
2446 DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2447
2448 if (denormModeCompatible(CallerMode, CalleeMode)) {
2449 DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2450 DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2451 if (CallerModeF32 == DenormalMode::getInvalid())
2452 CallerModeF32 = CallerMode;
2453 if (CalleeModeF32 == DenormalMode::getInvalid())
2454 CalleeModeF32 = CalleeMode;
2455 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2456 }
2457
2458 return false;
2459}
2460
2461static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2462 // Do not inline strictfp function into non-strictfp one. It would require
2463 // conversion of all FP operations in host function to constrained intrinsics.
2464 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2465 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2466}
2467
2468template<typename AttrClass>
2469static bool isEqual(const Function &Caller, const Function &Callee) {
2470 return Caller.getFnAttribute(AttrClass::getKind()) ==
2471 Callee.getFnAttribute(AttrClass::getKind());
2472}
2473
2474static bool isEqual(const Function &Caller, const Function &Callee,
2475 const StringRef &AttrName) {
2476 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2477}
2478
2479/// Compute the logical AND of the attributes of the caller and the
2480/// callee.
2481///
2482/// This function sets the caller's attribute to false if the callee's attribute
2483/// is false.
2484template<typename AttrClass>
2485static void setAND(Function &Caller, const Function &Callee) {
2486 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2487 !AttrClass::isSet(Callee, AttrClass::getKind()))
2488 AttrClass::set(Caller, AttrClass::getKind(), false);
2489}
2490
2491/// Compute the logical OR of the attributes of the caller and the
2492/// callee.
2493///
2494/// This function sets the caller's attribute to true if the callee's attribute
2495/// is true.
2496template<typename AttrClass>
2497static void setOR(Function &Caller, const Function &Callee) {
2498 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2499 AttrClass::isSet(Callee, AttrClass::getKind()))
2500 AttrClass::set(Caller, AttrClass::getKind(), true);
2501}
2502
2503/// If the inlined function had a higher stack protection level than the
2504/// calling function, then bump up the caller's stack protection level.
2505static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2506 // If the calling function has *no* stack protection level (e.g. it was built
2507 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2508 // change it as that could change the program's semantics.
2509 if (!Caller.hasStackProtectorFnAttr())
2510 return;
2511
2512 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2513 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2514 // clutter to the IR.
2515 AttributeMask OldSSPAttr;
2516 OldSSPAttr.addAttribute(Attribute::StackProtect)
2517 .addAttribute(Attribute::StackProtectStrong)
2518 .addAttribute(Attribute::StackProtectReq);
2519
2520 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2521 Caller.removeFnAttrs(OldSSPAttr);
2522 Caller.addFnAttr(Attribute::StackProtectReq);
2523 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2524 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2525 Caller.removeFnAttrs(OldSSPAttr);
2526 Caller.addFnAttr(Attribute::StackProtectStrong);
2527 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2528 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2529 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2530 Caller.addFnAttr(Attribute::StackProtect);
2531}
2532
2533/// If the inlined function required stack probes, then ensure that
2534/// the calling function has those too.
2535static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2536 if (!Caller.hasFnAttribute("probe-stack") &&
2537 Callee.hasFnAttribute("probe-stack")) {
2538 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2539 }
2540}
2541
2542/// If the inlined function defines the size of guard region
2543/// on the stack, then ensure that the calling function defines a guard region
2544/// that is no larger.
2545static void
2547 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2548 if (CalleeAttr.isValid()) {
2549 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2550 if (CallerAttr.isValid()) {
2551 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2552 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2553 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2554
2555 if (CallerStackProbeSize > CalleeStackProbeSize) {
2556 Caller.addFnAttr(CalleeAttr);
2557 }
2558 } else {
2559 Caller.addFnAttr(CalleeAttr);
2560 }
2561 }
2562}
2563
2564/// If the inlined function defines a min legal vector width, then ensure
2565/// the calling function has the same or larger min legal vector width. If the
2566/// caller has the attribute, but the callee doesn't, we need to remove the
2567/// attribute from the caller since we can't make any guarantees about the
2568/// caller's requirements.
2569/// This function is called after the inlining decision has been made so we have
2570/// to merge the attribute this way. Heuristics that would use
2571/// min-legal-vector-width to determine inline compatibility would need to be
2572/// handled as part of inline cost analysis.
2573static void
2575 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2576 if (CallerAttr.isValid()) {
2577 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2578 if (CalleeAttr.isValid()) {
2579 uint64_t CallerVectorWidth, CalleeVectorWidth;
2580 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2581 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2582 if (CallerVectorWidth < CalleeVectorWidth)
2583 Caller.addFnAttr(CalleeAttr);
2584 } else {
2585 // If the callee doesn't have the attribute then we don't know anything
2586 // and must drop the attribute from the caller.
2587 Caller.removeFnAttr("min-legal-vector-width");
2588 }
2589 }
2590}
2591
2592/// If the inlined function has null_pointer_is_valid attribute,
2593/// set this attribute in the caller post inlining.
2594static void
2596 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2597 Caller.addFnAttr(Attribute::NullPointerIsValid);
2598 }
2599}
2600
2601struct EnumAttr {
2602 static bool isSet(const Function &Fn,
2603 Attribute::AttrKind Kind) {
2604 return Fn.hasFnAttribute(Kind);
2605 }
2606
2607 static void set(Function &Fn,
2608 Attribute::AttrKind Kind, bool Val) {
2609 if (Val)
2610 Fn.addFnAttr(Kind);
2611 else
2612 Fn.removeFnAttr(Kind);
2613 }
2614};
2615
2617 static bool isSet(const Function &Fn,
2618 StringRef Kind) {
2619 auto A = Fn.getFnAttribute(Kind);
2620 return A.getValueAsString() == "true";
2621 }
2622
2623 static void set(Function &Fn,
2624 StringRef Kind, bool Val) {
2625 Fn.addFnAttr(Kind, Val ? "true" : "false");
2626 }
2627};
2628
2629#define GET_ATTR_NAMES
2630#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2631 struct ENUM_NAME##Attr : EnumAttr { \
2632 static enum Attribute::AttrKind getKind() { \
2633 return llvm::Attribute::ENUM_NAME; \
2634 } \
2635 };
2636#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2637 struct ENUM_NAME##Attr : StrBoolAttr { \
2638 static StringRef getKind() { return #DISPLAY_NAME; } \
2639 };
2640#include "llvm/IR/Attributes.inc"
2641
2642#define GET_ATTR_COMPAT_FUNC
2643#include "llvm/IR/Attributes.inc"
2644
2646 const Function &Callee) {
2647 return hasCompatibleFnAttrs(Caller, Callee);
2648}
2649
2651 const Function &B) {
2652 return hasCompatibleFnAttrs(A, B);
2653}
2654
2656 const Function &Callee) {
2657 mergeFnAttrs(Caller, Callee);
2658}
2659
2661 const Function &ToMerge) {
2662
2663 // We merge functions so that they meet the most general case.
2664 // For example, if the NoNansFPMathAttr is set in one function, but not in
2665 // the other, in the merged function we can say that the NoNansFPMathAttr
2666 // is not set.
2667 // However if we have the SpeculativeLoadHardeningAttr set true in one
2668 // function, but not the other, we make sure that the function retains
2669 // that aspect in the merged function.
2670 mergeFnAttrs(Base, ToMerge);
2671}
2672
2674 uint64_t Width) {
2675 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2676 if (Attr.isValid()) {
2677 uint64_t OldWidth;
2678 Attr.getValueAsString().getAsInteger(0, OldWidth);
2679 if (Width > OldWidth)
2680 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2681 }
2682}
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)
Definition: Attributes.cpp:87
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
Definition: Attributes.cpp:749
@ RetAttr
Definition: Attributes.cpp:752
@ IntersectPreserve
Definition: Attributes.cpp:753
@ IntersectMin
Definition: Attributes.cpp:755
@ IntersectCustom
Definition: Attributes.cpp:756
@ ParamAttr
Definition: Attributes.cpp:751
@ FnAttr
Definition: Attributes.cpp:750
@ IntersectPropertyMask
Definition: Attributes.cpp:757
@ IntersectAnd
Definition: Attributes.cpp:754
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 uint64_t packAllocSizeArgs(unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
Definition: Attributes.cpp:61
static uint64_t packVScaleRangeArgs(unsigned MinValue, std::optional< unsigned > MaxValue)
Definition: Attributes.cpp:81
static bool hasIntersectProperty(Attribute::AttrKind Kind, AttributeProperty Prop)
Definition: Attributes.cpp:786
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
Definition: Attributes.cpp:59
static std::pair< unsigned, std::optional< unsigned > > unpackAllocSizeArgs(uint64_t Num)
Definition: Attributes.cpp:71
static bool checkDenormMode(const Function &Caller, const Function &Callee)
static unsigned getAttributeProperties(Attribute::AttrKind Kind)
Definition: Attributes.cpp:763
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)
Definition: Attributes.cpp:769
static const char * getModRefStr(ModRefInfo MR)
Definition: Attributes.cpp:514
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:622
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
std::string Name
This file defines a hash set that can be used to remove duplication of nodes in a graph.
#define I(x, y, z)
Definition: MD5.cpp:58
Load MIR Sample Profile
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
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...
void Profile(FoldingSetNodeID &id) const
Used to insert APInt objects, or objects that contain APInt objects, into FoldingSets.
Definition: APInt.cpp:156
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
const T & back() const
back - Get the last element.
Definition: ArrayRef.h:177
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition: ArrayRef.h:231
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:168
iterator begin() const
Definition: ArrayRef.h:156
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:163
AttrBuilder & addStructRetAttr(Type *Ty)
This turns a sret type into the form used internally in Attribute.
AttrBuilder & addAlignmentAttr(MaybeAlign Align)
This turns an alignment into the form used internally in Attribute.
AttrBuilder & addVScaleRangeAttrFromRawRepr(uint64_t RawVScaleRangeRepr)
Add a vscale_range attribute, using the representation returned by Attribute.getIntValue().
std::optional< uint64_t > getRawIntAttr(Attribute::AttrKind Kind) const
Return raw (possibly packed/encoded) value of integer attribute or std::nullopt if not set.
AttrBuilder & addAllocKindAttr(AllocFnKind Kind)
Attribute getAttribute(Attribute::AttrKind Kind) const
Return Attribute with the given Kind.
AttrBuilder & addByRefAttr(Type *Ty)
This turns a byref type into the form used internally in Attribute.
AttrBuilder & addNoFPClassAttr(FPClassTest NoFPClassMask)
AttrBuilder & addCapturesAttr(CaptureInfo CI)
Add captures attribute.
bool overlaps(const AttributeMask &AM) const
Return true if the builder has any attribute that's in the specified builder.
AttrBuilder & merge(const AttrBuilder &B)
Add the attributes from the builder.
AttrBuilder & addVScaleRangeAttr(unsigned MinValue, std::optional< unsigned > MaxValue)
This turns two ints into the form used internally in Attribute.
AttrBuilder(LLVMContext &Ctx)
Definition: Attributes.h:1069
AttrBuilder & addRawIntAttr(Attribute::AttrKind Kind, uint64_t Value)
Add integer attribute with raw value (packed/encoded if necessary).
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
AttrBuilder & addByValAttr(Type *Ty)
This turns a byval type into the form used internally in Attribute.
AttrBuilder & addDereferenceableAttr(uint64_t Bytes)
This turns the number of dereferenceable bytes into the form used internally in Attribute.
AttrBuilder & addInitializesAttr(const ConstantRangeList &CRL)
Add initializes attribute.
bool contains(Attribute::AttrKind A) const
Return true if the builder has the specified attribute.
AttrBuilder & addMemoryAttr(MemoryEffects ME)
Add memory effect attribute.
AttrBuilder & addConstantRangeListAttr(Attribute::AttrKind Kind, ArrayRef< ConstantRange > Val)
Add a ConstantRangeList attribute with the given ranges.
AttrBuilder & addConstantRangeAttr(Attribute::AttrKind Kind, const ConstantRange &CR)
Add a ConstantRange attribute with the given range.
AttrBuilder & addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr)
Add an allocsize attribute, using the representation returned by Attribute.getIntValue().
AttrBuilder & addPreallocatedAttr(Type *Ty)
This turns a preallocated type into the form used internally in Attribute.
AttrBuilder & addStackAlignmentAttr(MaybeAlign Align)
This turns a stack alignment into the form used internally in Attribute.
AttrBuilder & addInAllocaAttr(Type *Ty)
This turns an inalloca type into the form used internally in Attribute.
AttrBuilder & removeAttribute(Attribute::AttrKind Val)
Remove an attribute from the builder.
bool operator==(const AttrBuilder &B) const
Type * getTypeAttr(Attribute::AttrKind Kind) const
Retrieve type for the given type attribute.
AttrBuilder & remove(const AttributeMask &AM)
Remove the attributes from the builder.
std::optional< ConstantRange > getRange() const
Retrieve the range if the attribute exists (std::nullopt is returned otherwise).
AttrBuilder & addDereferenceableOrNullAttr(uint64_t Bytes)
This turns the number of dereferenceable_or_null bytes into the form used internally in Attribute.
AttrBuilder & addTypeAttr(Attribute::AttrKind Kind, Type *Ty)
Add a type attribute with the given type.
std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
Retrieve the allocsize args, or std::nullopt if the attribute does not exist.
AttrBuilder & addAllocSizeAttr(unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
This turns one (or two) ints into the form used internally in Attribute.
AttrBuilder & addRangeAttr(const ConstantRange &CR)
Add range attribute.
AttrBuilder & addUWTableAttr(UWTableKind Kind)
This turns the unwind table kind into the form used internally in Attribute.
void addAttribute(Attribute::AttrKind Kind)
bool hasAttribute(Attribute::AttrKind Kind) const
int cmp(const AttributeImpl &AI, bool KindOnly) const
Used to sort attributes.
Definition: Attributes.cpp:867
bool isConstantRangeAttribute() const
Definition: AttributeImpl.h:66
bool hasAttribute(Attribute::AttrKind A) const
Definition: Attributes.cpp:814
void Profile(FoldingSetNodeID &ID) const
Definition: AttributeImpl.h:95
Type * getValueAsType() const
Definition: Attributes.cpp:850
Attribute::AttrKind getKindAsEnum() const
Definition: Attributes.cpp:824
bool operator<(const AttributeImpl &AI) const
Used when sorting the attributes.
Definition: Attributes.cpp:902
uint64_t getValueAsInt() const
Definition: Attributes.cpp:830
bool isIntAttribute() const
Definition: AttributeImpl.h:63
bool isTypeAttribute() const
Definition: AttributeImpl.h:65
bool getValueAsBool() const
Definition: Attributes.cpp:835
StringRef getKindAsString() const
Definition: Attributes.cpp:840
StringRef getValueAsString() const
Definition: Attributes.cpp:845
bool isEnumAttribute() const
Definition: AttributeImpl.h:62
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Definition: Attributes.cpp:861
bool isConstantRangeListAttribute() const
Definition: AttributeImpl.h:69
bool isStringAttribute() const
Definition: AttributeImpl.h:64
const ConstantRange & getValueAsConstantRange() const
Definition: Attributes.cpp:855
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
void Profile(FoldingSetNodeID &ID) const
AttributeListImpl(ArrayRef< AttributeSet > Sets)
iterator end() const
friend class AttributeList
bool hasAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const
Return true if the attribute exists at the given index.
Type * getParamStructRetType(unsigned ArgNo) const
Return the sret type for the specified function parameter.
AttributeList addDereferenceableParamAttr(LLVMContext &C, unsigned ArgNo, uint64_t Bytes) const
Add the dereferenceable attribute to the attribute set at the given arg index.
AttributeList removeAttributeAtIndex(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Remove the specified attribute at the specified index from this attribute list.
AttributeList addRangeRetAttr(LLVMContext &C, const ConstantRange &CR) const
Add the range attribute to the attribute set at the return value index.
bool hasAttributesAtIndex(unsigned Index) const
Return true if attribute exists at the given index.
friend class AttributeListImpl
Definition: Attributes.h:500
AttributeSet getFnAttrs() const
The function attributes are returned.
index_iterator indexes() const
Use this to iterate over the valid attribute indexes.
Definition: Attributes.h:1013
AttributeList removeAttributesAtIndex(LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const
Remove the specified attributes at the specified index from this attribute list.
friend class AttributeSet
Definition: Attributes.h:501
AttributeList()=default
iterator begin() const
MaybeAlign getRetStackAlignment() const
Get the stack alignment of the return value.
AttributeList addRetAttributes(LLVMContext &C, const AttrBuilder &B) const
Add a return value attribute to the list.
Definition: Attributes.h:620
void print(raw_ostream &O) const
AttributeList addDereferenceableRetAttr(LLVMContext &C, uint64_t Bytes) const
Add the dereferenceable attribute to the attribute set at the given index.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
AllocFnKind getAllocKind() const
bool isEmpty() const
Return true if there are no attributes.
Definition: Attributes.h:1025
AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
friend class AttrBuilder
Definition: Attributes.h:499
bool hasFnAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the function.
uint64_t getParamDereferenceableBytes(unsigned Index) const
Get the number of dereferenceable bytes (or zero if unknown) of an arg.
MaybeAlign getParamAlignment(unsigned ArgNo) const
Return the alignment for the specified function parameter.
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 end() const
Type * getParamInAllocaType(unsigned ArgNo) const
Return the inalloca type for the specified function parameter.
unsigned getNumAttrSets() const
FPClassTest getRetNoFPClass() const
Get the disallowed floating-point classes of the return value.
std::string getAsString(unsigned Index, bool InAttrGrp=false) const
Return the attributes at the index as a string.
UWTableKind getUWTableKind() const
Get the unwind table kind requested for the function.
MaybeAlign getRetAlignment() const
Return the alignment of the return value.
Type * getParamElementType(unsigned ArgNo) const
Return the elementtype type for the specified function parameter.
Attribute getAttributeAtIndex(unsigned Index, Attribute::AttrKind Kind) const
Return the attribute object that exists at the given index.
Type * getParamPreallocatedType(unsigned ArgNo) const
Return the preallocated type for the specified function parameter.
bool hasParentContext(LLVMContext &C) const
Return true if this attribute list belongs to the LLVMContext.
const AttributeSet * iterator
Definition: Attributes.h:981
MaybeAlign getFnStackAlignment() const
Get the stack alignment of the function.
AttributeList addAttributesAtIndex(LLVMContext &C, unsigned Index, const AttrBuilder &B) const
Add attributes to the attribute set at the given index.
Type * getParamByValType(unsigned ArgNo) const
Return the byval type for the specified function parameter.
MaybeAlign getParamStackAlignment(unsigned ArgNo) const
Return the stack alignment for the specified function parameter.
uint64_t getRetDereferenceableBytes() const
Get the number of dereferenceable bytes (or zero if unknown) of the return value.
AttributeList addAllocSizeParamAttr(LLVMContext &C, unsigned ArgNo, unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg) const
Add the allocsize attribute to the attribute set at the given arg index.
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const
Get the number of dereferenceable_or_null bytes (or zero if unknown) of an arg.
AttributeList addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned ArgNo, uint64_t Bytes) const
Add the dereferenceable_or_null attribute to the attribute set at the given arg index.
AttributeSet getAttributes(unsigned Index) const
The attributes for the specified index are returned.
FPClassTest getParamNoFPClass(unsigned ArgNo) const
Get the disallowed floating-point classes of the argument value.
std::optional< AttributeList > intersectWith(LLVMContext &C, AttributeList Other) const
Try to intersect this AttributeList with Other.
Type * getParamByRefType(unsigned ArgNo) const
Return the byref type for the specified function parameter.
AttributeList addAttributeAtIndex(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Add an attribute to the attribute set at the given index.
AttributeSet getParamAttrs(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
AttributeList addParamAttributes(LLVMContext &C, unsigned ArgNo, const AttrBuilder &B) const
Add an argument attribute to the list.
Definition: Attributes.h:649
std::optional< ConstantRange > getParamRange(unsigned ArgNo) const
Get range (or std::nullopt if unknown) of an arg.
uint64_t getRetDereferenceableOrNullBytes() const
Get the number of dereferenceable_or_null bytes (or zero if unknown) of the return value.
AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind) const
Add an argument attribute to the list.
Definition: Attributes.h:628
MemoryEffects getMemoryEffects() const
Returns memory effects of the function.
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
Definition: AttributeMask.h:44
bool contains(Attribute::AttrKind A) const
Return true if the builder has the specified attribute.
Definition: AttributeMask.h:67
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
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
uint64_t getDereferenceableBytes() const
unsigned getNumAttributes() const
Return the number of attributes this AttributeList contains.
void Profile(FoldingSetNodeID &ID) const
std::string getAsString(bool InAttrGrp) const
static AttributeSetNode * get(LLVMContext &C, const AttrBuilder &B)
FPClassTest getNoFPClass() const
Attribute getAttribute(Attribute::AttrKind Kind) const
AllocFnKind getAllocKind() const
bool hasAttributes() const
Return true if attributes exists in this set.
Definition: Attributes.h:411
AttributeSet removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Remove the specified attribute from this set.
Definition: Attributes.cpp:946
Type * getInAllocaType() const
Type * getByValType() const
AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
Definition: Attributes.cpp:933
MemoryEffects getMemoryEffects() const
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists in this set.
std::optional< AttributeSet > intersectWith(LLVMContext &C, AttributeSet Other) const
Try to intersect this AttributeSet with Other.
Definition: Attributes.cpp:974
Type * getStructRetType() const
std::string getAsString(bool InAttrGrp=false) const
unsigned getVScaleRangeMin() const
std::optional< std::pair< unsigned, std::optional< unsigned > > > getAllocSizeArgs() const
UWTableKind getUWTableKind() const
bool hasParentContext(LLVMContext &C) const
Return true if this attribute set belongs to the LLVMContext.
iterator begin() const
iterator end() const
AttributeSet removeAttributes(LLVMContext &C, const AttributeMask &AttrsToRemove) const
Remove the specified attributes from this set.
Definition: Attributes.cpp:962
std::optional< unsigned > getVScaleRangeMax() const
MaybeAlign getStackAlignment() const
Attribute getAttribute(Attribute::AttrKind Kind) const
Return the attribute object.
Type * getPreallocatedType() const
uint64_t getDereferenceableBytes() const
MaybeAlign getAlignment() const
FPClassTest getNoFPClass() const
Type * getElementType() const
Type * getByRefType() const
CaptureInfo getCaptureInfo() const
AttributeSet()=default
AttributeSet is a trivially copyable value type.
static AttributeSet get(LLVMContext &C, const AttrBuilder &B)
Definition: Attributes.cpp:910
uint64_t getDereferenceableOrNullBytes() const
unsigned getNumAttributes() const
Return the number of attributes in this set.
AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
Definition: Attributes.cpp:918
void dump() const
bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
Definition: Attributes.cpp:348
static Attribute getWithStructRetType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:260
static Attribute::AttrKind getAttrKindFromName(StringRef AttrName)
Definition: Attributes.cpp:305
bool isEnumAttribute() const
Return true if the attribute is an Attribute::AttrKind type.
Definition: Attributes.cpp:340
static Attribute getWithStackAlignment(LLVMContext &Context, Align Alignment)
Definition: Attributes.cpp:239
const ConstantRange & getRange() const
Returns the value of the range attribute.
Definition: Attributes.cpp:502
static bool intersectWithCustom(AttrKind Kind)
Definition: Attributes.cpp:806
bool isIntAttribute() const
Return true if the attribute is an integer attribute.
Definition: Attributes.cpp:344
static Attribute getWithByRefType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:264
std::optional< unsigned > getVScaleRangeMax() const
Returns the maximum value for the vscale_range attribute or std::nullopt when unknown.
Definition: Attributes.cpp:466
uint64_t getValueAsInt() const
Return the attribute's value as an integer.
Definition: Attributes.cpp:371
unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
Definition: Attributes.cpp:460
AllocFnKind getAllocKind() const
Definition: Attributes.cpp:478
bool isConstantRangeAttribute() const
Return true if the attribute is a ConstantRange attribute.
Definition: Attributes.cpp:356
StringRef getKindAsString() const
Return the attribute's kind as a string.
Definition: Attributes.cpp:385
static Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:268
static bool intersectWithMin(AttrKind Kind)
Definition: Attributes.cpp:803
static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
Definition: Attributes.cpp:95
static bool canUseAsRetAttr(AttrKind Kind)
Definition: Attributes.cpp:782
static bool isTypeAttrKind(AttrKind Kind)
Definition: Attributes.h:105
std::string getAsString(bool InAttrGrp=false) const
The Attribute is converted to a string of equivalent mnemonic.
Definition: Attributes.cpp:528
uint64_t getDereferenceableOrNullBytes() const
Returns the number of dereferenceable_or_null bytes from the dereferenceable_or_null attribute.
Definition: Attributes.cpp:446
static Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)
Definition: Attributes.cpp:244
std::pair< unsigned, std::optional< unsigned > > getAllocSizeArgs() const
Returns the argument numbers for the allocsize attribute.
Definition: Attributes.cpp:454
static Attribute getWithUWTableKind(LLVMContext &Context, UWTableKind Kind)
Definition: Attributes.cpp:276
FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
Definition: Attributes.cpp:496
static Attribute getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
Definition: Attributes.cpp:292
Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
Definition: Attributes.cpp:364
Attribute()=default
bool getValueAsBool() const
Return the attribute's value as a boolean.
Definition: Attributes.cpp:378
ArrayRef< ConstantRange > getInitializes() const
Returns the value of the initializes attribute.
Definition: Attributes.cpp:508
const ConstantRange & getValueAsConstantRange() const
Return the attribute's value as a ConstantRange.
Definition: Attributes.cpp:406
uint64_t getDereferenceableBytes() const
Returns the number of dereferenceable bytes from the dereferenceable attribute.
Definition: Attributes.cpp:439
static Attribute getWithVScaleRangeArgs(LLVMContext &Context, unsigned MinValue, unsigned MaxValue)
Definition: Attributes.cpp:299
MemoryEffects getMemoryEffects() const
Returns memory effects.
Definition: Attributes.cpp:484
void Profile(FoldingSetNodeID &ID) const
Definition: Attributes.cpp:745
UWTableKind getUWTableKind() const
Definition: Attributes.cpp:472
static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, uint64_t Bytes)
Definition: Attributes.cpp:250
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
Definition: Attributes.cpp:412
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:392
static bool isExistingAttribute(StringRef Name)
Return true if the provided string matches the IR name of an attribute.
Definition: Attributes.cpp:328
bool hasKindAsEnum() const
Returns true if the attribute's kind can be represented as an enum (Enum, Integer,...
Definition: Attributes.h:218
static StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind)
Definition: Attributes.cpp:314
static bool canUseAsFnAttr(AttrKind Kind)
Definition: Attributes.cpp:774
static bool intersectWithAnd(AttrKind Kind)
Definition: Attributes.cpp:800
static Attribute getWithNoFPClass(LLVMContext &Context, FPClassTest Mask)
Definition: Attributes.cpp:286
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition: Attributes.h:86
@ None
No attributes have been set.
Definition: Attributes.h:88
@ EndAttrKinds
Sentinel value useful for loops.
Definition: Attributes.h:91
static bool isConstantRangeAttrKind(AttrKind Kind)
Definition: Attributes.h:108
bool hasParentContext(LLVMContext &C) const
Return true if this attribute belongs to the LLVMContext.
Definition: Attributes.cpp:720
bool isTypeAttribute() const
Return true if the attribute is a type attribute.
Definition: Attributes.cpp:352
static Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:272
static bool isIntAttrKind(AttrKind Kind)
Definition: Attributes.h:102
static bool isConstantRangeListAttrKind(AttrKind Kind)
Definition: Attributes.h:111
bool isConstantRangeListAttribute() const
Return true if the attribute is a ConstantRangeList attribute.
Definition: Attributes.cpp:360
static Attribute getWithByValType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:256
bool hasAttribute(AttrKind Val) const
Return true if the attribute is present.
Definition: Attributes.cpp:418
static bool isEnumAttrKind(AttrKind Kind)
Definition: Attributes.h:99
static Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
Definition: Attributes.cpp:281
static bool canUseAsParamAttr(AttrKind Kind)
Definition: Attributes.cpp:778
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition: Attributes.h:208
MaybeAlign getStackAlignment() const
Returns the stack alignment field of an attribute as a byte alignment value.
Definition: Attributes.cpp:433
MaybeAlign getAlignment() const
Returns the alignment field of an attribute as a byte alignment value.
Definition: Attributes.cpp:427
CaptureInfo getCaptureInfo() const
Returns information from captures attribute.
Definition: Attributes.cpp:490
static bool intersectMustPreserve(AttrKind Kind)
Definition: Attributes.cpp:797
int cmpKind(Attribute A) const
Used to sort attribute by kind.
Definition: Attributes.cpp:728
bool operator<(Attribute A) const
Less-than operator. Useful for sorting the attributes list.
Definition: Attributes.cpp:738
static Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
Definition: Attributes.cpp:234
Type * getValueAsType() const
Return the attribute's value as a Type.
Definition: Attributes.cpp:399
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
Definition: Allocator.h:148
Represents which components of the pointer may be captured in which location.
Definition: ModRef.h:318
static CaptureInfo createFromIntValue(uint32_t Data)
Definition: ModRef.h:363
static CaptureInfo all()
Create CaptureInfo that may capture all components of the pointer.
Definition: ModRef.h:331
uint32_t toIntValue() const
Convert CaptureInfo into an encoded integer value (used by captures attribute).
Definition: ModRef.h:370
static size_t totalSizeToAlloc(ArrayRef< ConstantRange > Val)
This class represents a list of constant ranges.
ArrayRef< ConstantRange > rangesRef() const
void print(raw_ostream &OS) const
Print out the ranges to a stream.
This class represents a range of values.
Definition: ConstantRange.h:47
const APInt & getLower() const
Return the lower value for this range.
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.
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 bool isSupportedFloatingPointType(Type *Ty)
Returns true if Ty is a supported floating-point type for phi, select, or call FPMathOperators.
Definition: Operator.h:349
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
Definition: FoldingSet.h:327
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
FoldingSet< AttributeImpl > AttrsSet
BumpPtrAllocator Alloc
FoldingSet< AttributeSetNode > AttrsSetNodes
FoldingSet< AttributeListImpl > AttrsLists
SpecificBumpPtrAllocator< ConstantRangeAttributeImpl > ConstantRangeAttributeAlloc
std::vector< ConstantRangeListAttributeImpl * > ConstantRangeListAttributes
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
LLVMContextImpl *const pImpl
Definition: LLVMContext.h:69
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition: ModRef.h:165
static MemoryEffectsBase createFromIntValue(uint32_t Data)
Create MemoryEffectsBase from an encoded integer value (used by memory attribute).
Definition: ModRef.h:154
static auto locations()
Returns iterator over all supported location kinds.
Definition: ModRef.h:95
uint32_t toIntValue() const
Convert MemoryEffectsBase into an encoded integer value (used by memory attribute).
Definition: ModRef.h:160
static MemoryEffectsBase unknown()
Create MemoryEffectsBase that can read and write any memory.
Definition: ModRef.h:112
size_t size() const
Definition: SmallVector.h:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:937
void reserve(size_type N)
Definition: SmallVector.h:663
void resize(size_type N)
Definition: SmallVector.h:638
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
static size_t totalSizeToAlloc(StringRef Kind, StringRef Val)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:470
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:229
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
int compare(StringRef RHS) const
compare - Compare two strings; the result is negative, zero, or positive if this string is lexicograp...
Definition: StringRef.h:183
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
R Default(T Value)
Definition: StringSwitch.h:182
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
Definition: Type.h:243
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:264
void print(raw_ostream &O, bool IsForDebug=false, bool NoDetails=false) const
Print the current type.
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
Definition: Type.h:267
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:237
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:139
LLVM Value Representation.
Definition: Value.h:74
static constexpr uint64_t MaximumAlignment
Definition: Value.h:811
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:661
This class provides various memory handling functions that manipulate MemoryBlock instances.
Definition: Memory.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool areInlineCompatible(const Function &Caller, const Function &Callee)
AttributeMask getUBImplyingAttributes()
Get param/return attributes which imply immediate undefined behavior if an invalid value is passed.
bool isNoFPClassCompatibleType(Type *Ty)
Returns true if this is a type legal for the 'nofpclass' attribute.
bool areOutlineCompatible(const Function &A, const Function &B)
Checks if there are any incompatible function attributes between A and B.
void updateMinLegalVectorWidthAttr(Function &Fn, uint64_t Width)
Update min-legal-vector-width if it is in Attribute and less than Width.
void mergeAttributesForOutlining(Function &Base, const Function &ToMerge)
Merges the functions attributes from ToMerge into function Base.
AttributeMask typeIncompatible(Type *Ty, AttributeSet AS, AttributeSafetyKind ASK=ASK_ALL)
Which attributes cannot be applied to a type.
void mergeAttributesForInlining(Function &Caller, const Function &Callee)
Merge caller's and callee's attributes.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:1739
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
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:1697
AllocFnKind
Definition: Attributes.h:49
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2115
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:1746
UWTableKind
Definition: CodeGen.h:120
@ None
No unwind table requested.
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1664
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
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:1753
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:1926
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
Definition: ModRef.h:27
@ Ref
The access may reference the value stored in memory.
@ ModRef
The access may reference and may modify the value stored in memory.
@ Mod
The access may modify the value stored in memory.
@ NoModRef
The access neither references nor modifies the value stored in memory.
@ ArgMem
Access to memory via argument pointers.
@ Other
Any other memory.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ InaccessibleMem
Memory that is inaccessible via LLVM IR.
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:1978
OutputIt copy(R &&Range, OutputIt Out)
Definition: STLExtras.h:1841
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:2099
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:860
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
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
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:117
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition: Alignment.h:141
Function object to check whether the first component of a container supported by std::get (like std::...
Definition: STLExtras.h:1467