let hasFolder = 1;
}
+def RankOp : Std_Op<"rank", [NoSideEffect]> {
+ let summary = "rank operation";
+ let description = [{
+ The "rank" operation takes a tensor operand and returns its rank.
+
+ %1 = rank %0 : index
+ }];
+
+ let arguments = (ins AnyTensor);
+ let results = (outs Index);
+
+ let builders = [OpBuilder<
+ "Builder *builder, OperationState *result, Value *tensor", [{
+ auto indexType = builder->getIndexType();
+ build(builder, result, indexType, tensor);
+ }]>];
+
+ let hasFolder = 1;
+}
+
def RemFOp : FloatArithmeticOp<"remf"> {
let summary = "floating point division remainder operation";
}
}
//===----------------------------------------------------------------------===//
+// RankOp
+//===----------------------------------------------------------------------===//
+
+static void print(OpAsmPrinter *p, RankOp op) {
+ *p << "rank " << *op.getOperand() << " : " << op.getOperand()->getType();
+}
+
+static ParseResult parseRankOp(OpAsmParser *parser, OperationState *result) {
+ OpAsmParser::OperandType operandInfo;
+ Type type;
+ Type indexType = parser->getBuilder().getIndexType();
+
+ return failure(parser->parseOperand(operandInfo) ||
+ parser->parseColonType(type) ||
+ parser->resolveOperand(operandInfo, type, result->operands) ||
+ parser->addTypeToList(indexType, result->types));
+}
+
+static LogicalResult verify(RankOp op) {
+ auto type = op.getOperand()->getType();
+ if (!type.isa<TensorType>()) {
+ return op.emitOpError("requires an operand that is a tensor");
+ }
+ return success();
+}
+
+OpFoldResult RankOp::fold(ArrayRef<Attribute> operands) {
+ // Constant fold rank when the rank of the tensor is known.
+ auto type = getOperand()->getType();
+ if (auto tensorType = type.dyn_cast<RankedTensorType>()) {
+ int64_t rank = tensorType.getRank();
+ return IntegerAttr::get(IndexType::get(getContext()), rank);
+ }
+ return IntegerAttr();
+}
+
+//===----------------------------------------------------------------------===//
// RemISOp
//===----------------------------------------------------------------------===//
// CHECK: %{{[0-9]+}} = cmpf "oeq", %cst_8, %cst_8 : vector<4xf32>
%70 = cmpf "oeq", %vcf32, %vcf32 : vector<4 x f32>
+ // CHECK: %{{[0-9]+}} = rank %arg0 : tensor<4x4x?xf32>
+ %71 = "std.rank"(%t) : (tensor<4x4x?xf32>) -> index
+
+ // CHECK: %{{[0-9]+}} = rank %arg0 : tensor<4x4x?xf32>
+ %72 = rank %t : tensor<4x4x?xf32>
+
return
}
// -----
+func @rank(f32) {
+^bb(%0: f32):
+ "std.rank"(%0): (f32)->index // expected-error {{'std.rank' op operand #0 must be tensor of any type values}}
+ return
+}
+
+// -----
+
func @constant() {
^bb:
%x = "std.constant"(){value: "xyz"} : () -> i32 // expected-error {{requires a result type that aligns with the 'value' attribute}}
// CHECK-NEXT: return
return %ext_1, %ext_2, %ext_3, %ext_4 : f32, f16, f16, i32
}
+
+
+// CHECK-LABEL: func @fold_rank
+func @fold_rank() -> (index) {
+ %const_0 = constant dense<tensor<2x1x4xi32>, [[[1, -2, 1, 36]], [[0, 2, -1, 64]]]>
+
+ // Fold a rank into a constant
+ // CHECK-NEXT: {{.*}} = constant 3 : index
+ %rank_0 = rank %const_0 : tensor<2x1x4xi32>
+
+ // CHECK-NEXT: return
+ return %rank_0 : index
+}
+