Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -2771,6 +2771,12 @@ "``< i32 42, i32 11, i32 74, i32 100 >``". Vector constants must have :ref:`vector type `, and the number and types of elements must match those specified by the type. +**Scalable vector constants (unit step vector)** + Scalable vector constants cannot be represented by a list of elements + because the number of elements required is unknown. To mitigate this + the string '``stepvector``' can be used to represent the constant vector + "``<0, 1, 2, 3, 4...``" wherever an :ref:`integer ` + :ref:`vector ` is expected. **Zero initialization** The string '``zeroinitializer``' can be used to zero initialize a value to zero of *any* type, including scalar and Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -219,6 +219,7 @@ LLVMConstantStructValueKind, LLVMConstantVectorValueKind, + LLVMStepVectorValueValueKind, LLVMUndefValueValueKind, LLVMVScaleValueValueKind, LLVMConstantAggregateZeroValueKind, @@ -1184,6 +1185,7 @@ macro(GlobalObject) \ macro(Function) \ macro(GlobalVariable) \ + macro(StepVectorValue) \ macro(UndefValue) \ macro(VScaleValue) \ macro(Instruction) \ Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -284,6 +284,7 @@ // asmdialect,asmstr,conststr] CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands] CST_CODE_VSCALE = 25, // VSCALE + CST_CODE_STEPVEC = 26, // STEPVEC }; /// 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 @@ -1198,6 +1198,28 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) //===----------------------------------------------------------------------===// +/// A constant vector representing the numeric sequence "0, 1, 2, 3, 4...". +/// +class StepVectorValue final : public ConstantData { + StepVectorValue(const StepVectorValue &) = delete; + + friend class Constant; + void destroyConstantImpl(); + + explicit StepVectorValue(Type *T) : ConstantData(T, StepVectorValueVal) {} + +public: + /// Static factory methods - Return a 'stepvector' object of the specified + /// type or a ConstantVector if the result's vector length is known. + 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() == StepVectorValueVal; + } +}; + +//===----------------------------------------------------------------------===// /// 'undef' values are things that do not have specified contents. /// These are used for a variety of purposes, including global variable /// initializers and operands to instructions. 'undef' values can occur with Index: include/llvm/IR/Value.def =================================================================== --- include/llvm/IR/Value.def +++ include/llvm/IR/Value.def @@ -71,6 +71,7 @@ HANDLE_CONSTANT(ConstantVector) // ConstantData. +HANDLE_CONSTANT(StepVectorValue) HANDLE_CONSTANT(UndefValue) HANDLE_CONSTANT(VScaleValue) HANDLE_CONSTANT(ConstantAggregateZero) Index: lib/AsmParser/LLLexer.cpp =================================================================== --- lib/AsmParser/LLLexer.cpp +++ lib/AsmParser/LLLexer.cpp @@ -520,6 +520,7 @@ KEYWORD(zeroinitializer); KEYWORD(undef); KEYWORD(vscale); + KEYWORD(stepvector); KEYWORD(null); KEYWORD(none); KEYWORD(to); Index: lib/AsmParser/LLParser.h =================================================================== --- lib/AsmParser/LLParser.h +++ lib/AsmParser/LLParser.h @@ -55,7 +55,8 @@ t_InlineAsm, // Value in FTy/StrVal/StrVal2/UIntVal. t_ConstantStruct, // Value in ConstantStructElts. t_PackedConstantStruct, // Value in ConstantStructElts. - t_VScale // No value. + t_VScale, // No value. + t_StepVector // No value. } Kind = t_LocalID; LLLexer::LocTy Loc; Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -2745,6 +2745,7 @@ ID.Kind = ValID::t_Constant; break; case lltok::kw_null: ID.Kind = ValID::t_Null; break; + case lltok::kw_stepvector: ID.Kind = ValID::t_StepVector; 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; @@ -4494,6 +4495,11 @@ return Error(ID.Loc, "null must be a pointer type"); V = ConstantPointerNull::get(cast(Ty)); return false; + case ValID::t_StepVector: + if (!Ty->isVectorTy() || !Ty->getVectorElementType()->isIntegerTy()) + return Error(ID.Loc, "stepvector must be an integer vector type"); + V = StepVectorValue::get(Ty); + return false; case ValID::t_Undef: // FIXME: LabelTy should not be a first-class type. if (!Ty->isFirstClassType() || Ty->isLabelTy()) Index: lib/AsmParser/LLToken.h =================================================================== --- lib/AsmParser/LLToken.h +++ lib/AsmParser/LLToken.h @@ -72,6 +72,7 @@ kw_zeroinitializer, kw_undef, kw_vscale, + kw_stepvector, kw_null, kw_none, kw_to, Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -3265,6 +3265,9 @@ unsigned BitCode = Stream.readRecord(Entry.ID, Record); switch (BitCode) { default: // Default behavior: unknown constant + case bitc::CST_CODE_STEPVEC: // STEPVEC + V = StepVectorValue::get(CurTy); + break; case bitc::CST_CODE_UNDEF: // UNDEF V = UndefValue::get(CurTy); break; Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2112,6 +2112,8 @@ unsigned AbbrevToUse = 0; if (C->isNullValue()) { Code = bitc::CST_CODE_NULL; + } else if (isa(C)) { + Code = bitc::CST_CODE_STEPVEC; } else if (isa(C)) { Code = bitc::CST_CODE_UNDEF; } else if (isa(C)) { Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1310,6 +1310,11 @@ return; } + if (isa(CV)) { + Out << "stepvector"; + return; + } + if (isa(CV)) { Out << "undef"; return; Index: lib/IR/Constants.cpp =================================================================== --- lib/IR/Constants.cpp +++ lib/IR/Constants.cpp @@ -769,6 +769,39 @@ } //===----------------------------------------------------------------------===// +// StepVectorValue Implementation +//===----------------------------------------------------------------------===// + +Constant *StepVectorValue::get(Type *Ty) { + assert(Ty->isVectorTy() && Ty->getVectorElementType()->isIntegerTy() && + "StepVector must be an integer vector type!"); + + if (!Ty->getVectorIsScalable()) { + // Always return a constant vector when the vector length is known. + Type* EltTy = Ty->getVectorElementType(); + + SmallVector Indices; + for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) + Indices.push_back(ConstantInt::get(EltTy, i)); + + return ConstantVector::get(Indices); + } + + std::unique_ptr &Entry = + Ty->getContext().pImpl->SVVConstants[Ty]; + if (!Entry) + Entry.reset(new StepVectorValue(Ty)); + + return Entry.get(); +} + +/// Remove the constant from the constant table. +void StepVectorValue::destroyConstantImpl() { + // Free the constant and any dangling references to it. + getContext().pImpl->SVVConstants.erase(getType()); +} + +//===----------------------------------------------------------------------===// // UndefValue Implementation //===----------------------------------------------------------------------===// Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -1118,6 +1118,7 @@ DenseMap> CPNConstants; + DenseMap> SVVConstants; DenseMap> UVConstants; DenseMap> VSVConstants; Index: lib/IR/LLVMContextImpl.cpp =================================================================== --- lib/IR/LLVMContextImpl.cpp +++ lib/IR/LLVMContextImpl.cpp @@ -98,6 +98,7 @@ CAZConstants.clear(); CPNConstants.clear(); + SVVConstants.clear(); UVConstants.clear(); VSVConstants.clear(); IntConstants.clear(); Index: test/Bitcode/compatibility.ll =================================================================== --- test/Bitcode/compatibility.ll +++ test/Bitcode/compatibility.ll @@ -43,6 +43,8 @@ ; CHECK: @const.null = constant i8* null @const.vscale = constant i32 vscale ; CHECK: @const.vscale = constant i32 vscale +@const.stepvector = constant stepvector +; CHECK: @const.stepvector = constant stepvector %const.struct.type = type { i32, i8 } %const.struct.type.packed = type <{ i32, i8 }> @const.struct = constant %const.struct.type { i32 -1, i8 undef } Index: test/Transforms/ConstProp/constant-expr.ll =================================================================== --- test/Transforms/ConstProp/constant-expr.ll +++ test/Transforms/ConstProp/constant-expr.ll @@ -109,3 +109,6 @@ i32 10, i32 20), i32 30) ; CHECK: select = internal constant i32 select {{.*}} i32 10, i32 30 + +@stepvector = constant <4 x i32> stepvector +; CHECK: @stepvector = constant <4 x i32>