mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[IR] Add vscale_range IR function attribute
This attribute represents the minimum and maximum values vscale can take. For now this attribute is not hooked up to anything during codegen, this will be added in the future when such codegen is considered stable. Additionally hook up the -msve-vector-bits=<x> clang option to emit this attribute. Differential Revision: https://reviews.llvm.org/D98030
This commit is contained in:
parent
093c73b470
commit
839304c777
@ -1070,6 +1070,7 @@ The integer codes are mapped to well-known attributes as follows.
|
||||
* code 68: ``noundef``
|
||||
* code 69: ``byref``
|
||||
* code 70: ``mustprogress``
|
||||
* code 74: ``vscale_range(<Min>[, <Max>])``
|
||||
|
||||
.. note::
|
||||
The ``allocsize`` attribute has a special encoding for its arguments. Its two
|
||||
@ -1077,6 +1078,12 @@ The integer codes are mapped to well-known attributes as follows.
|
||||
(i.e. ``(EltSizeParam << 32) | NumEltsParam``), with ``NumEltsParam`` taking on
|
||||
the sentinel value -1 if it is not specified.
|
||||
|
||||
.. note::
|
||||
The ``vscale_range`` attribute has a special encoding for its arguments. Its two
|
||||
arguments, which are 32-bit integers, are packed into one 64-bit integer value
|
||||
(i.e. ``(Min << 32) | Max``), with ``Max`` taking on the value of ``Min`` if
|
||||
it is not specified.
|
||||
|
||||
.. _TYPE_BLOCK:
|
||||
|
||||
TYPE_BLOCK Contents
|
||||
|
@ -1992,6 +1992,11 @@ example:
|
||||
function does not satisfy this contract, the behavior is undefined. This
|
||||
attribute does not apply transitively to callees, but does apply to call
|
||||
sites within the function. Note that `willreturn` implies `mustprogress`.
|
||||
``vscale_range(<min>[, <max>])``
|
||||
This attribute indicates the minimum and maximum vscale value for the given
|
||||
function. A value of 0 means unbounded. If the optional max value is omitted
|
||||
then max is set to the value of min. If the attribute is not present, no
|
||||
assumptions are made about the range of vscale.
|
||||
|
||||
Call Site Attributes
|
||||
----------------------
|
||||
|
@ -659,6 +659,7 @@ enum AttributeKindCodes {
|
||||
ATTR_KIND_NO_CALLBACK = 71,
|
||||
ATTR_KIND_HOT = 72,
|
||||
ATTR_KIND_NO_PROFILE = 73,
|
||||
ATTR_KIND_VSCALE_RANGE = 74,
|
||||
};
|
||||
|
||||
enum ComdatSelectionKindCodes {
|
||||
|
@ -108,6 +108,8 @@ public:
|
||||
static Attribute getWithAllocSizeArgs(LLVMContext &Context,
|
||||
unsigned ElemSizeArg,
|
||||
const Optional<unsigned> &NumElemsArg);
|
||||
static Attribute getWithVScaleRangeArgs(LLVMContext &Context,
|
||||
unsigned MinValue, unsigned MaxValue);
|
||||
static Attribute getWithByValType(LLVMContext &Context, Type *Ty);
|
||||
static Attribute getWithStructRetType(LLVMContext &Context, Type *Ty);
|
||||
static Attribute getWithByRefType(LLVMContext &Context, Type *Ty);
|
||||
@ -197,6 +199,10 @@ public:
|
||||
/// if not known).
|
||||
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
|
||||
|
||||
/// Returns the argument numbers for the vscale_range attribute (or pair(0, 0)
|
||||
/// if not known).
|
||||
std::pair<unsigned, unsigned> getVScaleRangeArgs() const;
|
||||
|
||||
/// The Attribute is converted to a string of equivalent mnemonic. This
|
||||
/// is, presumably, for writing out the mnemonics for the assembly writer.
|
||||
std::string getAsString(bool InAttrGrp = false) const;
|
||||
@ -320,6 +326,7 @@ public:
|
||||
Type *getByRefType() const;
|
||||
Type *getPreallocatedType() const;
|
||||
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
|
||||
std::pair<unsigned, unsigned> getVScaleRangeArgs() const;
|
||||
std::string getAsString(bool InAttrGrp = false) const;
|
||||
|
||||
using iterator = const Attribute *;
|
||||
@ -572,6 +579,13 @@ public:
|
||||
return addAllocSizeAttr(C, ArgNo + FirstArgIndex, ElemSizeArg, NumElemsArg);
|
||||
}
|
||||
|
||||
/// Add the vscale_range attribute to the attribute set at the given index.
|
||||
/// Returns a new list because attribute lists are immutable.
|
||||
LLVM_NODISCARD AttributeList addVScaleRangeAttr(LLVMContext &C,
|
||||
unsigned Index,
|
||||
unsigned MinValue,
|
||||
unsigned MaxValue);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// AttributeList Accessors
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -690,6 +704,9 @@ public:
|
||||
std::pair<unsigned, Optional<unsigned>>
|
||||
getAllocSizeArgs(unsigned Index) const;
|
||||
|
||||
/// Get the vscale_range argument numbers (or pair(0, 0) if unknown).
|
||||
std::pair<unsigned, unsigned> getVScaleRangeArgs(unsigned Index) const;
|
||||
|
||||
/// Return the attributes at the index as a string.
|
||||
std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
|
||||
|
||||
@ -763,6 +780,7 @@ class AttrBuilder {
|
||||
uint64_t DerefBytes = 0;
|
||||
uint64_t DerefOrNullBytes = 0;
|
||||
uint64_t AllocSizeArgs = 0;
|
||||
uint64_t VScaleRangeArgs = 0;
|
||||
Type *ByValType = nullptr;
|
||||
Type *StructRetType = nullptr;
|
||||
Type *ByRefType = nullptr;
|
||||
@ -865,6 +883,10 @@ public:
|
||||
/// doesn't exist, pair(0, 0) is returned.
|
||||
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
|
||||
|
||||
/// Retrieve the vscale_range args, if the vscale_range attribute exists. If
|
||||
/// it doesn't exist, pair(0, 0) is returned.
|
||||
std::pair<unsigned, unsigned> getVScaleRangeArgs() const;
|
||||
|
||||
/// This turns an alignment into the form used internally in Attribute.
|
||||
/// This call has no effect if Align is not set.
|
||||
AttrBuilder &addAlignmentAttr(MaybeAlign Align);
|
||||
@ -901,6 +923,9 @@ public:
|
||||
AttrBuilder &addAllocSizeAttr(unsigned ElemSizeArg,
|
||||
const Optional<unsigned> &NumElemsArg);
|
||||
|
||||
/// This turns two ints into the form used internally in Attribute.
|
||||
AttrBuilder &addVScaleRangeAttr(unsigned MinValue, unsigned MaxValue);
|
||||
|
||||
/// This turns a byval type into the form used internally in Attribute.
|
||||
AttrBuilder &addByValAttr(Type *Ty);
|
||||
|
||||
@ -917,6 +942,10 @@ public:
|
||||
/// Attribute.getIntValue().
|
||||
AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr);
|
||||
|
||||
/// Add a vscale_range attribute, using the representation returned by
|
||||
/// Attribute.getIntValue().
|
||||
AttrBuilder &addVScaleRangeAttrFromRawRepr(uint64_t RawVScaleRangeRepr);
|
||||
|
||||
/// Return true if the builder contains no target-independent
|
||||
/// attributes.
|
||||
bool empty() const { return Attrs.none(); }
|
||||
|
@ -247,6 +247,9 @@ def SwiftSelf : EnumAttr<"swiftself">;
|
||||
/// Function must be in a unwind table.
|
||||
def UWTable : EnumAttr<"uwtable">;
|
||||
|
||||
/// Minimum/Maximum vscale value for function.
|
||||
def VScaleRange : IntAttr<"vscale_range">;
|
||||
|
||||
/// Function always comes back to callsite.
|
||||
def WillReturn : EnumAttr<"willreturn">;
|
||||
|
||||
|
@ -697,6 +697,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(swifterror);
|
||||
KEYWORD(swiftself);
|
||||
KEYWORD(uwtable);
|
||||
KEYWORD(vscale_range);
|
||||
KEYWORD(willreturn);
|
||||
KEYWORD(writeonly);
|
||||
KEYWORD(zeroext);
|
||||
|
@ -1341,6 +1341,14 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
|
||||
B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
|
||||
continue;
|
||||
}
|
||||
case lltok::kw_vscale_range: {
|
||||
unsigned MinValue, MaxValue;
|
||||
// inAttrGrp doesn't matter; we only support vscale_range(a[, b])
|
||||
if (parseVScaleRangeArguments(MinValue, MaxValue))
|
||||
return true;
|
||||
B.addVScaleRangeAttr(MinValue, MaxValue);
|
||||
continue;
|
||||
}
|
||||
case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break;
|
||||
case lltok::kw_argmemonly: B.addAttribute(Attribute::ArgMemOnly); break;
|
||||
case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break;
|
||||
@ -1806,6 +1814,7 @@ bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) {
|
||||
case lltok::kw_shadowcallstack:
|
||||
case lltok::kw_strictfp:
|
||||
case lltok::kw_uwtable:
|
||||
case lltok::kw_vscale_range:
|
||||
HaveError |=
|
||||
error(Lex.getLoc(), "invalid use of function-only attribute");
|
||||
break;
|
||||
@ -1915,6 +1924,7 @@ bool LLParser::parseOptionalReturnAttrs(AttrBuilder &B) {
|
||||
case lltok::kw_shadowcallstack:
|
||||
case lltok::kw_strictfp:
|
||||
case lltok::kw_uwtable:
|
||||
case lltok::kw_vscale_range:
|
||||
HaveError |=
|
||||
error(Lex.getLoc(), "invalid use of function-only attribute");
|
||||
break;
|
||||
@ -2355,6 +2365,29 @@ bool LLParser::parseAllocSizeArguments(unsigned &BaseSizeArg,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLParser::parseVScaleRangeArguments(unsigned &MinValue,
|
||||
unsigned &MaxValue) {
|
||||
Lex.Lex();
|
||||
|
||||
auto StartParen = Lex.getLoc();
|
||||
if (!EatIfPresent(lltok::lparen))
|
||||
return error(StartParen, "expected '('");
|
||||
|
||||
if (parseUInt32(MinValue))
|
||||
return true;
|
||||
|
||||
if (EatIfPresent(lltok::comma)) {
|
||||
if (parseUInt32(MaxValue))
|
||||
return true;
|
||||
} else
|
||||
MaxValue = MinValue;
|
||||
|
||||
auto EndParen = Lex.getLoc();
|
||||
if (!EatIfPresent(lltok::rparen))
|
||||
return error(EndParen, "expected ')'");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseScopeAndOrdering
|
||||
/// if isAtomic: ::= SyncScope? AtomicOrdering
|
||||
/// else: ::=
|
||||
|
@ -281,6 +281,7 @@ namespace llvm {
|
||||
bool parseOptionalCommaInAlloca(bool &IsInAlloca);
|
||||
bool parseAllocSizeArguments(unsigned &BaseSizeArg,
|
||||
Optional<unsigned> &HowManyArg);
|
||||
bool parseVScaleRangeArguments(unsigned &MinValue, unsigned &MaxValue);
|
||||
bool parseIndexList(SmallVectorImpl<unsigned> &Indices,
|
||||
bool &AteExtraComma);
|
||||
bool parseIndexList(SmallVectorImpl<unsigned> &Indices) {
|
||||
|
@ -240,6 +240,7 @@ enum Kind {
|
||||
kw_swifterror,
|
||||
kw_swiftself,
|
||||
kw_uwtable,
|
||||
kw_vscale_range,
|
||||
kw_willreturn,
|
||||
kw_writeonly,
|
||||
kw_zeroext,
|
||||
|
@ -1526,6 +1526,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
|
||||
return Attribute::SwiftSelf;
|
||||
case bitc::ATTR_KIND_UW_TABLE:
|
||||
return Attribute::UWTable;
|
||||
case bitc::ATTR_KIND_VSCALE_RANGE:
|
||||
return Attribute::VScaleRange;
|
||||
case bitc::ATTR_KIND_WILLRETURN:
|
||||
return Attribute::WillReturn;
|
||||
case bitc::ATTR_KIND_WRITEONLY:
|
||||
@ -1638,6 +1640,8 @@ Error BitcodeReader::parseAttributeGroupBlock() {
|
||||
B.addDereferenceableOrNullAttr(Record[++i]);
|
||||
else if (Kind == Attribute::AllocSize)
|
||||
B.addAllocSizeAttrFromRawRepr(Record[++i]);
|
||||
else if (Kind == Attribute::VScaleRange)
|
||||
B.addVScaleRangeAttrFromRawRepr(Record[++i]);
|
||||
} else if (Record[i] == 3 || Record[i] == 4) { // String attribute
|
||||
bool HasValue = (Record[i++] == 4);
|
||||
SmallString<64> KindStr;
|
||||
|
@ -738,6 +738,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
|
||||
return bitc::ATTR_KIND_SWIFT_SELF;
|
||||
case Attribute::UWTable:
|
||||
return bitc::ATTR_KIND_UW_TABLE;
|
||||
case Attribute::VScaleRange:
|
||||
return bitc::ATTR_KIND_VSCALE_RANGE;
|
||||
case Attribute::WillReturn:
|
||||
return bitc::ATTR_KIND_WILLRETURN;
|
||||
case Attribute::WriteOnly:
|
||||
|
@ -252,6 +252,7 @@ public:
|
||||
uint64_t getDereferenceableBytes() const;
|
||||
uint64_t getDereferenceableOrNullBytes() const;
|
||||
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
|
||||
std::pair<unsigned, unsigned> getVScaleRangeArgs() const;
|
||||
std::string getAsString(bool InAttrGrp) const;
|
||||
Type *getByValType() const;
|
||||
Type *getStructRetType() const;
|
||||
|
@ -78,6 +78,17 @@ unpackAllocSizeArgs(uint64_t Num) {
|
||||
return std::make_pair(ElemSizeArg, NumElemsArg);
|
||||
}
|
||||
|
||||
static uint64_t packVScaleRangeArgs(unsigned MinValue, unsigned MaxValue) {
|
||||
return uint64_t(MinValue) << 32 | MaxValue;
|
||||
}
|
||||
|
||||
static std::pair<unsigned, unsigned> unpackVScaleRangeArgs(uint64_t Value) {
|
||||
unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
|
||||
unsigned MinValue = Value >> 32;
|
||||
|
||||
return std::make_pair(MinValue, MaxValue);
|
||||
}
|
||||
|
||||
Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
|
||||
uint64_t Val) {
|
||||
LLVMContextImpl *pImpl = Context.pImpl;
|
||||
@ -192,6 +203,12 @@ Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
|
||||
return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
|
||||
}
|
||||
|
||||
Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
|
||||
unsigned MinValue,
|
||||
unsigned MaxValue) {
|
||||
return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
|
||||
}
|
||||
|
||||
Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
|
||||
return StringSwitch<Attribute::AttrKind>(AttrName)
|
||||
#define GET_ATTR_NAMES
|
||||
@ -220,7 +237,8 @@ bool Attribute::doesAttrKindHaveArgument(Attribute::AttrKind AttrKind) {
|
||||
AttrKind == Attribute::StackAlignment ||
|
||||
AttrKind == Attribute::Dereferenceable ||
|
||||
AttrKind == Attribute::AllocSize ||
|
||||
AttrKind == Attribute::DereferenceableOrNull;
|
||||
AttrKind == Attribute::DereferenceableOrNull ||
|
||||
AttrKind == Attribute::VScaleRange;
|
||||
}
|
||||
|
||||
bool Attribute::isExistingAttribute(StringRef Name) {
|
||||
@ -328,6 +346,12 @@ std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
|
||||
return unpackAllocSizeArgs(pImpl->getValueAsInt());
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> Attribute::getVScaleRangeArgs() const {
|
||||
assert(hasAttribute(Attribute::VScaleRange) &&
|
||||
"Trying to get vscale args from non-vscale attribute");
|
||||
return unpackVScaleRangeArgs(pImpl->getValueAsInt());
|
||||
}
|
||||
|
||||
std::string Attribute::getAsString(bool InAttrGrp) const {
|
||||
if (!pImpl) return {};
|
||||
|
||||
@ -536,6 +560,18 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
|
||||
return Result;
|
||||
}
|
||||
|
||||
if (hasAttribute(Attribute::VScaleRange)) {
|
||||
unsigned MinValue, MaxValue;
|
||||
std::tie(MinValue, MaxValue) = getVScaleRangeArgs();
|
||||
|
||||
std::string Result = "vscale_range(";
|
||||
Result += utostr(MinValue);
|
||||
Result += ',';
|
||||
Result += utostr(MaxValue);
|
||||
Result += ')';
|
||||
return Result;
|
||||
}
|
||||
|
||||
// Convert target-dependent attributes to strings of the form:
|
||||
//
|
||||
// "kind"
|
||||
@ -778,6 +814,11 @@ std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
|
||||
: std::pair<unsigned, Optional<unsigned>>(0, 0);
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> AttributeSet::getVScaleRangeArgs() const {
|
||||
return SetNode ? SetNode->getVScaleRangeArgs()
|
||||
: std::pair<unsigned, unsigned>(0, 0);
|
||||
}
|
||||
|
||||
std::string AttributeSet::getAsString(bool InAttrGrp) const {
|
||||
return SetNode ? SetNode->getAsString(InAttrGrp) : "";
|
||||
}
|
||||
@ -895,6 +936,11 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
|
||||
Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second);
|
||||
break;
|
||||
}
|
||||
case Attribute::VScaleRange: {
|
||||
auto A = B.getVScaleRangeArgs();
|
||||
Attr = Attribute::getWithVScaleRangeArgs(C, A.first, A.second);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Attr = Attribute::get(C, Kind);
|
||||
}
|
||||
@ -994,6 +1040,12 @@ AttributeSetNode::getAllocSizeArgs() const {
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> AttributeSetNode::getVScaleRangeArgs() const {
|
||||
if (auto A = findEnumAttribute(Attribute::VScaleRange))
|
||||
return A->getVScaleRangeArgs();
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
|
||||
std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
|
||||
std::string Str;
|
||||
for (iterator I = begin(), E = end(); I != E; ++I) {
|
||||
@ -1427,6 +1479,14 @@ AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index,
|
||||
return addAttributes(C, Index, B);
|
||||
}
|
||||
|
||||
AttributeList AttributeList::addVScaleRangeAttr(LLVMContext &C, unsigned Index,
|
||||
unsigned MinValue,
|
||||
unsigned MaxValue) {
|
||||
AttrBuilder B;
|
||||
B.addVScaleRangeAttr(MinValue, MaxValue);
|
||||
return addAttributes(C, Index, B);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AttributeList Accessor Methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1524,6 +1584,11 @@ AttributeList::getAllocSizeArgs(unsigned Index) const {
|
||||
return getAttributes(Index).getAllocSizeArgs();
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned>
|
||||
AttributeList::getVScaleRangeArgs(unsigned Index) const {
|
||||
return getAttributes(Index).getVScaleRangeArgs();
|
||||
}
|
||||
|
||||
std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
|
||||
return getAttributes(Index).getAsString(InAttrGrp);
|
||||
}
|
||||
@ -1587,6 +1652,7 @@ void AttrBuilder::clear() {
|
||||
StackAlignment.reset();
|
||||
DerefBytes = DerefOrNullBytes = 0;
|
||||
AllocSizeArgs = 0;
|
||||
VScaleRangeArgs = 0;
|
||||
ByValType = nullptr;
|
||||
StructRetType = nullptr;
|
||||
ByRefType = nullptr;
|
||||
@ -1620,6 +1686,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
|
||||
DerefOrNullBytes = Attr.getDereferenceableOrNullBytes();
|
||||
else if (Kind == Attribute::AllocSize)
|
||||
AllocSizeArgs = Attr.getValueAsInt();
|
||||
else if (Kind == Attribute::VScaleRange)
|
||||
VScaleRangeArgs = Attr.getValueAsInt();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1650,6 +1718,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
|
||||
DerefOrNullBytes = 0;
|
||||
else if (Val == Attribute::AllocSize)
|
||||
AllocSizeArgs = 0;
|
||||
else if (Val == Attribute::VScaleRange)
|
||||
VScaleRangeArgs = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -1670,6 +1740,10 @@ std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
|
||||
return unpackAllocSizeArgs(AllocSizeArgs);
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> AttrBuilder::getVScaleRangeArgs() const {
|
||||
return unpackVScaleRangeArgs(VScaleRangeArgs);
|
||||
}
|
||||
|
||||
AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
|
||||
if (!Align)
|
||||
return *this;
|
||||
@ -1726,6 +1800,23 @@ AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
|
||||
unsigned MaxValue) {
|
||||
return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
|
||||
}
|
||||
|
||||
AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
|
||||
// (0, 0) is not present hence ignore this case
|
||||
if (RawArgs == 0)
|
||||
return *this;
|
||||
|
||||
Attrs[Attribute::VScaleRange] = true;
|
||||
// Reuse existing machinery to store this as a single 64-bit integer so we can
|
||||
// save a few bytes over using a pair<unsigned, unsigned>.
|
||||
VScaleRangeArgs = RawArgs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
|
||||
Attrs[Attribute::ByVal] = true;
|
||||
ByValType = Ty;
|
||||
@ -1779,6 +1870,9 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
|
||||
if (!PreallocatedType)
|
||||
PreallocatedType = B.PreallocatedType;
|
||||
|
||||
if (!VScaleRangeArgs)
|
||||
VScaleRangeArgs = B.VScaleRangeArgs;
|
||||
|
||||
Attrs |= B.Attrs;
|
||||
|
||||
for (const auto &I : B.td_attrs())
|
||||
@ -1816,6 +1910,9 @@ AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
|
||||
if (B.PreallocatedType)
|
||||
PreallocatedType = nullptr;
|
||||
|
||||
if (B.VScaleRangeArgs)
|
||||
VScaleRangeArgs = 0;
|
||||
|
||||
Attrs &= ~B.Attrs;
|
||||
|
||||
for (const auto &I : B.td_attrs())
|
||||
@ -1876,7 +1973,8 @@ bool AttrBuilder::operator==(const AttrBuilder &B) const {
|
||||
return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
|
||||
DerefBytes == B.DerefBytes && ByValType == B.ByValType &&
|
||||
StructRetType == B.StructRetType && ByRefType == B.ByRefType &&
|
||||
PreallocatedType == B.PreallocatedType;
|
||||
PreallocatedType == B.PreallocatedType &&
|
||||
VScaleRangeArgs == B.VScaleRangeArgs;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1629,6 +1629,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
|
||||
case Attribute::InlineHint:
|
||||
case Attribute::StackAlignment:
|
||||
case Attribute::UWTable:
|
||||
case Attribute::VScaleRange:
|
||||
case Attribute::NonLazyBind:
|
||||
case Attribute::ReturnsTwice:
|
||||
case Attribute::SanitizeAddress:
|
||||
@ -1987,6 +1988,14 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
|
||||
return;
|
||||
}
|
||||
|
||||
if (Attrs.hasFnAttribute(Attribute::VScaleRange)) {
|
||||
std::pair<unsigned, unsigned> Args =
|
||||
Attrs.getVScaleRangeArgs(AttributeList::FunctionIndex);
|
||||
|
||||
if (Args.first > Args.second && Args.second != 0)
|
||||
CheckFailed("'vscale_range' minimum cannot be greater than maximum", V);
|
||||
}
|
||||
|
||||
if (Attrs.hasFnAttribute("frame-pointer")) {
|
||||
StringRef FP = Attrs.getAttribute(AttributeList::FunctionIndex,
|
||||
"frame-pointer").getValueAsString();
|
||||
|
@ -73,6 +73,7 @@ static Attribute::AttrKind parseAttrKind(StringRef Kind) {
|
||||
.Case("sspstrong", Attribute::StackProtectStrong)
|
||||
.Case("strictfp", Attribute::StrictFP)
|
||||
.Case("uwtable", Attribute::UWTable)
|
||||
.Case("vscale_range", Attribute::VScaleRange)
|
||||
.Default(Attribute::None);
|
||||
}
|
||||
|
||||
|
@ -970,6 +970,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
|
||||
case Attribute::StackProtectStrong:
|
||||
case Attribute::StrictFP:
|
||||
case Attribute::UWTable:
|
||||
case Attribute::VScaleRange:
|
||||
case Attribute::NoCfCheck:
|
||||
case Attribute::MustProgress:
|
||||
case Attribute::NoProfile:
|
||||
|
@ -422,6 +422,31 @@ define void @f71() hot
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: define void @f72() #45
|
||||
define void @f72() vscale_range(8)
|
||||
{
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: define void @f73() #46
|
||||
define void @f73() vscale_range(1,8)
|
||||
{
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: define void @f74() #47
|
||||
define void @f74() vscale_range(1,0)
|
||||
{
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: define void @f75()
|
||||
; CHECK-NOT: define void @f75() #
|
||||
define void @f75() vscale_range(0,0)
|
||||
{
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: attributes #0 = { noreturn }
|
||||
; CHECK: attributes #1 = { nounwind }
|
||||
; CHECK: attributes #2 = { readnone }
|
||||
@ -467,4 +492,7 @@ define void @f71() hot
|
||||
; CHECK: attributes #42 = { nocallback }
|
||||
; CHECK: attributes #43 = { cold }
|
||||
; CHECK: attributes #44 = { hot }
|
||||
; CHECK: attributes #45 = { vscale_range(8,8) }
|
||||
; CHECK: attributes #46 = { vscale_range(1,8) }
|
||||
; CHECK: attributes #47 = { vscale_range(1,0) }
|
||||
; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin }
|
||||
|
4
test/Verifier/vscale_range.ll
Normal file
4
test/Verifier/vscale_range.ll
Normal file
@ -0,0 +1,4 @@
|
||||
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: 'vscale_range' minimum cannot be greater than maximum
|
||||
declare i8* @b(i32*) vscale_range(8, 1)
|
Loading…
Reference in New Issue
Block a user