== }]
# rank>)>]>;
+// Whether a shaped type has a rank greater than or equal of the specified rank.
+class HasRankGreaterOrEqualPred<int rank> : And<[
+ HasRankPred,
+ CPred<[{$_self.cast<::mlir::ShapedType>().getRank() >= }] # rank>
+]>;
+
// Vector types.
class VectorOf<list<Type> allowedTypes> :
string summary = "ranked tensor">
: TensorOf<allowedTypes, !listconcat([HasRankPred], preds), summary>;
+class Non0RankedTensorOf<list<Type> allowedTypes>
+ : TensorOf<allowedTypes, [HasRankGreaterOrEqualPred<1>],
+ "non-0-ranked.tensor">;
+
def AnyRankedTensor : RankedTensorOf<[AnyType]>;
+def AnyNon0RankedTensor : Non0RankedTensorOf<[AnyType]>;
+def AnyUnrankedTensor : UnrankedTensorOf<[AnyType]>;
+
+def AnyNon0RankedOrUnrankedTensor:
+ AnyTypeOf<[AnyUnrankedTensor, AnyNon0RankedTensor]>;
// Ranked tensor type with one of the specified types and ranks.
class TensorRankOf<list<Type> allowedTypes, list<int> ranks>
class MemRefOf<list<Type> allowedTypes> :
ShapedContainerType<allowedTypes, IsMemRefTypePred, "memref",
"::mlir::MemRefType">;
+class Non0RankedMemRefOf<list<Type> allowedTypes> :
+ ConfinedType<MemRefOf<allowedTypes>, [HasRankGreaterOrEqualPred<1>],
+ "non-0-ranked." # MemRefOf<allowedTypes>.summary,
+ "::mlir::MemRefType">;
def AnyMemRef : MemRefOf<[AnyType]>;
+def AnyNon0RankedMemRef : Non0RankedMemRefOf<[AnyType]>;
class RankedOrUnrankedMemRefOf<list<Type> allowedTypes>:
AnyTypeOf<[UnrankedMemRefOf<allowedTypes>, MemRefOf<allowedTypes>]>;
def AnyRankedOrUnrankedMemRef: AnyTypeOf<[AnyUnrankedMemRef, AnyMemRef]>;
+def AnyNon0RankedOrUnrankedMemRef:
+ AnyTypeOf<[AnyUnrankedMemRef, AnyNon0RankedMemRef]>;
// Memref declarations handle any memref, independent of rank, size, (static or
// dynamic), layout, or memory space.
// RUN: mlir-opt %s -tensor-bufferize -cse -split-input-file -verify-diagnostics | FileCheck %s
// CHECK-LABEL: func @dim(
-// CHECK-SAME: %[[TENSOR:.*]]: tensor<f32>,
+// CHECK-SAME: %[[TENSOR:.*]]: tensor<*xf32>,
// CHECK-SAME: %[[INDEX:.*]]: index) -> index {
-// CHECK: %[[MEMREF:.*]] = bufferization.to_memref %[[TENSOR]] : memref<f32>
-// CHECK: %[[EXTENT:.*]] = memref.dim %[[MEMREF]], %[[INDEX]] : memref<f32>
+// CHECK: %[[MEMREF:.*]] = bufferization.to_memref %[[TENSOR]] : memref<*xf32>
+// CHECK: %[[EXTENT:.*]] = memref.dim %[[MEMREF]], %[[INDEX]] : memref<*xf32>
// CHECK: return %[[EXTENT]] : index
-func.func @dim(%arg0: tensor<f32>, %arg1: index) -> index {
- %0 = tensor.dim %arg0, %arg1 : tensor<f32>
+func.func @dim(%arg0: tensor<*xf32>, %arg1: index) -> index {
+ %0 = tensor.dim %arg0, %arg1 : tensor<*xf32>
return %0 : index
}
// -----
+// Asking the dimension of a 0-D shape doesn't make sense.
+func.func @dim_0_ranked(%arg : tensor<f32>, %arg1 : index) {
+ tensor.dim %arg, %arg1 : tensor<f32> // expected-error {{'tensor.dim' op operand #0 must be unranked.tensor of any type values or non-0-ranked.tensor of any type values, but got 'tensor<f32>'}}
+ return
+}
+
+// -----
+
func.func @tensor.cast_mismatching_constants(%arg0: tensor<1xf32>) {
// expected-error@+1 {{operand type 'tensor<1xf32>' and result type 'tensor<2xf32>' are cast incompatible}}
%0 = tensor.cast %arg0 : tensor<1xf32> to tensor<2xf32>