[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