LLVM 21.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
292 return get(Context, Captures, CI.toIntValue());
293}
294
296Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
297 const std::optional<unsigned> &NumElemsArg) {
298 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&
299 "Invalid allocsize arguments -- given allocsize(0, 0)");
300 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
301}
302
304 unsigned MinValue,
305 unsigned MaxValue) {
306 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
307}
308
310 return StringSwitch<Attribute::AttrKind>(AttrName)
311#define GET_ATTR_NAMES
312#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
313 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
314#include "llvm/IR/Attributes.inc"
316}
317
319 switch (AttrKind) {
320#define GET_ATTR_NAMES
321#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
322 case Attribute::ENUM_NAME: \
323 return #DISPLAY_NAME;
324#include "llvm/IR/Attributes.inc"
325 case Attribute::None:
326 return "none";
327 default:
328 llvm_unreachable("invalid Kind");
329 }
330}
331
334#define GET_ATTR_NAMES
335#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
336#include "llvm/IR/Attributes.inc"
337 .Default(false);
338}
339
340//===----------------------------------------------------------------------===//
341// Attribute Accessor Methods
342//===----------------------------------------------------------------------===//
343
345 return pImpl && pImpl->isEnumAttribute();
346}
347
349 return pImpl && pImpl->isIntAttribute();
350}
351
353 return pImpl && pImpl->isStringAttribute();
354}
355
357 return pImpl && pImpl->isTypeAttribute();
358}
359
361 return pImpl && pImpl->isConstantRangeAttribute();
362}
363
365 return pImpl && pImpl->isConstantRangeListAttribute();
366}
367
369 if (!pImpl) return None;
371 "Invalid attribute type to get the kind as an enum!");
372 return pImpl->getKindAsEnum();
373}
374
376 if (!pImpl) return 0;
378 "Expected the attribute to be an integer attribute!");
379 return pImpl->getValueAsInt();
380}
381
383 if (!pImpl) return false;
385 "Expected the attribute to be a string attribute!");
386 return pImpl->getValueAsBool();
387}
388
390 if (!pImpl) return {};
392 "Invalid attribute type to get the kind as a string!");
393 return pImpl->getKindAsString();
394}
395
397 if (!pImpl) return {};
399 "Invalid attribute type to get the value as a string!");
400 return pImpl->getValueAsString();
401}
402
404 if (!pImpl) return {};
406 "Invalid attribute type to get the value as a type!");
407 return pImpl->getValueAsType();
408}
409
412 "Invalid attribute type to get the value as a ConstantRange!");
413 return pImpl->getValueAsConstantRange();
414}
415
418 "Invalid attribute type to get the value as a ConstantRangeList!");
419 return pImpl->getValueAsConstantRangeList();
420}
421
423 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
424}
425
427 if (!isStringAttribute()) return false;
428 return pImpl && pImpl->hasAttribute(Kind);
429}
430
432 assert(hasAttribute(Attribute::Alignment) &&
433 "Trying to get alignment from non-alignment attribute!");
434 return MaybeAlign(pImpl->getValueAsInt());
435}
436
438 assert(hasAttribute(Attribute::StackAlignment) &&
439 "Trying to get alignment from non-alignment attribute!");
440 return MaybeAlign(pImpl->getValueAsInt());
441}
442
444 assert(hasAttribute(Attribute::Dereferenceable) &&
445 "Trying to get dereferenceable bytes from "
446 "non-dereferenceable attribute!");
447 return pImpl->getValueAsInt();
448}
449
451 assert(hasAttribute(Attribute::DereferenceableOrNull) &&
452 "Trying to get dereferenceable bytes from "
453 "non-dereferenceable attribute!");
454 return pImpl->getValueAsInt();
455}
456
457std::pair<unsigned, std::optional<unsigned>>
459 assert(hasAttribute(Attribute::AllocSize) &&
460 "Trying to get allocsize args from non-allocsize attribute");
461 return unpackAllocSizeArgs(pImpl->getValueAsInt());
462}
463
465 assert(hasAttribute(Attribute::VScaleRange) &&
466 "Trying to get vscale args from non-vscale attribute");
467 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).first;
468}
469
470std::optional<unsigned> Attribute::getVScaleRangeMax() const {
471 assert(hasAttribute(Attribute::VScaleRange) &&
472 "Trying to get vscale args from non-vscale attribute");
473 return unpackVScaleRangeArgs(pImpl->getValueAsInt()).second;
474}
475
477 assert(hasAttribute(Attribute::UWTable) &&
478 "Trying to get unwind table kind from non-uwtable attribute");
479 return UWTableKind(pImpl->getValueAsInt());
480}
481
483 assert(hasAttribute(Attribute::AllocKind) &&
484 "Trying to get allockind value from non-allockind attribute");
485 return AllocFnKind(pImpl->getValueAsInt());
486}
487
489 assert(hasAttribute(Attribute::Memory) &&
490 "Can only call getMemoryEffects() on memory attribute");
492}
493
495 assert(hasAttribute(Attribute::Captures) &&
496 "Can only call getCaptureInfo() on captures attribute");
498}
499
501 assert(hasAttribute(Attribute::NoFPClass) &&
502 "Can only call getNoFPClass() on nofpclass attribute");
503 return static_cast<FPClassTest>(pImpl->getValueAsInt());
504}
505
507 assert(hasAttribute(Attribute::Range) &&
508 "Trying to get range args from non-range attribute");
509 return pImpl->getValueAsConstantRange();
510}
511
513 assert(hasAttribute(Attribute::Initializes) &&
514 "Trying to get initializes attr from non-ConstantRangeList attribute");
515 return pImpl->getValueAsConstantRangeList();
516}
517
518static const char *getModRefStr(ModRefInfo MR) {
519 switch (MR) {
521 return "none";
522 case ModRefInfo::Ref:
523 return "read";
524 case ModRefInfo::Mod:
525 return "write";
527 return "readwrite";
528 }
529 llvm_unreachable("Invalid ModRefInfo");
530}
531
532std::string Attribute::getAsString(bool InAttrGrp) const {
533 if (!pImpl) return {};
534
535 if (isEnumAttribute())
537
538 if (isTypeAttribute()) {
539 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
540 Result += '(';
541 raw_string_ostream OS(Result);
542 getValueAsType()->print(OS, false, true);
543 OS.flush();
544 Result += ')';
545 return Result;
546 }
547
548 // FIXME: These should be output like this:
549 //
550 // align=4
551 // alignstack=8
552 //
553 if (hasAttribute(Attribute::Alignment))
554 return (InAttrGrp ? "align=" + Twine(getValueAsInt())
555 : "align " + Twine(getValueAsInt()))
556 .str();
557
558 auto AttrWithBytesToString = [&](const char *Name) {
559 return (InAttrGrp ? Name + ("=" + Twine(getValueAsInt()))
560 : Name + ("(" + Twine(getValueAsInt())) + ")")
561 .str();
562 };
563
564 if (hasAttribute(Attribute::StackAlignment))
565 return AttrWithBytesToString("alignstack");
566
567 if (hasAttribute(Attribute::Dereferenceable))
568 return AttrWithBytesToString("dereferenceable");
569
570 if (hasAttribute(Attribute::DereferenceableOrNull))
571 return AttrWithBytesToString("dereferenceable_or_null");
572
573 if (hasAttribute(Attribute::AllocSize)) {
574 unsigned ElemSize;
575 std::optional<unsigned> NumElems;
576 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
577
578 return (NumElems
579 ? "allocsize(" + Twine(ElemSize) + "," + Twine(*NumElems) + ")"
580 : "allocsize(" + Twine(ElemSize) + ")")
581 .str();
582 }
583
584 if (hasAttribute(Attribute::VScaleRange)) {
585 unsigned MinValue = getVScaleRangeMin();
586 std::optional<unsigned> MaxValue = getVScaleRangeMax();
587 return ("vscale_range(" + Twine(MinValue) + "," +
588 Twine(MaxValue.value_or(0)) + ")")
589 .str();
590 }
591
592 if (hasAttribute(Attribute::UWTable)) {
594 assert(Kind != UWTableKind::None && "uwtable attribute should not be none");
595 return Kind == UWTableKind::Default ? "uwtable" : "uwtable(sync)";
596 }
597
598 if (hasAttribute(Attribute::AllocKind)) {
599 AllocFnKind Kind = getAllocKind();
602 parts.push_back("alloc");
604 parts.push_back("realloc");
606 parts.push_back("free");
608 parts.push_back("uninitialized");
610 parts.push_back("zeroed");
612 parts.push_back("aligned");
613 return ("allockind(\"" +
614 Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
615 .str();
616 }
617
618 if (hasAttribute(Attribute::Memory)) {
619 std::string Result;
620 raw_string_ostream OS(Result);
621 bool First = true;
622 OS << "memory(";
623
625
626 // Print access kind for "other" as the default access kind. This way it
627 // will apply to any new location kinds that get split out of "other".
629 if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
630 First = false;
631 OS << getModRefStr(OtherMR);
632 }
633
634 for (auto Loc : MemoryEffects::locations()) {
635 ModRefInfo MR = ME.getModRef(Loc);
636 if (MR == OtherMR)
637 continue;
638
639 if (!First)
640 OS << ", ";
641 First = false;
642
643 switch (Loc) {
645 OS << "argmem: ";
646 break;
648 OS << "inaccessiblemem: ";
649 break;
651 llvm_unreachable("This is represented as the default access kind");
652 }
653 OS << getModRefStr(MR);
654 }
655 OS << ")";
656 OS.flush();
657 return Result;
658 }
659
660 if (hasAttribute(Attribute::Captures)) {
661 std::string Result;
662 raw_string_ostream OS(Result);
663 OS << getCaptureInfo();
664 return Result;
665 }
666
667 if (hasAttribute(Attribute::NoFPClass)) {
668 std::string Result = "nofpclass";
669 raw_string_ostream OS(Result);
670 OS << getNoFPClass();
671 return Result;
672 }
673
674 if (hasAttribute(Attribute::Range)) {
675 std::string Result;
676 raw_string_ostream OS(Result);
678 OS << "range(";
679 OS << "i" << CR.getBitWidth() << " ";
680 OS << CR.getLower() << ", " << CR.getUpper();
681 OS << ")";
682 OS.flush();
683 return Result;
684 }
685
686 if (hasAttribute(Attribute::Initializes)) {
687 std::string Result;
688 raw_string_ostream OS(Result);
690 OS << "initializes(";
691 CRL.print(OS);
692 OS << ")";
693 OS.flush();
694 return Result;
695 }
696
697 // Convert target-dependent attributes to strings of the form:
698 //
699 // "kind"
700 // "kind" = "value"
701 //
702 if (isStringAttribute()) {
703 std::string Result;
704 {
705 raw_string_ostream OS(Result);
706 OS << '"' << getKindAsString() << '"';
707
708 // Since some attribute strings contain special characters that cannot be
709 // printable, those have to be escaped to make the attribute value
710 // printable as is. e.g. "\01__gnu_mcount_nc"
711 const auto &AttrVal = pImpl->getValueAsString();
712 if (!AttrVal.empty()) {
713 OS << "=\"";
714 printEscapedString(AttrVal, OS);
715 OS << "\"";
716 }
717 }
718 return Result;
719 }
720
721 llvm_unreachable("Unknown attribute");
722}
723
725 assert(isValid() && "invalid Attribute doesn't refer to any context");
727 pImpl->Profile(ID);
728 void *Unused;
729 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
730}
731
733 if (!pImpl && !A.pImpl)
734 return 0;
735 if (!pImpl)
736 return 1;
737 if (!A.pImpl)
738 return -1;
739 return pImpl->cmp(*A.pImpl, /*KindOnly=*/true);
740}
741
743 if (!pImpl && !A.pImpl) return false;
744 if (!pImpl) return true;
745 if (!A.pImpl) return false;
746 return *pImpl < *A.pImpl;
747}
748
750 ID.AddPointer(pImpl);
751}
752
754 FnAttr = (1 << 0),
755 ParamAttr = (1 << 1),
756 RetAttr = (1 << 2),
758 IntersectAnd = (1 << 3),
759 IntersectMin = (2 << 3),
760 IntersectCustom = (3 << 3),
762};
763
764#define GET_ATTR_PROP_TABLE
765#include "llvm/IR/Attributes.inc"
766
768 unsigned Index = Kind - 1;
769 assert(Index < std::size(AttrPropTable) && "Invalid attribute kind");
770 return AttrPropTable[Index];
771}
772
774 AttributeProperty Prop) {
775 return getAttributeProperties(Kind) & Prop;
776}
777
779 return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
780}
781
783 return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
784}
785
787 return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
788}
789
791 AttributeProperty Prop) {
792 assert((Prop == AttributeProperty::IntersectPreserve ||
793 Prop == AttributeProperty::IntersectAnd ||
794 Prop == AttributeProperty::IntersectMin ||
795 Prop == AttributeProperty::IntersectCustom) &&
796 "Unknown intersect property");
797 return (getAttributeProperties(Kind) &
798 AttributeProperty::IntersectPropertyMask) == Prop;
799}
800
802 return hasIntersectProperty(Kind, AttributeProperty::IntersectPreserve);
803}
805 return hasIntersectProperty(Kind, AttributeProperty::IntersectAnd);
806}
808 return hasIntersectProperty(Kind, AttributeProperty::IntersectMin);
809}
811 return hasIntersectProperty(Kind, AttributeProperty::IntersectCustom);
812}
813
814//===----------------------------------------------------------------------===//
815// AttributeImpl Definition
816//===----------------------------------------------------------------------===//
817
819 if (isStringAttribute()) return false;
820 return getKindAsEnum() == A;
821}
822
824 if (!isStringAttribute()) return false;
825 return getKindAsString() == Kind;
826}
827
831 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
832}
833
836 return static_cast<const IntAttributeImpl *>(this)->getValue();
837}
838
840 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
841 return getValueAsString() == "true";
842}
843
846 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
847}
848
851 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
852}
853
856 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
857}
858
861 return static_cast<const ConstantRangeAttributeImpl *>(this)
862 ->getConstantRangeValue();
863}
864
867 return static_cast<const ConstantRangeListAttributeImpl *>(this)
868 ->getConstantRangeListValue();
869}
870
871int AttributeImpl::cmp(const AttributeImpl &AI, bool KindOnly) const {
872 if (this == &AI)
873 return 0;
874
875 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
876 // relative to their enum value) and then strings.
877 if (!isStringAttribute()) {
878 if (AI.isStringAttribute())
879 return -1;
880
881 if (getKindAsEnum() != AI.getKindAsEnum())
882 return getKindAsEnum() < AI.getKindAsEnum() ? -1 : 1;
883 else if (KindOnly)
884 return 0;
885
886 assert(!AI.isEnumAttribute() && "Non-unique attribute");
887 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable");
888 assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges");
890 "Unclear how to compare range list");
891 // TODO: Is this actually needed?
892 assert(AI.isIntAttribute() && "Only possibility left");
893 if (getValueAsInt() < AI.getValueAsInt())
894 return -1;
895 return getValueAsInt() == AI.getValueAsInt() ? 0 : 1;
896 }
897 if (!AI.isStringAttribute())
898 return 1;
899 if (KindOnly)
901 if (getKindAsString() == AI.getKindAsString())
904}
905
907 return cmp(AI, /*KindOnly=*/false) < 0;
908}
909
910//===----------------------------------------------------------------------===//
911// AttributeSet Definition
912//===----------------------------------------------------------------------===//
913
916}
917
919 return AttributeSet(AttributeSetNode::get(C, Attrs));
920}
921
923 Attribute::AttrKind Kind) const {
924 if (hasAttribute(Kind)) return *this;
925 AttrBuilder B(C);
926 B.addAttribute(Kind);
928}
929
931 StringRef Value) const {
932 AttrBuilder B(C);
933 B.addAttribute(Kind, Value);
935}
936
938 const AttributeSet AS) const {
939 if (!hasAttributes())
940 return AS;
941
942 if (!AS.hasAttributes())
943 return *this;
944
945 AttrBuilder B(C, *this);
946 B.merge(AttrBuilder(C, AS));
947 return get(C, B);
948}
949
951 Attribute::AttrKind Kind) const {
952 if (!hasAttribute(Kind)) return *this;
953 AttrBuilder B(C, *this);
954 B.removeAttribute(Kind);
955 return get(C, B);
956}
957
959 StringRef Kind) const {
960 if (!hasAttribute(Kind)) return *this;
961 AttrBuilder B(C, *this);
962 B.removeAttribute(Kind);
963 return get(C, B);
964}
965
967 const AttributeMask &Attrs) const {
968 AttrBuilder B(C, *this);
969 // If there is nothing to remove, directly return the original set.
970 if (!B.overlaps(Attrs))
971 return *this;
972
973 B.remove(Attrs);
974 return get(C, B);
975}
976
977std::optional<AttributeSet>
979 if (*this == Other)
980 return *this;
981
982 AttrBuilder Intersected(C);
983 // Iterate over both attr sets at once.
984 auto ItBegin0 = begin();
985 auto ItEnd0 = end();
986 auto ItBegin1 = Other.begin();
987 auto ItEnd1 = Other.end();
988
989 while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {
990 // Loop through all attributes in both this and Other in sorted order. If
991 // the attribute is only present in one of the sets, it will be set in
992 // Attr0. If it is present in both sets both Attr0 and Attr1 will be set.
993 Attribute Attr0, Attr1;
994 if (ItBegin1 == ItEnd1)
995 Attr0 = *ItBegin0++;
996 else if (ItBegin0 == ItEnd0)
997 Attr0 = *ItBegin1++;
998 else {
999 int Cmp = ItBegin0->cmpKind(*ItBegin1);
1000 if (Cmp == 0) {
1001 Attr0 = *ItBegin0++;
1002 Attr1 = *ItBegin1++;
1003 } else if (Cmp < 0)
1004 Attr0 = *ItBegin0++;
1005 else
1006 Attr0 = *ItBegin1++;
1007 }
1008 assert(Attr0.isValid() && "Iteration should always yield a valid attr");
1009
1010 auto IntersectEq = [&]() {
1011 if (!Attr1.isValid())
1012 return false;
1013 if (Attr0 != Attr1)
1014 return false;
1015 Intersected.addAttribute(Attr0);
1016 return true;
1017 };
1018
1019 // Non-enum assume we must preserve. Handle early so we can unconditionally
1020 // use Kind below.
1021 if (!Attr0.hasKindAsEnum()) {
1022 if (!IntersectEq())
1023 return std::nullopt;
1024 continue;
1025 }
1026
1027 Attribute::AttrKind Kind = Attr0.getKindAsEnum();
1028 // If we don't have both attributes, then fail if the attribute is
1029 // must-preserve or drop it otherwise.
1030 if (!Attr1.isValid()) {
1032 return std::nullopt;
1033 continue;
1034 }
1035
1036 // We have both attributes so apply the intersection rule.
1037 assert(Attr1.hasKindAsEnum() && Kind == Attr1.getKindAsEnum() &&
1038 "Iterator picked up two different attributes in the same iteration");
1039
1040 // Attribute we can intersect with "and"
1041 if (Attribute::intersectWithAnd(Kind)) {
1043 "Invalid attr type of intersectAnd");
1044 Intersected.addAttribute(Kind);
1045 continue;
1046 }
1047
1048 // Attribute we can intersect with "min"
1049 if (Attribute::intersectWithMin(Kind)) {
1051 "Invalid attr type of intersectMin");
1052 uint64_t NewVal = std::min(Attr0.getValueAsInt(), Attr1.getValueAsInt());
1053 Intersected.addRawIntAttr(Kind, NewVal);
1054 continue;
1055 }
1056 // Attribute we can intersect but need a custom rule for.
1058 switch (Kind) {
1059 case Attribute::Alignment:
1060 // If `byval` is present, alignment become must-preserve. This is
1061 // handled below if we have `byval`.
1062 Intersected.addAlignmentAttr(
1063 std::min(Attr0.getAlignment().valueOrOne(),
1064 Attr1.getAlignment().valueOrOne()));
1065 break;
1066 case Attribute::Memory:
1067 Intersected.addMemoryAttr(Attr0.getMemoryEffects() |
1068 Attr1.getMemoryEffects());
1069 break;
1070 case Attribute::Captures:
1071 Intersected.addCapturesAttr(Attr0.getCaptureInfo() |
1072 Attr1.getCaptureInfo());
1073 break;
1074 case Attribute::NoFPClass:
1075 Intersected.addNoFPClassAttr(Attr0.getNoFPClass() &
1076 Attr1.getNoFPClass());
1077 break;
1078 case Attribute::Range: {
1079 ConstantRange Range0 = Attr0.getRange();
1080 ConstantRange Range1 = Attr1.getRange();
1081 ConstantRange NewRange = Range0.unionWith(Range1);
1082 if (!NewRange.isFullSet())
1083 Intersected.addRangeAttr(NewRange);
1084 } break;
1085 default:
1086 llvm_unreachable("Unknown attribute with custom intersection rule");
1087 }
1088 continue;
1089 }
1090
1091 // Attributes with no intersection rule. Only intersect if they are equal.
1092 // Otherwise fail.
1093 if (!IntersectEq())
1094 return std::nullopt;
1095
1096 // Special handling of `byval`. `byval` essentially turns align attr into
1097 // must-preserve
1098 if (Kind == Attribute::ByVal &&
1099 getAttribute(Attribute::Alignment) !=
1100 Other.getAttribute(Attribute::Alignment))
1101 return std::nullopt;
1102 }
1103
1104 return get(C, Intersected);
1105}
1106
1108 return SetNode ? SetNode->getNumAttributes() : 0;
1109}
1110
1112 return SetNode ? SetNode->hasAttribute(Kind) : false;
1113}
1114
1116 return SetNode ? SetNode->hasAttribute(Kind) : false;
1117}
1118
1120 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1121}
1122
1124 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
1125}
1126
1128 return SetNode ? SetNode->getAlignment() : std::nullopt;
1129}
1130
1132 return SetNode ? SetNode->getStackAlignment() : std::nullopt;
1133}
1134
1136 return SetNode ? SetNode->getDereferenceableBytes() : 0;
1137}
1138
1140 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
1141}
1142
1144 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
1145}
1146
1148 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
1149}
1150
1152 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
1153}
1154
1156 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
1157}
1158
1160 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
1161}
1162
1164 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
1165}
1166
1167std::optional<std::pair<unsigned, std::optional<unsigned>>>
1169 if (SetNode)
1170 return SetNode->getAllocSizeArgs();
1171 return std::nullopt;
1172}
1173
1175 return SetNode ? SetNode->getVScaleRangeMin() : 1;
1176}
1177
1178std::optional<unsigned> AttributeSet::getVScaleRangeMax() const {
1179 return SetNode ? SetNode->getVScaleRangeMax() : std::nullopt;
1180}
1181
1183 return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
1184}
1185
1187 return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
1188}
1189
1191 return SetNode ? SetNode->getMemoryEffects() : MemoryEffects::unknown();
1192}
1193
1195 return SetNode ? SetNode->getCaptureInfo() : CaptureInfo::all();
1196}
1197
1199 return SetNode ? SetNode->getNoFPClass() : fcNone;
1200}
1201
1202std::string AttributeSet::getAsString(bool InAttrGrp) const {
1203 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
1204}
1205
1207 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context");
1209 SetNode->Profile(ID);
1210 void *Unused;
1211 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
1212}
1213
1215 return SetNode ? SetNode->begin() : nullptr;
1216}
1217
1219 return SetNode ? SetNode->end() : nullptr;
1220}
1221
1222#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1224 dbgs() << "AS =\n";
1225 dbgs() << " { ";
1226 dbgs() << getAsString(true) << " }\n";
1227}
1228#endif
1229
1230//===----------------------------------------------------------------------===//
1231// AttributeSetNode Definition
1232//===----------------------------------------------------------------------===//
1233
1234AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
1235 : NumAttrs(Attrs.size()) {
1236 // There's memory after the node where we can store the entries in.
1237 llvm::copy(Attrs, getTrailingObjects<Attribute>());
1238
1239 for (const auto &I : *this) {
1240 if (I.isStringAttribute())
1241 StringAttrs.insert({ I.getKindAsString(), I });
1242 else
1243 AvailableAttrs.addAttribute(I.getKindAsEnum());
1244 }
1245}
1246
1248 ArrayRef<Attribute> Attrs) {
1249 SmallVector<Attribute, 8> SortedAttrs(Attrs);
1250 llvm::sort(SortedAttrs);
1251 return getSorted(C, SortedAttrs);
1252}
1253
1254AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
1255 ArrayRef<Attribute> SortedAttrs) {
1256 if (SortedAttrs.empty())
1257 return nullptr;
1258
1259 // Build a key to look up the existing attributes.
1260 LLVMContextImpl *pImpl = C.pImpl;
1262
1263 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!");
1264 for (const auto &Attr : SortedAttrs)
1265 Attr.Profile(ID);
1266
1267 void *InsertPoint;
1268 AttributeSetNode *PA =
1269 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
1270
1271 // If we didn't find any existing attributes of the same shape then create a
1272 // new one and insert it.
1273 if (!PA) {
1274 // Coallocate entries after the AttributeSetNode itself.
1275 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
1276 PA = new (Mem) AttributeSetNode(SortedAttrs);
1277 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
1278 }
1279
1280 // Return the AttributeSetNode that we found or created.
1281 return PA;
1282}
1283
1285 return getSorted(C, B.attrs());
1286}
1287
1289 return StringAttrs.count(Kind);
1290}
1291
1292std::optional<Attribute>
1293AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
1294 // Do a quick presence check.
1295 if (!hasAttribute(Kind))
1296 return std::nullopt;
1297
1298 // Attributes in a set are sorted by enum value, followed by string
1299 // attributes. Binary search the one we want.
1300 const Attribute *I =
1301 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
1302 [](Attribute A, Attribute::AttrKind Kind) {
1303 return A.getKindAsEnum() < Kind;
1304 });
1305 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?");
1306 return *I;
1307}
1308
1310 if (auto A = findEnumAttribute(Kind))
1311 return *A;
1312 return {};
1313}
1314
1316 return StringAttrs.lookup(Kind);
1317}
1318
1320 if (auto A = findEnumAttribute(Attribute::Alignment))
1321 return A->getAlignment();
1322 return std::nullopt;
1323}
1324
1326 if (auto A = findEnumAttribute(Attribute::StackAlignment))
1327 return A->getStackAlignment();
1328 return std::nullopt;
1329}
1330
1332 if (auto A = findEnumAttribute(Kind))
1333 return A->getValueAsType();
1334 return nullptr;
1335}
1336
1338 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
1339 return A->getDereferenceableBytes();
1340 return 0;
1341}
1342
1344 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
1345 return A->getDereferenceableOrNullBytes();
1346 return 0;
1347}
1348
1349std::optional<std::pair<unsigned, std::optional<unsigned>>>
1351 if (auto A = findEnumAttribute(Attribute::AllocSize))
1352 return A->getAllocSizeArgs();
1353 return std::nullopt;
1354}
1355
1357 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1358 return A->getVScaleRangeMin();
1359 return 1;
1360}
1361
1362std::optional<unsigned> AttributeSetNode::getVScaleRangeMax() const {
1363 if (auto A = findEnumAttribute(Attribute::VScaleRange))
1364 return A->getVScaleRangeMax();
1365 return std::nullopt;
1366}
1367
1369 if (auto A = findEnumAttribute(Attribute::UWTable))
1370 return A->getUWTableKind();
1371 return UWTableKind::None;
1372}
1373
1375 if (auto A = findEnumAttribute(Attribute::AllocKind))
1376 return A->getAllocKind();
1377 return AllocFnKind::Unknown;
1378}
1379
1381 if (auto A = findEnumAttribute(Attribute::Memory))
1382 return A->getMemoryEffects();
1383 return MemoryEffects::unknown();
1384}
1385
1387 if (auto A = findEnumAttribute(Attribute::Captures))
1388 return A->getCaptureInfo();
1389 return CaptureInfo::all();
1390}
1391
1393 if (auto A = findEnumAttribute(Attribute::NoFPClass))
1394 return A->getNoFPClass();
1395 return fcNone;
1396}
1397
1398std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
1399 std::string Str;
1400 for (iterator I = begin(), E = end(); I != E; ++I) {
1401 if (I != begin())
1402 Str += ' ';
1403 Str += I->getAsString(InAttrGrp);
1404 }
1405 return Str;
1406}
1407
1408//===----------------------------------------------------------------------===//
1409// AttributeListImpl Definition
1410//===----------------------------------------------------------------------===//
1411
1412/// Map from AttributeList index to the internal array index. Adding one happens
1413/// to work, because -1 wraps around to 0.
1414static unsigned attrIdxToArrayIdx(unsigned Index) {
1415 return Index + 1;
1416}
1417
1419 : NumAttrSets(Sets.size()) {
1420 assert(!Sets.empty() && "pointless AttributeListImpl");
1421
1422 // There's memory after the node where we can store the entries in.
1423 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
1424
1425 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
1426 // summary bitsets.
1427 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
1428 if (!I.isStringAttribute())
1429 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
1430
1431 for (const auto &Set : Sets)
1432 for (const auto &I : Set)
1433 if (!I.isStringAttribute())
1434 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
1435}
1436
1438 Profile(ID, ArrayRef(begin(), end()));
1439}
1440
1443 for (const auto &Set : Sets)
1444 ID.AddPointer(Set.SetNode);
1445}
1446
1448 unsigned *Index) const {
1449 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
1450 return false;
1451
1452 if (Index) {
1453 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
1454 if (begin()[I].hasAttribute(Kind)) {
1455 *Index = I - 1;
1456 break;
1457 }
1458 }
1459 }
1460
1461 return true;
1462}
1463
1464
1465#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1467 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1468}
1469#endif
1470
1471//===----------------------------------------------------------------------===//
1472// AttributeList Construction and Mutation Methods
1473//===----------------------------------------------------------------------===//
1474
1475AttributeList AttributeList::getImpl(LLVMContext &C,
1476 ArrayRef<AttributeSet> AttrSets) {
1477 assert(!AttrSets.empty() && "pointless AttributeListImpl");
1478
1479 LLVMContextImpl *pImpl = C.pImpl;
1481 AttributeListImpl::Profile(ID, AttrSets);
1482
1483 void *InsertPoint;
1484 AttributeListImpl *PA =
1485 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1486
1487 // If we didn't find any existing attributes of the same shape then
1488 // create a new one and insert it.
1489 if (!PA) {
1490 // Coallocate entries after the AttributeListImpl itself.
1491 void *Mem = pImpl->Alloc.Allocate(
1492 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1493 alignof(AttributeListImpl));
1494 PA = new (Mem) AttributeListImpl(AttrSets);
1495 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1496 }
1497
1498 // Return the AttributesList that we found or created.
1499 return AttributeList(PA);
1500}
1501
1504 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1505 // If there are no attributes then return a null AttributesList pointer.
1506 if (Attrs.empty())
1507 return {};
1508
1510 "Misordered Attributes list!");
1511 assert(llvm::all_of(Attrs,
1512 [](const std::pair<unsigned, Attribute> &Pair) {
1513 return Pair.second.isValid();
1514 }) &&
1515 "Pointless attribute!");
1516
1517 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1518 // list.
1520 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1521 E = Attrs.end(); I != E; ) {
1522 unsigned Index = I->first;
1524 while (I != E && I->first == Index) {
1525 AttrVec.push_back(I->second);
1526 ++I;
1527 }
1528
1529 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1530 }
1531
1532 return get(C, AttrPairVec);
1533}
1534
1537 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1538 // If there are no attributes then return a null AttributesList pointer.
1539 if (Attrs.empty())
1540 return {};
1541
1543 "Misordered Attributes list!");
1544 assert(llvm::none_of(Attrs,
1545 [](const std::pair<unsigned, AttributeSet> &Pair) {
1546 return !Pair.second.hasAttributes();
1547 }) &&
1548 "Pointless attribute!");
1549
1550 unsigned MaxIndex = Attrs.back().first;
1551 // If the MaxIndex is FunctionIndex and there are other indices in front
1552 // of it, we need to use the largest of those to get the right size.
1553 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1554 MaxIndex = Attrs[Attrs.size() - 2].first;
1555
1556 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1557 for (const auto &Pair : Attrs)
1558 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1559
1560 return getImpl(C, AttrVec);
1561}
1562
1564 AttributeSet RetAttrs,
1565 ArrayRef<AttributeSet> ArgAttrs) {
1566 // Scan from the end to find the last argument with attributes. Most
1567 // arguments don't have attributes, so it's nice if we can have fewer unique
1568 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1569 unsigned NumSets = 0;
1570 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1571 if (ArgAttrs[I - 1].hasAttributes()) {
1572 NumSets = I + 2;
1573 break;
1574 }
1575 }
1576 if (NumSets == 0) {
1577 // Check function and return attributes if we didn't have argument
1578 // attributes.
1579 if (RetAttrs.hasAttributes())
1580 NumSets = 2;
1581 else if (FnAttrs.hasAttributes())
1582 NumSets = 1;
1583 }
1584
1585 // If all attribute sets were empty, we can use the empty attribute list.
1586 if (NumSets == 0)
1587 return {};
1588
1590 AttrSets.reserve(NumSets);
1591 // If we have any attributes, we always have function attributes.
1592 AttrSets.push_back(FnAttrs);
1593 if (NumSets > 1)
1594 AttrSets.push_back(RetAttrs);
1595 if (NumSets > 2) {
1596 // Drop the empty argument attribute sets at the end.
1597 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1598 llvm::append_range(AttrSets, ArgAttrs);
1599 }
1600
1601 return getImpl(C, AttrSets);
1602}
1603
1605 AttributeSet Attrs) {
1606 if (!Attrs.hasAttributes())
1607 return {};
1608 Index = attrIdxToArrayIdx(Index);
1609 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1610 AttrSets[Index] = Attrs;
1611 return getImpl(C, AttrSets);
1612}
1613
1615 const AttrBuilder &B) {
1616 return get(C, Index, AttributeSet::get(C, B));
1617}
1618
1622 for (const auto K : Kinds)
1623 Attrs.emplace_back(Index, Attribute::get(C, K));
1624 return get(C, Attrs);
1625}
1626
1629 ArrayRef<uint64_t> Values) {
1630 assert(Kinds.size() == Values.size() && "Mismatched attribute values.");
1632 auto VI = Values.begin();
1633 for (const auto K : Kinds)
1634 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1635 return get(C, Attrs);
1636}
1637
1639 ArrayRef<StringRef> Kinds) {
1641 for (const auto &K : Kinds)
1642 Attrs.emplace_back(Index, Attribute::get(C, K));
1643 return get(C, Attrs);
1644}
1645
1648 if (Attrs.empty())
1649 return {};
1650 if (Attrs.size() == 1)
1651 return Attrs[0];
1652
1653 unsigned MaxSize = 0;
1654 for (const auto &List : Attrs)
1655 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1656
1657 // If every list was empty, there is no point in merging the lists.
1658 if (MaxSize == 0)
1659 return {};
1660
1661 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1662 for (unsigned I = 0; I < MaxSize; ++I) {
1663 AttrBuilder CurBuilder(C);
1664 for (const auto &List : Attrs)
1665 CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
1666 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1667 }
1668
1669 return getImpl(C, NewAttrSets);
1670}
1671
1674 Attribute::AttrKind Kind) const {
1675 AttributeSet Attrs = getAttributes(Index);
1676 if (Attrs.hasAttribute(Kind))
1677 return *this;
1678 // TODO: Insert at correct position and avoid sort.
1679 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1680 NewAttrs.push_back(Attribute::get(C, Kind));
1681 return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs));
1682}
1683
1685 StringRef Kind,
1686 StringRef Value) const {
1687 AttrBuilder B(C);
1688 B.addAttribute(Kind, Value);
1689 return addAttributesAtIndex(C, Index, B);
1690}
1691
1693 Attribute A) const {
1694 AttrBuilder B(C);
1695 B.addAttribute(A);
1696 return addAttributesAtIndex(C, Index, B);
1697}
1698
1699AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C,
1700 unsigned Index,
1701 AttributeSet Attrs) const {
1702 Index = attrIdxToArrayIdx(Index);
1703 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1704 if (Index >= AttrSets.size())
1705 AttrSets.resize(Index + 1);
1706 AttrSets[Index] = Attrs;
1707
1708 // Remove trailing empty attribute sets.
1709 while (!AttrSets.empty() && !AttrSets.back().hasAttributes())
1710 AttrSets.pop_back();
1711 if (AttrSets.empty())
1712 return {};
1713 return AttributeList::getImpl(C, AttrSets);
1714}
1715
1717 unsigned Index,
1718 const AttrBuilder &B) const {
1719 if (!B.hasAttributes())
1720 return *this;
1721
1722 if (!pImpl)
1723 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1724
1725 AttrBuilder Merged(C, getAttributes(Index));
1726 Merged.merge(B);
1727 return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
1728}
1729
1731 ArrayRef<unsigned> ArgNos,
1732 Attribute A) const {
1733 assert(llvm::is_sorted(ArgNos));
1734
1735 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1736 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1737 if (MaxIndex >= AttrSets.size())
1738 AttrSets.resize(MaxIndex + 1);
1739
1740 for (unsigned ArgNo : ArgNos) {
1741 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1742 AttrBuilder B(C, AttrSets[Index]);
1743 B.addAttribute(A);
1744 AttrSets[Index] = AttributeSet::get(C, B);
1745 }
1746
1747 return getImpl(C, AttrSets);
1748}
1749
1752 Attribute::AttrKind Kind) const {
1753 AttributeSet Attrs = getAttributes(Index);
1754 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1755 if (Attrs == NewAttrs)
1756 return *this;
1757 return setAttributesAtIndex(C, Index, NewAttrs);
1758}
1759
1761 unsigned Index,
1762 StringRef Kind) const {
1763 AttributeSet Attrs = getAttributes(Index);
1764 AttributeSet NewAttrs = Attrs.removeAttribute(C, Kind);
1765 if (Attrs == NewAttrs)
1766 return *this;
1767 return setAttributesAtIndex(C, Index, NewAttrs);
1768}
1769
1771 LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
1772 AttributeSet Attrs = getAttributes(Index);
1773 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1774 // If nothing was removed, return the original list.
1775 if (Attrs == NewAttrs)
1776 return *this;
1777 return setAttributesAtIndex(C, Index, NewAttrs);
1778}
1779
1782 unsigned WithoutIndex) const {
1783 if (!pImpl)
1784 return {};
1785 if (attrIdxToArrayIdx(WithoutIndex) >= getNumAttrSets())
1786 return *this;
1787 return setAttributesAtIndex(C, WithoutIndex, AttributeSet());
1788}
1789
1791 uint64_t Bytes) const {
1792 AttrBuilder B(C);
1793 B.addDereferenceableAttr(Bytes);
1794 return addRetAttributes(C, B);
1795}
1796
1798 unsigned Index,
1799 uint64_t Bytes) const {
1800 AttrBuilder B(C);
1801 B.addDereferenceableAttr(Bytes);
1802 return addParamAttributes(C, Index, B);
1803}
1804
1807 uint64_t Bytes) const {
1808 AttrBuilder B(C);
1809 B.addDereferenceableOrNullAttr(Bytes);
1810 return addParamAttributes(C, Index, B);
1811}
1812
1814 const ConstantRange &CR) const {
1815 AttrBuilder B(C);
1816 B.addRangeAttr(CR);
1817 return addRetAttributes(C, B);
1818}
1819
1821 LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
1822 const std::optional<unsigned> &NumElemsArg) const {
1823 AttrBuilder B(C);
1824 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1825 return addParamAttributes(C, Index, B);
1826}
1827
1828std::optional<AttributeList>
1830 // Trivial case, the two lists are equal.
1831 if (*this == Other)
1832 return *this;
1833
1835 auto IndexIt =
1836 index_iterator(std::max(getNumAttrSets(), Other.getNumAttrSets()));
1837 for (unsigned Idx : IndexIt) {
1838 auto IntersectedAS =
1839 getAttributes(Idx).intersectWith(C, Other.getAttributes(Idx));
1840 // If any index fails to intersect, fail.
1841 if (!IntersectedAS)
1842 return std::nullopt;
1843 if (!IntersectedAS->hasAttributes())
1844 continue;
1845 IntersectedAttrs.push_back(std::make_pair(Idx, *IntersectedAS));
1846 }
1847
1848 llvm::sort(IntersectedAttrs, llvm::less_first());
1849 return AttributeList::get(C, IntersectedAttrs);
1850}
1851
1852//===----------------------------------------------------------------------===//
1853// AttributeList Accessor Methods
1854//===----------------------------------------------------------------------===//
1855
1857 return getAttributes(ArgNo + FirstArgIndex);
1858}
1859
1861 return getAttributes(ReturnIndex);
1862}
1863
1866}
1867
1869 Attribute::AttrKind Kind) const {
1870 return getAttributes(Index).hasAttribute(Kind);
1871}
1872
1873bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const {
1874 return getAttributes(Index).hasAttribute(Kind);
1875}
1876
1877bool AttributeList::hasAttributesAtIndex(unsigned Index) const {
1878 return getAttributes(Index).hasAttributes();
1879}
1880
1882 return pImpl && pImpl->hasFnAttribute(Kind);
1883}
1884
1887}
1888
1890 unsigned *Index) const {
1891 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1892}
1893
1895 Attribute::AttrKind Kind) const {
1896 return getAttributes(Index).getAttribute(Kind);
1897}
1898
1900 StringRef Kind) const {
1901 return getAttributes(Index).getAttribute(Kind);
1902}
1903
1906}
1907
1909 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1910}
1911
1914}
1915
1918}
1919
1922}
1923
1925 return getAttributes(Index + FirstArgIndex).getByRefType();
1926}
1927
1930}
1931
1934}
1935
1937 return getAttributes(Index + FirstArgIndex).getElementType();
1938}
1939
1941 return getFnAttrs().getStackAlignment();
1942}
1943
1945 return getRetAttrs().getStackAlignment();
1946}
1947
1950}
1951
1953 return getParamAttrs(Index).getDereferenceableBytes();
1954}
1955
1958}
1959
1963}
1964
1965std::optional<ConstantRange>
1966AttributeList::getParamRange(unsigned ArgNo) const {
1967 auto RangeAttr = getParamAttrs(ArgNo).getAttribute(Attribute::Range);
1968 if (RangeAttr.isValid())
1969 return RangeAttr.getRange();
1970 return std::nullopt;
1971}
1972
1974 return getRetAttrs().getNoFPClass();
1975}
1976
1978 return getParamAttrs(Index).getNoFPClass();
1979}
1980
1982 return getFnAttrs().getUWTableKind();
1983}
1984
1986 return getFnAttrs().getAllocKind();
1987}
1988
1990 return getFnAttrs().getMemoryEffects();
1991}
1992
1993std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1994 return getAttributes(Index).getAsString(InAttrGrp);
1995}
1996
1998 Index = attrIdxToArrayIdx(Index);
1999 if (!pImpl || Index >= getNumAttrSets())
2000 return {};
2001 return pImpl->begin()[Index];
2002}
2003
2005 assert(!isEmpty() && "an empty attribute list has no parent context");
2007 pImpl->Profile(ID);
2008 void *Unused;
2009 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
2010}
2011
2013 return pImpl ? pImpl->begin() : nullptr;
2014}
2015
2017 return pImpl ? pImpl->end() : nullptr;
2018}
2019
2020//===----------------------------------------------------------------------===//
2021// AttributeList Introspection Methods
2022//===----------------------------------------------------------------------===//
2023
2025 return pImpl ? pImpl->NumAttrSets : 0;
2026}
2027
2029 O << "AttributeList[\n";
2030
2031 for (unsigned i : indexes()) {
2032 if (!getAttributes(i).hasAttributes())
2033 continue;
2034 O << " { ";
2035 switch (i) {
2037 O << "return";
2038 break;
2040 O << "function";
2041 break;
2042 default:
2043 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
2044 }
2045 O << " => " << getAsString(i) << " }\n";
2046 }
2047
2048 O << "]\n";
2049}
2050
2051#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2053#endif
2054
2055//===----------------------------------------------------------------------===//
2056// AttrBuilder Method Implementations
2057//===----------------------------------------------------------------------===//
2058
2060 append_range(Attrs, AS);
2061 assert(is_sorted(Attrs) && "AttributeSet should be sorted");
2062}
2063
2064void AttrBuilder::clear() { Attrs.clear(); }
2065
2066/// Attribute comparator that only compares attribute keys. Enum attributes are
2067/// sorted before string attributes.
2069 bool operator()(Attribute A0, Attribute A1) const {
2070 bool A0IsString = A0.isStringAttribute();
2071 bool A1IsString = A1.isStringAttribute();
2072 if (A0IsString) {
2073 if (A1IsString)
2074 return A0.getKindAsString() < A1.getKindAsString();
2075 else
2076 return false;
2077 }
2078 if (A1IsString)
2079 return true;
2080 return A0.getKindAsEnum() < A1.getKindAsEnum();
2081 }
2083 if (A0.isStringAttribute())
2084 return false;
2085 return A0.getKindAsEnum() < Kind;
2086 }
2087 bool operator()(Attribute A0, StringRef Kind) const {
2088 if (A0.isStringAttribute())
2089 return A0.getKindAsString() < Kind;
2090 return true;
2091 }
2092};
2093
2094template <typename K>
2096 Attribute Attr) {
2097 auto It = lower_bound(Attrs, Kind, AttributeComparator());
2098 if (It != Attrs.end() && It->hasAttribute(Kind))
2099 std::swap(*It, Attr);
2100 else
2101 Attrs.insert(It, Attr);
2102}
2103
2105 if (Attr.isStringAttribute())
2106 addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
2107 else
2108 addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
2109 return *this;
2110}
2111
2113 addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
2114 return *this;
2115}
2116
2118 addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
2119 return *this;
2120}
2121
2123 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
2124 auto It = lower_bound(Attrs, Val, AttributeComparator());
2125 if (It != Attrs.end() && It->hasAttribute(Val))
2126 Attrs.erase(It);
2127 return *this;
2128}
2129
2131 auto It = lower_bound(Attrs, A, AttributeComparator());
2132 if (It != Attrs.end() && It->hasAttribute(A))
2133 Attrs.erase(It);
2134 return *this;
2135}
2136
2137std::optional<uint64_t>
2139 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
2140 Attribute A = getAttribute(Kind);
2141 if (A.isValid())
2142 return A.getValueAsInt();
2143 return std::nullopt;
2144}
2145
2147 uint64_t Value) {
2148 return addAttribute(Attribute::get(Ctx, Kind, Value));
2149}
2150
2151std::optional<std::pair<unsigned, std::optional<unsigned>>>
2153 Attribute A = getAttribute(Attribute::AllocSize);
2154 if (A.isValid())
2155 return A.getAllocSizeArgs();
2156 return std::nullopt;
2157}
2158
2160 if (!Align)
2161 return *this;
2162
2163 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.");
2164 return addRawIntAttr(Attribute::Alignment, Align->value());
2165}
2166
2168 // Default alignment, allow the target to define how to align it.
2169 if (!Align)
2170 return *this;
2171
2172 assert(*Align <= 0x100 && "Alignment too large.");
2173 return addRawIntAttr(Attribute::StackAlignment, Align->value());
2174}
2175
2177 if (Bytes == 0) return *this;
2178
2179 return addRawIntAttr(Attribute::Dereferenceable, Bytes);
2180}
2181
2183 if (Bytes == 0)
2184 return *this;
2185
2186 return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes);
2187}
2188
2191 const std::optional<unsigned> &NumElems) {
2192 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
2193}
2194
2196 // (0, 0) is our "not present" value, so we need to check for it here.
2197 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)");
2198 return addRawIntAttr(Attribute::AllocSize, RawArgs);
2199}
2200
2202 std::optional<unsigned> MaxValue) {
2203 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
2204}
2205
2207 // (0, 0) is not present hence ignore this case
2208 if (RawArgs == 0)
2209 return *this;
2210
2211 return addRawIntAttr(Attribute::VScaleRange, RawArgs);
2212}
2213
2215 if (Kind == UWTableKind::None)
2216 return *this;
2217 return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
2218}
2219
2221 return addRawIntAttr(Attribute::Memory, ME.toIntValue());
2222}
2223
2225 return addRawIntAttr(Attribute::Captures, CI.toIntValue());
2226}
2227
2229 if (Mask == fcNone)
2230 return *this;
2231
2232 return addRawIntAttr(Attribute::NoFPClass, Mask);
2233}
2234
2236 return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
2237}
2238
2240 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
2241 Attribute A = getAttribute(Kind);
2242 return A.isValid() ? A.getValueAsType() : nullptr;
2243}
2244
2246 return addAttribute(Attribute::get(Ctx, Kind, Ty));
2247}
2248
2250 return addTypeAttr(Attribute::ByVal, Ty);
2251}
2252
2254 return addTypeAttr(Attribute::StructRet, Ty);
2255}
2256
2258 return addTypeAttr(Attribute::ByRef, Ty);
2259}
2260
2262 return addTypeAttr(Attribute::Preallocated, Ty);
2263}
2264
2266 return addTypeAttr(Attribute::InAlloca, Ty);
2267}
2268
2270 const ConstantRange &CR) {
2271 if (CR.isFullSet())
2272 return *this;
2273
2274 return addAttribute(Attribute::get(Ctx, Kind, CR));
2275}
2276
2278 return addConstantRangeAttr(Attribute::Range, CR);
2279}
2280
2284 return addAttribute(Attribute::get(Ctx, Kind, Val));
2285}
2286
2288 return addConstantRangeListAttr(Attribute::Initializes, CRL.rangesRef());
2289}
2290
2292 // TODO: Could make this O(n) as we're merging two sorted lists.
2293 for (const auto &I : B.attrs())
2294 addAttribute(I);
2295
2296 return *this;
2297}
2298
2300 erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
2301 return *this;
2302}
2303
2305 return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
2306}
2307
2309 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
2310 auto It = lower_bound(Attrs, A, AttributeComparator());
2311 if (It != Attrs.end() && It->hasAttribute(A))
2312 return *It;
2313 return {};
2314}
2315
2317 auto It = lower_bound(Attrs, A, AttributeComparator());
2318 if (It != Attrs.end() && It->hasAttribute(A))
2319 return *It;
2320 return {};
2321}
2322
2323std::optional<ConstantRange> AttrBuilder::getRange() const {
2324 const Attribute RangeAttr = getAttribute(Attribute::Range);
2325 if (RangeAttr.isValid())
2326 return RangeAttr.getRange();
2327 return std::nullopt;
2328}
2329
2331 return getAttribute(A).isValid();
2332}
2333
2335 return getAttribute(A).isValid();
2336}
2337
2339 return Attrs == B.Attrs;
2340}
2341
2342//===----------------------------------------------------------------------===//
2343// AttributeFuncs Function Defintions
2344//===----------------------------------------------------------------------===//
2345
2346/// Returns true if this is a type legal for the 'nofpclass' attribute. This
2347/// follows the same type rules as FPMathOperator.
2350}
2351
2352/// Which attributes cannot be applied to a type.
2354 AttributeSafetyKind ASK) {
2355 AttributeMask Incompatible;
2356
2357 if (!Ty->isIntegerTy()) {
2358 // Attributes that only apply to integers.
2359 if (ASK & ASK_SAFE_TO_DROP)
2360 Incompatible.addAttribute(Attribute::AllocAlign);
2361 if (ASK & ASK_UNSAFE_TO_DROP)
2362 Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt);
2363 }
2364
2365 if (!Ty->isIntOrIntVectorTy()) {
2366 // Attributes that only apply to integers or vector of integers.
2367 if (ASK & ASK_SAFE_TO_DROP)
2368 Incompatible.addAttribute(Attribute::Range);
2369 } else {
2370 Attribute RangeAttr = AS.getAttribute(Attribute::Range);
2371 if (RangeAttr.isValid() &&
2372 RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())
2373 Incompatible.addAttribute(Attribute::Range);
2374 }
2375
2376 if (!Ty->isPointerTy()) {
2377 // Attributes that only apply to pointers.
2378 if (ASK & ASK_SAFE_TO_DROP)
2379 Incompatible.addAttribute(Attribute::NoAlias)
2380 .addAttribute(Attribute::NonNull)
2381 .addAttribute(Attribute::ReadNone)
2382 .addAttribute(Attribute::ReadOnly)
2383 .addAttribute(Attribute::Dereferenceable)
2384 .addAttribute(Attribute::DereferenceableOrNull)
2385 .addAttribute(Attribute::Writable)
2386 .addAttribute(Attribute::DeadOnUnwind)
2387 .addAttribute(Attribute::Initializes)
2388 .addAttribute(Attribute::Captures);
2389 if (ASK & ASK_UNSAFE_TO_DROP)
2390 Incompatible.addAttribute(Attribute::Nest)
2391 .addAttribute(Attribute::SwiftError)
2392 .addAttribute(Attribute::Preallocated)
2393 .addAttribute(Attribute::InAlloca)
2394 .addAttribute(Attribute::ByVal)
2395 .addAttribute(Attribute::StructRet)
2396 .addAttribute(Attribute::ByRef)
2397 .addAttribute(Attribute::ElementType)
2398 .addAttribute(Attribute::AllocatedPointer);
2399 }
2400
2401 // Attributes that only apply to pointers or vectors of pointers.
2402 if (!Ty->isPtrOrPtrVectorTy()) {
2403 if (ASK & ASK_SAFE_TO_DROP)
2404 Incompatible.addAttribute(Attribute::Alignment);
2405 }
2406
2407 if (ASK & ASK_SAFE_TO_DROP) {
2409 Incompatible.addAttribute(Attribute::NoFPClass);
2410 }
2411
2412 // Some attributes can apply to all "values" but there are no `void` values.
2413 if (Ty->isVoidTy()) {
2414 if (ASK & ASK_SAFE_TO_DROP)
2415 Incompatible.addAttribute(Attribute::NoUndef);
2416 }
2417
2418 return Incompatible;
2419}
2420
2422 AttributeMask AM;
2423 AM.addAttribute(Attribute::NoUndef);
2424 AM.addAttribute(Attribute::Dereferenceable);
2425 AM.addAttribute(Attribute::DereferenceableOrNull);
2426 return AM;
2427}
2428
2429/// Callees with dynamic denormal modes are compatible with any caller mode.
2430static bool denormModeCompatible(DenormalMode CallerMode,
2431 DenormalMode CalleeMode) {
2432 if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
2433 return true;
2434
2435 // If they don't exactly match, it's OK if the mismatched component is
2436 // dynamic.
2437 if (CalleeMode.Input == CallerMode.Input &&
2438 CalleeMode.Output == DenormalMode::Dynamic)
2439 return true;
2440
2441 if (CalleeMode.Output == CallerMode.Output &&
2442 CalleeMode.Input == DenormalMode::Dynamic)
2443 return true;
2444 return false;
2445}
2446
2447static bool checkDenormMode(const Function &Caller, const Function &Callee) {
2448 DenormalMode CallerMode = Caller.getDenormalModeRaw();
2449 DenormalMode CalleeMode = Callee.getDenormalModeRaw();
2450
2451 if (denormModeCompatible(CallerMode, CalleeMode)) {
2452 DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
2453 DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
2454 if (CallerModeF32 == DenormalMode::getInvalid())
2455 CallerModeF32 = CallerMode;
2456 if (CalleeModeF32 == DenormalMode::getInvalid())
2457 CalleeModeF32 = CalleeMode;
2458 return denormModeCompatible(CallerModeF32, CalleeModeF32);
2459 }
2460
2461 return false;
2462}
2463
2464static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2465 // Do not inline strictfp function into non-strictfp one. It would require
2466 // conversion of all FP operations in host function to constrained intrinsics.
2467 return !Callee.getAttributes().hasFnAttr(Attribute::StrictFP) ||
2468 Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
2469}
2470
2471template<typename AttrClass>
2472static bool isEqual(const Function &Caller, const Function &Callee) {
2473 return Caller.getFnAttribute(AttrClass::getKind()) ==
2474 Callee.getFnAttribute(AttrClass::getKind());
2475}
2476
2477static bool isEqual(const Function &Caller, const Function &Callee,
2478 const StringRef &AttrName) {
2479 return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2480}
2481
2482/// Compute the logical AND of the attributes of the caller and the
2483/// callee.
2484///
2485/// This function sets the caller's attribute to false if the callee's attribute
2486/// is false.
2487template<typename AttrClass>
2488static void setAND(Function &Caller, const Function &Callee) {
2489 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
2490 !AttrClass::isSet(Callee, AttrClass::getKind()))
2491 AttrClass::set(Caller, AttrClass::getKind(), false);
2492}
2493
2494/// Compute the logical OR of the attributes of the caller and the
2495/// callee.
2496///
2497/// This function sets the caller's attribute to true if the callee's attribute
2498/// is true.
2499template<typename AttrClass>
2500static void setOR(Function &Caller, const Function &Callee) {
2501 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
2502 AttrClass::isSet(Callee, AttrClass::getKind()))
2503 AttrClass::set(Caller, AttrClass::getKind(), true);
2504}
2505
2506/// If the inlined function had a higher stack protection level than the
2507/// calling function, then bump up the caller's stack protection level.
2508static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
2509 // If the calling function has *no* stack protection level (e.g. it was built
2510 // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
2511 // change it as that could change the program's semantics.
2512 if (!Caller.hasStackProtectorFnAttr())
2513 return;
2514
2515 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
2516 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
2517 // clutter to the IR.
2518 AttributeMask OldSSPAttr;
2519 OldSSPAttr.addAttribute(Attribute::StackProtect)
2520 .addAttribute(Attribute::StackProtectStrong)
2521 .addAttribute(Attribute::StackProtectReq);
2522
2523 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
2524 Caller.removeFnAttrs(OldSSPAttr);
2525 Caller.addFnAttr(Attribute::StackProtectReq);
2526 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
2527 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
2528 Caller.removeFnAttrs(OldSSPAttr);
2529 Caller.addFnAttr(Attribute::StackProtectStrong);
2530 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
2531 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
2532 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
2533 Caller.addFnAttr(Attribute::StackProtect);
2534}
2535
2536/// If the inlined function required stack probes, then ensure that
2537/// the calling function has those too.
2538static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
2539 if (!Caller.hasFnAttribute("probe-stack") &&
2540 Callee.hasFnAttribute("probe-stack")) {
2541 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
2542 }
2543}
2544
2545/// If the inlined function defines the size of guard region
2546/// on the stack, then ensure that the calling function defines a guard region
2547/// that is no larger.
2548static void
2550 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
2551 if (CalleeAttr.isValid()) {
2552 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
2553 if (CallerAttr.isValid()) {
2554 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2555 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2556 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2557
2558 if (CallerStackProbeSize > CalleeStackProbeSize) {
2559 Caller.addFnAttr(CalleeAttr);
2560 }
2561 } else {
2562 Caller.addFnAttr(CalleeAttr);
2563 }
2564 }
2565}
2566
2567/// If the inlined function defines a min legal vector width, then ensure
2568/// the calling function has the same or larger min legal vector width. If the
2569/// caller has the attribute, but the callee doesn't, we need to remove the
2570/// attribute from the caller since we can't make any guarantees about the
2571/// caller's requirements.
2572/// This function is called after the inlining decision has been made so we have
2573/// to merge the attribute this way. Heuristics that would use
2574/// min-legal-vector-width to determine inline compatibility would need to be
2575/// handled as part of inline cost analysis.
2576static void
2578 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2579 if (CallerAttr.isValid()) {
2580 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2581 if (CalleeAttr.isValid()) {
2582 uint64_t CallerVectorWidth, CalleeVectorWidth;
2583 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2584 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2585 if (CallerVectorWidth < CalleeVectorWidth)
2586 Caller.addFnAttr(CalleeAttr);
2587 } else {
2588 // If the callee doesn't have the attribute then we don't know anything
2589 // and must drop the attribute from the caller.
2590 Caller.removeFnAttr("min-legal-vector-width");
2591 }
2592 }
2593}
2594
2595/// If the inlined function has null_pointer_is_valid attribute,
2596/// set this attribute in the caller post inlining.
2597static void
2599 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2600 Caller.addFnAttr(Attribute::NullPointerIsValid);
2601 }
2602}
2603
2604struct EnumAttr {
2605 static bool isSet(const Function &Fn,
2606 Attribute::AttrKind Kind) {
2607 return Fn.hasFnAttribute(Kind);
2608 }
2609
2610 static void set(Function &Fn,
2611 Attribute::AttrKind Kind, bool Val) {
2612 if (Val)
2613 Fn.addFnAttr(Kind);
2614 else
2615 Fn.removeFnAttr(Kind);
2616 }
2617};
2618
2620 static bool isSet(const Function &Fn,
2621 StringRef Kind) {
2622 auto A = Fn.getFnAttribute(Kind);
2623 return A.getValueAsString() == "true";
2624 }
2625
2626 static void set(Function &Fn,
2627 StringRef Kind, bool Val) {
2628 Fn.addFnAttr(Kind, Val ? "true" : "false");
2629 }
2630};
2631
2632#define GET_ATTR_NAMES
2633#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2634 struct ENUM_NAME##Attr : EnumAttr { \
2635 static enum Attribute::AttrKind getKind() { \
2636 return llvm::Attribute::ENUM_NAME; \
2637 } \
2638 };
2639#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2640 struct ENUM_NAME##Attr : StrBoolAttr { \
2641 static StringRef getKind() { return #DISPLAY_NAME; } \
2642 };
2643#include "llvm/IR/Attributes.inc"
2644
2645#define GET_ATTR_COMPAT_FUNC
2646#include "llvm/IR/Attributes.inc"
2647
2649 const Function &Callee) {
2650 return hasCompatibleFnAttrs(Caller, Callee);
2651}
2652
2654 const Function &B) {
2655 return hasCompatibleFnAttrs(A, B);
2656}
2657
2659 const Function &Callee) {
2660 mergeFnAttrs(Caller, Callee);
2661}
2662
2664 const Function &ToMerge) {
2665
2666 // We merge functions so that they meet the most general case.
2667 // For example, if the NoNansFPMathAttr is set in one function, but not in
2668 // the other, in the merged function we can say that the NoNansFPMathAttr
2669 // is not set.
2670 // However if we have the SpeculativeLoadHardeningAttr set true in one
2671 // function, but not the other, we make sure that the function retains
2672 // that aspect in the merged function.
2673 mergeFnAttrs(Base, ToMerge);
2674}
2675
2677 uint64_t Width) {
2678 Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
2679 if (Attr.isValid()) {
2680 uint64_t OldWidth;
2681 Attr.getValueAsString().getAsInteger(0, OldWidth);
2682 if (Width > OldWidth)
2683 Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
2684 }
2685}
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:753
@ RetAttr
Definition: Attributes.cpp:756
@ IntersectPreserve
Definition: Attributes.cpp:757
@ IntersectMin
Definition: Attributes.cpp:759
@ IntersectCustom
Definition: Attributes.cpp:760
@ ParamAttr
Definition: Attributes.cpp:755
@ FnAttr
Definition: Attributes.cpp:754
@ IntersectPropertyMask
Definition: Attributes.cpp:761
@ IntersectAnd
Definition: Attributes.cpp:758
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:790
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:767
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:773
static const char * getModRefStr(ModRefInfo MR)
Definition: Attributes.cpp:518
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:1070
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:871
bool isConstantRangeAttribute() const
Definition: AttributeImpl.h:66
bool hasAttribute(Attribute::AttrKind A) const
Definition: Attributes.cpp:818
void Profile(FoldingSetNodeID &ID) const
Definition: AttributeImpl.h:95
Type * getValueAsType() const
Definition: Attributes.cpp:854
Attribute::AttrKind getKindAsEnum() const
Definition: Attributes.cpp:828
bool operator<(const AttributeImpl &AI) const
Used when sorting the attributes.
Definition: Attributes.cpp:906
uint64_t getValueAsInt() const
Definition: Attributes.cpp:834
bool isIntAttribute() const
Definition: AttributeImpl.h:63
bool isTypeAttribute() const
Definition: AttributeImpl.h:65
bool getValueAsBool() const
Definition: Attributes.cpp:839
StringRef getKindAsString() const
Definition: Attributes.cpp:844
StringRef getValueAsString() const
Definition: Attributes.cpp:849
bool isEnumAttribute() const
Definition: AttributeImpl.h:62
ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Definition: Attributes.cpp:865
bool isConstantRangeListAttribute() const
Definition: AttributeImpl.h:69
bool isStringAttribute() const
Definition: AttributeImpl.h:64
const ConstantRange & getValueAsConstantRange() const
Definition: Attributes.cpp:859
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:501
AttributeSet getFnAttrs() const
The function attributes are returned.
index_iterator indexes() const
Use this to iterate over the valid attribute indexes.
Definition: Attributes.h:1014
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:502
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:621
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:1026
AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
friend class AttrBuilder
Definition: Attributes.h:500
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:982
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:650
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:629
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:412
AttributeSet removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Remove the specified attribute from this set.
Definition: Attributes.cpp:950
Type * getInAllocaType() const
Type * getByValType() const
AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
Definition: Attributes.cpp:937
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:978
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:966
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:914
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:922
void dump() const
bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
Definition: Attributes.cpp:352
static Attribute getWithStructRetType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:260
static Attribute::AttrKind getAttrKindFromName(StringRef AttrName)
Definition: Attributes.cpp:309
bool isEnumAttribute() const
Return true if the attribute is an Attribute::AttrKind type.
Definition: Attributes.cpp:344
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:506
static bool intersectWithCustom(AttrKind Kind)
Definition: Attributes.cpp:810
bool isIntAttribute() const
Return true if the attribute is an integer attribute.
Definition: Attributes.cpp:348
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:470
uint64_t getValueAsInt() const
Return the attribute's value as an integer.
Definition: Attributes.cpp:375
unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
Definition: Attributes.cpp:464
AllocFnKind getAllocKind() const
Definition: Attributes.cpp:482
bool isConstantRangeAttribute() const
Return true if the attribute is a ConstantRange attribute.
Definition: Attributes.cpp:360
StringRef getKindAsString() const
Return the attribute's kind as a string.
Definition: Attributes.cpp:389
static Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty)
Definition: Attributes.cpp:268
static bool intersectWithMin(AttrKind Kind)
Definition: Attributes.cpp:807
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:786
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:532
uint64_t getDereferenceableOrNullBytes() const
Returns the number of dereferenceable_or_null bytes from the dereferenceable_or_null attribute.
Definition: Attributes.cpp:450
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:458
static Attribute getWithUWTableKind(LLVMContext &Context, UWTableKind Kind)
Definition: Attributes.cpp:276
FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
Definition: Attributes.cpp:500
static Attribute getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const std::optional< unsigned > &NumElemsArg)
Definition: Attributes.cpp:296
Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
Definition: Attributes.cpp:368
Attribute()=default
bool getValueAsBool() const
Return the attribute's value as a boolean.
Definition: Attributes.cpp:382
ArrayRef< ConstantRange > getInitializes() const
Returns the value of the initializes attribute.
Definition: Attributes.cpp:512
const ConstantRange & getValueAsConstantRange() const
Return the attribute's value as a ConstantRange.
Definition: Attributes.cpp:410
uint64_t getDereferenceableBytes() const
Returns the number of dereferenceable bytes from the dereferenceable attribute.
Definition: Attributes.cpp:443
static Attribute getWithVScaleRangeArgs(LLVMContext &Context, unsigned MinValue, unsigned MaxValue)
Definition: Attributes.cpp:303
MemoryEffects getMemoryEffects() const
Returns memory effects.
Definition: Attributes.cpp:488
void Profile(FoldingSetNodeID &ID) const
Definition: Attributes.cpp:749
UWTableKind getUWTableKind() const
Definition: Attributes.cpp:476
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:416
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:396
static bool isExistingAttribute(StringRef Name)
Return true if the provided string matches the IR name of an attribute.
Definition: Attributes.cpp:332
bool hasKindAsEnum() const
Returns true if the attribute's kind can be represented as an enum (Enum, Integer,...
Definition: Attributes.h:219
static StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind)
Definition: Attributes.cpp:318
static bool canUseAsFnAttr(AttrKind Kind)
Definition: Attributes.cpp:778
static bool intersectWithAnd(AttrKind Kind)
Definition: Attributes.cpp:804
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:724
bool isTypeAttribute() const
Return true if the attribute is a type attribute.
Definition: Attributes.cpp:356
static Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
Definition: Attributes.cpp:291
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:364
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:422
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:782
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition: Attributes.h:209
MaybeAlign getStackAlignment() const
Returns the stack alignment field of an attribute as a byte alignment value.
Definition: Attributes.cpp:437
MaybeAlign getAlignment() const
Returns the alignment field of an attribute as a byte alignment value.
Definition: Attributes.cpp:431
CaptureInfo getCaptureInfo() const
Returns information from captures attribute.
Definition: Attributes.cpp:494
static bool intersectMustPreserve(AttrKind Kind)
Definition: Attributes.cpp:801
int cmpKind(Attribute A) const
Used to sort attribute by kind.
Definition: Attributes.cpp:732
bool operator<(Attribute A) const
Less-than operator. Useful for sorting the attributes list.
Definition: Attributes.cpp:742
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:403
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:380
static CaptureInfo all()
Create CaptureInfo that may capture all components of the pointer.
Definition: ModRef.h:334
uint32_t toIntValue() const
Convert CaptureInfo into an encoded integer value (used by captures attribute).
Definition: ModRef.h:387
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