[llvm] 48f5a39 - [IR] Add vscale_range IR function attribute
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 22 09:46:21 PDT 2021
Correct me if I'm wrong, but in the case vscale_range is a singular
value, all scalable types collapse to non-scalable types right? If so,
I would strongly suggest a follow up patch which canonicalizes in that
manner in InstCombine.
Philip
On 3/22/21 5:05 AM, Bradley Smith via llvm-commits wrote:
> Author: Bradley Smith
> Date: 2021-03-22T12:05:06Z
> New Revision: 48f5a392cb73d99a58f01448926f6964ab5b0d0a
>
> URL: https://github.com/llvm/llvm-project/commit/48f5a392cb73d99a58f01448926f6964ab5b0d0a
> DIFF: https://github.com/llvm/llvm-project/commit/48f5a392cb73d99a58f01448926f6964ab5b0d0a.diff
>
> LOG: [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
>
> Added:
> clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c
> llvm/test/Verifier/vscale_range.ll
>
> Modified:
> clang/lib/CodeGen/CodeGenFunction.cpp
> llvm/docs/BitCodeFormat.rst
> llvm/docs/LangRef.rst
> llvm/include/llvm/Bitcode/LLVMBitCodes.h
> llvm/include/llvm/IR/Attributes.h
> llvm/include/llvm/IR/Attributes.td
> llvm/lib/AsmParser/LLLexer.cpp
> llvm/lib/AsmParser/LLParser.cpp
> llvm/lib/AsmParser/LLParser.h
> llvm/lib/AsmParser/LLToken.h
> llvm/lib/Bitcode/Reader/BitcodeReader.cpp
> llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
> llvm/lib/IR/AttributeImpl.h
> llvm/lib/IR/Attributes.cpp
> llvm/lib/IR/Verifier.cpp
> llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
> llvm/lib/Transforms/Utils/CodeExtractor.cpp
> llvm/test/Bitcode/attributes.ll
>
> Removed:
>
>
>
> ################################################################################
> diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
> index fd708849e609..e3fdf54716ab 100644
> --- a/clang/lib/CodeGen/CodeGenFunction.cpp
> +++ b/clang/lib/CodeGen/CodeGenFunction.cpp
> @@ -496,6 +496,13 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
> if (LargestVectorWidth)
> CurFn->addFnAttr("min-legal-vector-width", llvm::utostr(LargestVectorWidth));
>
> + // Add vscale attribute if appropriate.
> + if (getLangOpts().ArmSveVectorBits) {
> + unsigned VScale = getLangOpts().ArmSveVectorBits / 128;
> + CurFn->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(getLLVMContext(),
> + VScale, VScale));
> + }
> +
> // If we generated an unreachable return block, delete it now.
> if (ReturnBlock.isValid() && ReturnBlock.getBlock()->use_empty()) {
> Builder.ClearInsertionPoint();
>
> diff --git a/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c b/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c
> new file mode 100644
> index 000000000000..84541f9cb12d
> --- /dev/null
> +++ b/clang/test/CodeGen/arm-sve-vector-bits-vscale-range.c
> @@ -0,0 +1,12 @@
> +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=128 -S -emit-llvm -o - %s | FileCheck %s -D#VBITS=128
> +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=256 -S -emit-llvm -o - %s | FileCheck %s -D#VBITS=256
> +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=512 -S -emit-llvm -o - %s | FileCheck %s -D#VBITS=512
> +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=1024 -S -emit-llvm -o - %s | FileCheck %s -D#VBITS=1024
> +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=2048 -S -emit-llvm -o - %s | FileCheck %s -D#VBITS=2048
> +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=scalable -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-NONE
> +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-NONE
> +
> +// CHECK-LABEL: @func() #0
> +// CHECK: attributes #0 = { {{.*}} vscale_range([[#div(VBITS,128)]],[[#div(VBITS,128)]]) {{.*}} }
> +// CHECK-NONE-NOT: vscale_range
> +void func() {}
>
> diff --git a/llvm/docs/BitCodeFormat.rst b/llvm/docs/BitCodeFormat.rst
> index df0e195c6809..eff9d2866a8f 100644
> --- a/llvm/docs/BitCodeFormat.rst
> +++ b/llvm/docs/BitCodeFormat.rst
> @@ -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
>
> diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
> index 142556c55777..74d54440ee0e 100644
> --- a/llvm/docs/LangRef.rst
> +++ b/llvm/docs/LangRef.rst
> @@ -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
> ----------------------
>
> diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
> index 88a629493f04..bc1c5d4479f4 100644
> --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
> +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
> @@ -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 {
>
> diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h
> index 20f5cf1b1917..1e43d903360e 100644
> --- a/llvm/include/llvm/IR/Attributes.h
> +++ b/llvm/include/llvm/IR/Attributes.h
> @@ -108,6 +108,8 @@ class Attribute {
> 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 @@ class Attribute {
> /// 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 @@ class AttributeSet {
> 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 @@ class AttributeList {
> 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 @@ class AttributeList {
> 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 @@ class AttrBuilder {
> /// 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 @@ class AttrBuilder {
> 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 @@ class AttrBuilder {
> /// 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(); }
>
> diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td
> index 5515375d131e..9f62723646e5 100644
> --- a/llvm/include/llvm/IR/Attributes.td
> +++ b/llvm/include/llvm/IR/Attributes.td
> @@ -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">;
>
>
> diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
> index f1e2c0b39664..e9fb0820a839 100644
> --- a/llvm/lib/AsmParser/LLLexer.cpp
> +++ b/llvm/lib/AsmParser/LLLexer.cpp
> @@ -697,6 +697,7 @@ lltok::Kind LLLexer::LexIdentifier() {
> KEYWORD(swifterror);
> KEYWORD(swiftself);
> KEYWORD(uwtable);
> + KEYWORD(vscale_range);
> KEYWORD(willreturn);
> KEYWORD(writeonly);
> KEYWORD(zeroext);
>
> diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
> index 816dda6b8080..0372da19df55 100644
> --- a/llvm/lib/AsmParser/LLParser.cpp
> +++ b/llvm/lib/AsmParser/LLParser.cpp
> @@ -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: ::=
>
> diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h
> index a891e136c59f..1205394ff67f 100644
> --- a/llvm/lib/AsmParser/LLParser.h
> +++ b/llvm/lib/AsmParser/LLParser.h
> @@ -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) {
>
> diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h
> index 0b09dc84eeb6..b4b10c919ec7 100644
> --- a/llvm/lib/AsmParser/LLToken.h
> +++ b/llvm/lib/AsmParser/LLToken.h
> @@ -240,6 +240,7 @@ enum Kind {
> kw_swifterror,
> kw_swiftself,
> kw_uwtable,
> + kw_vscale_range,
> kw_willreturn,
> kw_writeonly,
> kw_zeroext,
>
> diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
> index fd2432981acf..951e32e36dd6 100644
> --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
> +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
> @@ -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;
>
> diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
> index fd4b0a6a6a38..e36ce87554f2 100644
> --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
> +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
> @@ -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:
>
> diff --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h
> index c69fe3fe0827..53c2228658b5 100644
> --- a/llvm/lib/IR/AttributeImpl.h
> +++ b/llvm/lib/IR/AttributeImpl.h
> @@ -252,6 +252,7 @@ class AttributeSetNode final
> 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;
>
> diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
> index 18c2f3aad5f0..4c087c967b01 100644
> --- a/llvm/lib/IR/Attributes.cpp
> +++ b/llvm/lib/IR/Attributes.cpp
> @@ -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;
> }
>
> //===----------------------------------------------------------------------===//
>
> diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
> index 595cc6d04cd7..77acfc447cab 100644
> --- a/llvm/lib/IR/Verifier.cpp
> +++ b/llvm/lib/IR/Verifier.cpp
> @@ -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();
>
> diff --git a/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp b/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
> index 1a8bb225a626..1a4be75dcf2f 100644
> --- a/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
> +++ b/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
> @@ -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);
> }
>
>
> diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
> index 4ad33c14585d..cfd350ff612a 100644
> --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp
> +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
> @@ -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:
>
> diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll
> index 089180ed4725..b8b41e5c4e5c 100644
> --- a/llvm/test/Bitcode/attributes.ll
> +++ b/llvm/test/Bitcode/attributes.ll
> @@ -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 }
>
> diff --git a/llvm/test/Verifier/vscale_range.ll b/llvm/test/Verifier/vscale_range.ll
> new file mode 100644
> index 000000000000..58c1bc012761
> --- /dev/null
> +++ b/llvm/test/Verifier/vscale_range.ll
> @@ -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)
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list