Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -3081,6 +3081,12 @@ :ref:`aggregate ` types. This is often used to avoid having to print large zero initializers (e.g. for large arrays) and is always exactly equivalent to using explicit zero initializers. +**VScale Constant** + The string '``vscale``' is a positive symbolic constant of type + integer that represents the runtime scaling factor as used in + the definition of :ref:`scalable vectors `, i.e. + '````'. The value is not known at compile + time, but is guaranteed to be constant throughout the program. **Metadata node** A metadata node is a constant tuple without types. For example: "``!{!0, !{!2, !0}, !"test"}``". Metadata can reference constant values, Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -279,6 +279,8 @@ LLVMInlineAsmValueKind, LLVMInstructionValueKind, + + LLVMVScaleValueKind, } LLVMValueKind; typedef enum { @@ -1538,6 +1540,7 @@ macro(Function) \ macro(GlobalVariable) \ macro(UndefValue) \ + macro(VScale) \ macro(Instruction) \ macro(BinaryOperator) \ macro(CallInst) \ Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -364,6 +364,7 @@ // asmdialect,asmstr,conststr] CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands] CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval] + CST_CODE_VSCALE = 26, // 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 @@ -1319,6 +1319,29 @@ } }; +//===----------------------------------------------------------------------===// +/// A constant representing the scaling factor 'vscale' of a scalable vector +/// of the form ''. +/// +class VScale final : public ConstantData { + friend class Constant; + + explicit VScale(Type *T) : ConstantData(T, VScaleVal) {} + + void destroyConstantImpl(); + +public: + VScale(const VScale &) = delete; + + /// 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() == VScaleVal; + } +}; + } // end namespace llvm #endif // LLVM_IR_CONSTANTS_H Index: include/llvm/IR/Value.def =================================================================== --- include/llvm/IR/Value.def +++ include/llvm/IR/Value.def @@ -73,6 +73,7 @@ // ConstantData. HANDLE_CONSTANT(UndefValue) +HANDLE_CONSTANT(VScale) HANDLE_CONSTANT(ConstantAggregateZero) HANDLE_CONSTANT(ConstantDataArray) HANDLE_CONSTANT(ConstantDataVector) 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 @@ -3096,6 +3096,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; @@ -5190,6 +5191,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 = VScale::get(Ty); + return false; case ValID::t_EmptyArray: if (!Ty->isArrayTy() || cast(Ty)->getNumElements() != 0) return Error(ID.Loc, "invalid empty array initializer"); @@ -5246,6 +5252,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/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -2366,6 +2366,9 @@ case bitc::CST_CODE_UNDEF: // UNDEF V = UndefValue::get(CurTy); break; + case bitc::CST_CODE_VSCALE: // VSCALE + V = VScale::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 @@ -2342,6 +2342,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 @@ -1502,6 +1502,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 @@ -926,6 +926,26 @@ } //===----------------------------------------------------------------------===// +// VScale Implementation +//===----------------------------------------------------------------------===// + +Constant *VScale::get(Type *Ty) { + assert(Ty->isIntegerTy() && "VScale must be an integer type!"); + + std::unique_ptr &Entry = Ty->getContext().pImpl->VScaleConstants[Ty]; + if (!Entry) + Entry.reset(new VScale(Ty)); + + return Entry.get(); +} + +/// Remove the constant from the constant table. +void VScale::destroyConstantImpl() { + // Free the constant and any dangling references to it. + getContext().pImpl->VScaleConstants.erase(getType()); +} + +//===----------------------------------------------------------------------===// // ConstantXXX Classes //===----------------------------------------------------------------------===// Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -1299,6 +1299,9 @@ using VectorConstantsTy = ConstantUniqueMap; VectorConstantsTy VectorConstants; + using VScaleConstantsTy = DenseMap>; + VScaleConstantsTy VScaleConstants; + DenseMap> CPNConstants; DenseMap> UVConstants; Index: lib/IR/LLVMContextImpl.cpp =================================================================== --- lib/IR/LLVMContextImpl.cpp +++ lib/IR/LLVMContextImpl.cpp @@ -98,6 +98,7 @@ UVConstants.clear(); IntConstants.clear(); FPConstants.clear(); + VScaleConstants.clear(); for (auto &CDSConstant : CDSConstants) delete CDSConstant.second; Index: test/Bitcode/compatibility.ll =================================================================== --- test/Bitcode/compatibility.ll +++ test/Bitcode/compatibility.ll @@ -40,6 +40,8 @@ @const.float = constant double 0.0 ; CHECK: @const.float = constant double 0.0 @const.null = constant i8* null +; CHECK: @const.vscale = constant i32 vscale +@const.vscale = constant i32 vscale ; CHECK: @const.null = constant i8* null %const.struct.type = type { i32, i8 } %const.struct.type.packed = type <{ i32, i8 }> Index: test/Feature/vscale-diagnostic.ll =================================================================== --- /dev/null +++ test/Feature/vscale-diagnostic.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s 2>&1 | FileCheck %s + +; CHECK: error: vscale must be an integer type +@v = constant float vscale Index: test/Feature/vscale-diagnostic2.ll =================================================================== --- /dev/null +++ test/Feature/vscale-diagnostic2.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s 2>&1 | FileCheck %s + +; CHECK: error: vscale must be an integer type +@v = constant <4 x i32> vscale Index: test/Feature/vscale.ll =================================================================== --- /dev/null +++ test/Feature/vscale.ll @@ -0,0 +1,4 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +; CHECK: constant i32 mul (i32 vscale, i32 42) +@v = constant i32 mul (i32 vscale, i32 42) Index: utils/vim/syntax/llvm.vim =================================================================== --- utils/vim/syntax/llvm.vim +++ utils/vim/syntax/llvm.vim @@ -181,7 +181,7 @@ syn match llvmFloat /-\?\<\d\+\.\d*\(e[+-]\d\+\)\?\>/ syn match llvmFloat /\<0x\x\+\>/ syn keyword llvmBoolean true false -syn keyword llvmConstant zeroinitializer undef null none +syn keyword llvmConstant zeroinitializer undef null none vscale syn match llvmComment /;.*$/ syn region llvmString start=/"/ skip=/\\"/ end=/"/ syn match llvmLabel /[-a-zA-Z$._][-a-zA-Z$._0-9]*:/