Tl;Dr
This RFC proposes an experiment to restrict some vector dialect operations (vector.insert and vector.extract) to require non-0D vectors or scalars. This does not propose changes to VectorType.
Motivation
0-D vectors introduce ambiguity in the representation of scalar values:
f32vsvector<f32>vsvector<1xf32>.
While vector<1xf32> aligns with the semantics of 1D vectors as containers with at least one element, vector<f32> and f32 both (effectively) represent a scalar element, raising the question:
Which representation should be used whenever creating an Op that accepts both?
Restricting 0-D vectors in certain contexts would help reduce ambiguity and enforce clearer semantics in the Vector dialect.
Proposed Experiment
I propose restricting the use of 0-D vectors in vector.extract and vector.insert. Specifically:
Allow (the non-indexed type is f32 (*)):
%0 = vector.extract %src[0, 0] : f32 from vector<2x2xf32>
%1 = vector.insert %v, %dst[0, 0] : f32 into vector<2x2xf32>
Disallow (the non-indexed type is vector<f32>):
%0 = vector.extract %arg0[0, 0] : vector<f32> from vector<2x2xf32>
%1 = vector.insert %v, %dst[0, 0] : vector<f32> into vector<2x2xf32>
This restriction would simplify semantics and clarify the role of 0-D vectors in the dialect without broader changes to VectorType.
(*) What’s non-indexed type? See the taxonomy proposed by @dcaballe in https://github.com/llvm/llvm-project/pull/115824.
Context
Vector Dialect
The Vector dialect has not fully embraced 0-D vectors:
- AnyVectorOfAnyRank is used 24 times in VectorOps.td, while
- AnyVectorOfNonZeroRank is used 26 times.
Also, vector.mask explicitely avoids 0-D vectors:
At this point, 0-D vectors are not supported by vector.mask.
This suggests that the usage of 0-D vectors is already limited and might remain so without significant impact.
SPIR-V
SPIR-V is an important consumer of the Vector dialect. Note that (from SPIR-V docs):
SPIR-V only supports vectors of 2/3/4 elements;
(see also spirv::CompositeType::isValid). This restriction aligns well with the proposed changes and should not impact SPIR-V usage.
LLVM
Unsurprisngly, lowering to LLVM requires converting 0-D vectors to something else. From LLVMTypeConverter::convertVectorType:
/// * 0-D
vector<T>are converted to vector<1xT>
Let’s look at a specific example:
func.func @shuffle(%arg0: vector<f32>) -> vector<3xf32> {
%1 = vector.shuffle %arg0, %arg0 [0, 1, 0] : vector<f32>, vector<f32>
return %1 : vector<3xf32>
}
Compiling that to AArch64 gives:
shuffle: // @shuffle
dup v0.4s, v0.s[0]
ret
Basically, a 0-D vector was converted to an “element” within a 4-element vector (v0.s[0]). Here’s a Compiler Explorer link for you:
- https://godbolt.org/z/491fe1fsn (and the dup instruction).
Similar example with vector.extract and vector.insert fails to lower to LLVM, see Compiler Explorer. I guess that’s a manifestation of how poorly 0-D vectors are supported.
In any case, from the point of view of the LLVM dialect, we could just replace 0-D vectors with 1-D vectors. Importantly, restricting vector.extract/vector.insert shouldn’t make much difference here.
Why Do We Have 0-D Vectors?
The Vector Dialect docs list 2 benefits of 0-D vectors:
The benefit of 0D vectors, tensors, and memrefs is that they make it easier to lower code from various frontends such as TensorFlow
Given that the main source of Vector Ops is the Linalg vectorizer, which we control, the restriction proposed here is unlikely to be a problem for frameworks like Tensorflow.
and make it easier to handle corner cases such as unrolling a loop from 1D to 0D.
Interestingly, ConvertVectorToSCF is the only transformation that I was able to find that “cares” about 0-D vectors. It’s unclear to me whether restricing vector.extract/vector.insert would be a problem here? Wouldn’t replacing vector<f32> with f32 be equally good?
For more context, here’s the original RFC that introduced 0-D vectors:
Previous discussions
Recent discussions related to 0-D vectors:
- https://github.com/llvm/llvm-project/pull/115824
- [mlir][Vector] Add support for 0-d shapes in extract-shape_cast folder by Groverkss · Pull Request #116650 · llvm/llvm-project · GitHub
- [mlir][Vector] Improve support for 0-d vectors in vector dialect lowerings · Issue #112913 · llvm/llvm-project · GitHub
Additionally, see this related RFC on replacing vector.extractelement and vector.insertelement with vector.extract and vector.insert:
Note: This RFC will be coordinated with the one above to ensure progress on one does not block the other.
Next Steps
- Restrict 0-D vectors in
vector.extractandvector.insertfor scalar extraction. - Observe the impact over several months to determine whether we can further limit 0-D vectors or if they remain essential.
- Use this experiment to clarify and enforce stricter semantics around 0-D vectors in the Vector dialect.
Acknowledgments
Special thanks to @dcaballe and @Groverkss for their efforts to improve these areas ![]()
Thank you,
-Andrzej