Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -2784,6 +2784,11 @@ Unlike other typed constants that are meant to be interpreted as part of the instruction stream, metadata is a place to attach additional information such as debug info. +**Scalable vector length** + Scalable vectors take the form "``< n x <# elements> x >``", + where "``n``" is an unknown positive integer constant. The string + '``vscale``' can be used to reference this value wherever an + :ref:`integer ` is expected. Global Variable and Function Addresses -------------------------------------- Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -220,6 +220,7 @@ LLVMConstantVectorValueKind, LLVMUndefValueValueKind, + LLVMVScaleValueValueKind, LLVMConstantAggregateZeroValueKind, LLVMConstantDataArrayValueKind, LLVMConstantDataVectorValueKind, @@ -1184,6 +1185,7 @@ macro(Function) \ macro(GlobalVariable) \ macro(UndefValue) \ + macro(VScaleValue) \ macro(Instruction) \ macro(BinaryOperator) \ macro(CallInst) \ Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -283,6 +283,7 @@ CST_CODE_INLINEASM = 23, // INLINEASM: [sideeffect|alignstack| // asmdialect,asmstr,conststr] CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands] + CST_CODE_VSCALE = 25, // VSCALE }; /// CastOpcodes - These are values used in the bitcode files to encode which Index: include/llvm/IR/Constants.h =================================================================== --- include/llvm/IR/Constants.h +++ include/llvm/IR/Constants.h @@ -1243,6 +1243,28 @@ } }; +//===----------------------------------------------------------------------===// +/// A constant representing the scaling factor 'n' of a scalable vector of the +/// form ''. +/// +class VScaleValue final : public ConstantData { + VScaleValue(const VScaleValue &) = delete; + + friend class Constant; + void destroyConstantImpl(); + + explicit VScaleValue(Type *T) : ConstantData(T, VScaleValueVal) {} + +public: + /// Static factory methods - Return a 'vscale' object of the specified type. + static Constant *get(Type *T); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == VScaleValueVal; + } +}; + } // End llvm namespace #endif Index: include/llvm/IR/Value.def =================================================================== --- include/llvm/IR/Value.def +++ include/llvm/IR/Value.def @@ -72,6 +72,7 @@ // ConstantData. HANDLE_CONSTANT(UndefValue) +HANDLE_CONSTANT(VScaleValue) HANDLE_CONSTANT(ConstantAggregateZero) HANDLE_CONSTANT(ConstantDataArray) HANDLE_CONSTANT(ConstantDataVector) Index: lib/AsmParser/LLLexer.cpp =================================================================== --- lib/AsmParser/LLLexer.cpp +++ lib/AsmParser/LLLexer.cpp @@ -519,6 +519,7 @@ KEYWORD(localexec); KEYWORD(zeroinitializer); KEYWORD(undef); + KEYWORD(vscale); KEYWORD(null); KEYWORD(none); KEYWORD(to); Index: lib/AsmParser/LLParser.h =================================================================== --- lib/AsmParser/LLParser.h +++ lib/AsmParser/LLParser.h @@ -54,7 +54,8 @@ t_Constant, // Value in ConstantVal. t_InlineAsm, // Value in FTy/StrVal/StrVal2/UIntVal. t_ConstantStruct, // Value in ConstantStructElts. - t_PackedConstantStruct // Value in ConstantStructElts. + t_PackedConstantStruct, // Value in ConstantStructElts. + t_VScale // No value. } Kind = t_LocalID; LLLexer::LocTy Loc; Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -2746,6 +2746,7 @@ break; case lltok::kw_null: ID.Kind = ValID::t_Null; break; case lltok::kw_undef: ID.Kind = ValID::t_Undef; break; + case lltok::kw_vscale: ID.Kind = ValID::t_VScale; break; case lltok::kw_zeroinitializer: ID.Kind = ValID::t_Zero; break; case lltok::kw_none: ID.Kind = ValID::t_None; break; @@ -4499,6 +4500,11 @@ return Error(ID.Loc, "invalid type for undef constant"); V = UndefValue::get(Ty); return false; + case ValID::t_VScale: + if (!Ty->isIntegerTy()) + return Error(ID.Loc, "vscale must be an integer type"); + V = VScaleValue::get(Ty); + return false; case ValID::t_EmptyArray: if (!Ty->isArrayTy() || cast(Ty)->getNumElements() != 0) return Error(ID.Loc, "invalid empty array initializer"); @@ -4555,6 +4561,7 @@ case ValID::t_APSInt: case ValID::t_APFloat: case ValID::t_Undef: + case ValID::t_VScale: case ValID::t_Constant: case ValID::t_ConstantStruct: case ValID::t_PackedConstantStruct: { Index: lib/AsmParser/LLToken.h =================================================================== --- lib/AsmParser/LLToken.h +++ lib/AsmParser/LLToken.h @@ -71,6 +71,7 @@ kw_localexec, kw_zeroinitializer, kw_undef, + kw_vscale, kw_null, kw_none, kw_to, Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -3268,6 +3268,9 @@ case bitc::CST_CODE_UNDEF: // UNDEF V = UndefValue::get(CurTy); break; + case bitc::CST_CODE_VSCALE: // VSCALE + V = VScaleValue::get(CurTy); + break; case bitc::CST_CODE_SETTYPE: // SETTYPE: [typeid] if (Record.empty()) return error("Invalid record"); Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2114,6 +2114,8 @@ Code = bitc::CST_CODE_NULL; } else if (isa(C)) { Code = bitc::CST_CODE_UNDEF; + } else if (isa(C)) { + Code = bitc::CST_CODE_VSCALE; } else if (const ConstantInt *IV = dyn_cast(C)) { if (IV->getBitWidth() <= 64) { uint64_t V = IV->getSExtValue(); Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1315,6 +1315,11 @@ return; } + if (isa(CV)) { + Out << "vscale"; + return; + } + if (const ConstantExpr *CE = dyn_cast(CV)) { Out << CE->getOpcodeName(); WriteOptimizationInfo(Out, CE); Index: lib/IR/Constants.cpp =================================================================== --- lib/IR/Constants.cpp +++ lib/IR/Constants.cpp @@ -772,6 +772,20 @@ // UndefValue Implementation //===----------------------------------------------------------------------===// +UndefValue *UndefValue::get(Type *Ty) { + std::unique_ptr &Entry = Ty->getContext().pImpl->UVConstants[Ty]; + if (!Entry) + Entry.reset(new UndefValue(Ty)); + + return Entry.get(); +} + +/// Remove the constant from the constant table. +void UndefValue::destroyConstantImpl() { + // Free the constant and any dangling references to it. + getContext().pImpl->UVConstants.erase(getType()); +} + UndefValue *UndefValue::getSequentialElement() const { return UndefValue::get(getType()->getSequentialElementType()); } @@ -802,6 +816,27 @@ } //===----------------------------------------------------------------------===// +// VScaleValue Implementation +//===----------------------------------------------------------------------===// + +Constant *VScaleValue::get(Type *Ty) { + assert(Ty->isIntegerTy() && "VScale must be an integer type!"); + + std::unique_ptr &Entry = + Ty->getContext().pImpl->VSVConstants[Ty]; + if (!Entry) + Entry.reset(new VScaleValue(Ty)); + + return Entry.get(); +} + +/// Remove the constant from the constant table. +void VScaleValue::destroyConstantImpl() { + // Free the constant and any dangling references to it. + getContext().pImpl->VSVConstants.erase(getType()); +} + +//===----------------------------------------------------------------------===// // ConstantXXX Classes //===----------------------------------------------------------------------===// @@ -1360,20 +1395,6 @@ getContext().pImpl->CPNConstants.erase(getType()); } -UndefValue *UndefValue::get(Type *Ty) { - std::unique_ptr &Entry = Ty->getContext().pImpl->UVConstants[Ty]; - if (!Entry) - Entry.reset(new UndefValue(Ty)); - - return Entry.get(); -} - -/// Remove the constant from the constant table. -void UndefValue::destroyConstantImpl() { - // Free the constant and any dangling references to it. - getContext().pImpl->UVConstants.erase(getType()); -} - BlockAddress *BlockAddress::get(BasicBlock *BB) { assert(BB->getParent() && "Block must have a parent"); return get(BB->getParent(), BB); Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -1119,6 +1119,7 @@ DenseMap> CPNConstants; DenseMap> UVConstants; + DenseMap> VSVConstants; StringMap CDSConstants; Index: lib/IR/LLVMContextImpl.cpp =================================================================== --- lib/IR/LLVMContextImpl.cpp +++ lib/IR/LLVMContextImpl.cpp @@ -99,6 +99,7 @@ CAZConstants.clear(); CPNConstants.clear(); UVConstants.clear(); + VSVConstants.clear(); IntConstants.clear(); FPConstants.clear(); Index: test/Bitcode/compatibility.ll =================================================================== --- test/Bitcode/compatibility.ll +++ test/Bitcode/compatibility.ll @@ -41,6 +41,8 @@ ; CHECK: @const.float = constant double 0.0 @const.null = constant i8* null ; CHECK: @const.null = constant i8* null +@const.vscale = constant i32 vscale +; CHECK: @const.vscale = constant i32 vscale %const.struct.type = type { i32, i8 } %const.struct.type.packed = type <{ i32, i8 }> @const.struct = constant %const.struct.type { i32 -1, i8 undef }