Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -2796,6 +2796,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 "`` x >``", + where "``m``" 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 @@ -232,6 +232,7 @@ LLVMInlineAsmValueKind, LLVMInstructionValueKind, + LLVMVScaleValueValueKind, } LLVMValueKind; typedef enum { @@ -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 @@ -311,6 +311,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 @@ -1292,6 +1292,28 @@ } }; +//===----------------------------------------------------------------------===// +/// A constant representing the scaling factor 'm' 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 namespace llvm #endif // LLVM_IR_CONSTANTS_H Index: include/llvm/IR/Value.def =================================================================== --- include/llvm/IR/Value.def +++ include/llvm/IR/Value.def @@ -79,6 +79,7 @@ HANDLE_CONSTANT(ConstantFP) HANDLE_CONSTANT(ConstantPointerNull) HANDLE_CONSTANT(ConstantTokenNone) +HANDLE_CONSTANT(VScaleValue) HANDLE_METADATA_VALUE(MetadataAsValue) HANDLE_INLINE_ASM_VALUE(InlineAsm) @@ -88,9 +89,9 @@ // don't add new values here! HANDLE_CONSTANT_MARKER(ConstantFirstVal, Function) -HANDLE_CONSTANT_MARKER(ConstantLastVal, ConstantTokenNone) +HANDLE_CONSTANT_MARKER(ConstantLastVal, VScaleValue) HANDLE_CONSTANT_MARKER(ConstantDataFirstVal, UndefValue) -HANDLE_CONSTANT_MARKER(ConstantDataLastVal, ConstantTokenNone) +HANDLE_CONSTANT_MARKER(ConstantDataLastVal, VScaleValue) HANDLE_CONSTANT_MARKER(ConstantAggregateFirstVal, ConstantArray) HANDLE_CONSTANT_MARKER(ConstantAggregateLastVal, ConstantVector) 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 @@ -2758,6 +2758,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; @@ -4601,6 +4602,11 @@ } else return Error(ID.Loc, "constant expression type mismatch"); 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; } llvm_unreachable("Invalid ValID"); } @@ -4617,7 +4623,8 @@ case ValID::t_Undef: case ValID::t_Constant: case ValID::t_ConstantStruct: - case ValID::t_PackedConstantStruct: { + case ValID::t_PackedConstantStruct: + case ValID:: t_VScale: { Value *V; if (ConvertValIDToValue(Ty, ID, V, /*PFS=*/nullptr)) return true; 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 @@ -2073,6 +2073,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 @@ -2221,6 +2221,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 @@ -1311,6 +1311,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 @@ -791,6 +791,27 @@ return Ty->getStructNumElements(); } +//===----------------------------------------------------------------------===// +// 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 //===----------------------------------------------------------------------===// Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -1159,6 +1159,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 }