")->getType().cast<ShapedType>().getElementType()",
type.predicate>]>;
+// Predicate to verify that a named argument or result's element type matches a
+// given type.
+class ArgOrResultElementTypeIs<string name, Type type> : And<[
+ SubstLeaves<"$_self", "$" # name # "->getType()", IsShapedTypePred>,
+ SubstLeaves<"$_self", "$" # name #
+ "->getType().cast<ShapedType>().getElementType()",
+ type.predicate>]>;
+
// Predicate to verify that the i'th operand and the j'th operand have the same
// elemental type.
// Type Constraint operand `i`'s Element type is Same As operand `j`'s Element
let results = (outs AnyVectorOrTensor:$res);
}
+def ArgAndResHaveFixedElementTypesOp :
+ TEST_Op<"arg_and_res_have_fixed_element_types",
+ [PredOpTrait<"fixed type combination",
+ Or<[And<[ArgOrResultElementTypeIs<"x", I32>,
+ ArgOrResultElementTypeIs<"y", F32>,
+ ArgOrResultElementTypeIs<"res", I16>]>,
+ ArgOrResultElementTypeIs<"attr", I8>]>>]> {
+ let arguments = (ins AnyVectorOrTensor:$x, AnyVectorOrTensor:$y, AnyAttr:$attr);
+ let results = (outs AnyVectorOrTensor:$res);
+}
+
//===----------------------------------------------------------------------===//
// Test Patterns
//===----------------------------------------------------------------------===//
return
}
+// -----
+
+// CHECK-LABEL: @fixed_element_types
+func @fixed_element_types(%arg0: tensor<* x i32>, %arg1: tensor<* x f32>) {
+ %0 = "test.arg_and_res_have_fixed_element_types"(%arg0, %arg1) {attr: ""} : (tensor<* x i32>, tensor<* x f32>) -> tensor<* x i16>
+ return
+}
+
+// -----
+
+// CHECK-LABEL: @fixed_element_types
+func @fixed_element_types(%arg0: tensor<* x i32>, %arg1: tensor<* x f32>) {
+ %0 = "test.arg_and_res_have_fixed_element_types"(%arg0, %arg1) {attr: splat<tensor<2xi8>, 1>}: (tensor<* x i32>, tensor<* x f32>) -> tensor<* x i32>
+ return
+}
+
+// -----
+
+func @fixed_element_types(%arg0: tensor<* x i32>, %arg1: tensor<* x f32>) {
+ // expected-error@+1 {{fixed type combination}}
+ %0 = "test.arg_and_res_have_fixed_element_types"(%arg0, %arg1) {attr: ""}: (tensor<* x i32>, tensor<* x f32>) -> tensor<* x i32>
+ return
+}
+
+// -----
+
+func @fixed_element_types(%arg0: tensor<* x i32>, %arg1: tensor<* x f32>) {
+ // expected-error@+1 {{fixed type combination}}
+ %0 = "test.arg_and_res_have_fixed_element_types"(%arg1, %arg0) {attr: ""}: (tensor<* x f32>, tensor<* x i32>) -> tensor<* x i16>
+ return
+}
FmtContext fctx;
fctx.withOp("(*this->getOperation())");
+ // Populate substitutions for attributes and named operands and results.
+ for (const auto &namedAttr : op.getAttributes())
+ fctx.addSubst(namedAttr.name,
+ formatv("(&this->getAttr(\"{0}\"))", namedAttr.name));
+ for (int i = 0, e = op.getNumOperands(); i < e; ++i) {
+ auto &value = op.getOperand(i);
+ // Skip from from first variadic operands for now. Else getOperand index
+ // used below doesn't match.
+ if (value.isVariadic())
+ break;
+ if (!value.name.empty())
+ fctx.addSubst(value.name,
+ formatv("this->getOperation()->getOperand({0})", i));
+ }
+ for (int i = 0, e = op.getNumResults(); i < e; ++i) {
+ auto &value = op.getResult(i);
+ // Skip from from first variadic results for now. Else getResult index used
+ // below doesn't match.
+ if (value.isVariadic())
+ break;
+ if (!value.name.empty())
+ fctx.addSubst(value.name,
+ formatv("this->getOperation()->getResult({0})", i));
+ }
+
// Verify the attributes have the correct type.
for (const auto &namedAttr : op.getAttributes()) {
const auto &attr = namedAttr.attr;
-
if (attr.isDerivedAttr())
continue;