let results = (outs Variadic<AnyType>:$resultA, Variadic<AnyType>:$resultB);
}
+// Single variadic arg, non variadic results, with SameOperandsAndResultType.
+// Tests suppression of ambiguious build methods for operations with
+// SameOperandsAndResultType trait.
+def TableGenBuildOp4 : TEST_Op<"tblgen_build_4", [SameOperandsAndResultType]> {
+ let arguments = (ins Variadic<AnyType>:$inputs);
+ let results = (outs AnyType:$result);
+}
+
+// Single variadic arg with SameOperandsAndResultType and InferTypeOpInterface.
+// Tests suppression of ambiguious build methods for operations with
+// SameOperandsAndResultType and InferTypeOpInterface.
+def TableGenBuildOp5 : TEST_Op<"tblgen_build_5",
+ [SameOperandsAndResultType, InferTypeOpInterface]> {
+ let arguments = (ins Variadic<AnyType>:$inputs);
+ let results = (outs AnyType:$result);
+
+ let extraClassDeclaration = [{
+ static LogicalResult inferReturnTypes(MLIRContext *,
+ Optional<Location> location, ValueRange operands,
+ DictionaryAttr attributes, RegionRange regions,
+ SmallVectorImpl<Type> &inferredReturnTypes) {
+ inferredReturnTypes.assign({operands[0].getType()});
+ return success();
+ }
+ }];
+}
+
#endif // TEST_OPS
// operand's type as all results' types.
void genUseOperandAsResultTypeCollectiveParamBuilder();
+ // Returns true if the inferred collective param build method should be
+ // generated.
+ bool shouldGenerateInferredTypeCollectiveParamBuilder();
+
// Generates the build() method that takes aggregate operands/attributes
// parameters. This build() method uses inferred types as result types.
// Requires: The type needs to be inferable via InferTypeOpInterface.
// result
//
// In that case, skip generating such ambiguous build methods here.
- bool hasSingleVariadicResult =
- op.getNumResults() == 1 && op.getResult(0).isVariadic();
-
- bool hasSingleVariadicArg =
- op.getNumArgs() == 1 &&
- op.getArg(0).is<tblgen::NamedTypeConstraint *>() &&
- op.getOperand(0).isVariadic();
- bool hasNoVariadicRegions = op.getNumVariadicRegions() == 0;
-
for (auto attrType : attrBuilderType) {
// Case 3b above.
- if (!(hasNoVariadicRegions && hasSingleVariadicArg &&
- hasSingleVariadicResult))
+ if (!(op.hasNoVariadicRegions() && op.hasSingleVariadicArg() &&
+ op.hasSingleVariadicResult()))
emit(attrType, TypeParamKind::Separate, /*inferType=*/false);
- if (canInferType(op))
- emit(attrType, TypeParamKind::None, /*inferType=*/true);
+ if (canInferType(op)) {
+ // When inferType = true, the generated build method does not have
+ // result types. If the op has a single variadic arg, then this build
+ // method will be ambiguious with the collective inferred build method
+ // generated in `genInferredTypeCollectiveParamBuilder`. If we are going
+ // to generate that collective inferred method, suppress generating the
+ // ambiguious build method here.
+ bool buildMethodAmbiguious =
+ op.hasSingleVariadicArg() &&
+ shouldGenerateInferredTypeCollectiveParamBuilder();
+ if (!buildMethodAmbiguious)
+ emit(attrType, TypeParamKind::None, /*inferType=*/true);
+ }
// The separate arg + collective param kind method will be:
// (a) Same as the separate arg + separate param kind method if there is
// only one variadic result.
// (b) Ambiguous with the collective params method under conditions in (3a)
// above.
// In either case, skip generating such build method.
- if (!hasSingleVariadicResult &&
- !(hasNoVariadicRegions && hasSingleVariadicArg))
+ if (!op.hasSingleVariadicResult() &&
+ !(op.hasNoVariadicRegions() && op.hasSingleVariadicArg()))
emit(attrType, TypeParamKind::Collective, /*inferType=*/false);
}
}
void OpEmitter::genUseOperandAsResultTypeCollectiveParamBuilder() {
- // If this op has a variadic result, we cannot generate this builder because
- // we don't know how many results to create.
- if (op.getNumVariableLengthResults() != 0)
- return;
-
int numResults = op.getNumResults();
// Signature
<< llvm::join(resultTypes, ", ") << "});\n\n";
}
+bool OpEmitter::shouldGenerateInferredTypeCollectiveParamBuilder() {
+ return canInferType(op) && op.getNumSuccessors() == 0;
+}
+
void OpEmitter::genInferredTypeCollectiveParamBuilder() {
// TODO: Expand to support regions.
std::string params =
// to facilitate different call patterns.
if (op.getNumVariableLengthResults() == 0) {
if (op.getTrait("OpTrait::SameOperandsAndResultType")) {
- genUseOperandAsResultTypeSeparateParamBuilder();
- genUseOperandAsResultTypeCollectiveParamBuilder();
+ // If the operation has a single variadic input, then the build method
+ // generated by `genUseOperandAsResultTypeSeparateParamBuilder` will be
+ // ambiguious with the one generated by
+ // `genUseOperandAsResultTypeCollectiveParamBuilder` (they both will have
+ // a single `ValueRange` argument for operands, and the collective one
+ // will have a `ArrayRef<NamedAttribute>` argument initalized to empty).
+ // Suppress such ambiguious build method.
+ if (!op.hasSingleVariadicArg())
+ genUseOperandAsResultTypeSeparateParamBuilder();
+
+ // The build method generated by the inferred type collective param
+ // builder and one generated here have the same arguments and hence
+ // generating both will be ambiguious. Enable just one of them.
+ if (!shouldGenerateInferredTypeCollectiveParamBuilder())
+ genUseOperandAsResultTypeCollectiveParamBuilder();
}
if (op.getTrait("OpTrait::FirstAttrDerivedResultType"))
genUseAttrAsResultTypeBuilder();
// Generate builder that infers type too.
// TODO: Expand to handle regions and successors.
- if (canInferType(op) && op.getNumSuccessors() == 0)
+ if (shouldGenerateInferredTypeCollectiveParamBuilder())
genInferredTypeCollectiveParamBuilder();
}
concreteOp.erase();
}
+ // Helper method to test ops with inferred result types and single variadic
+ // input.
+ template <typename OpTy>
+ void testSingleVariadicInputInferredType() {
+ // Test separate arg, separate param build method.
+ auto op = builder.create<OpTy>(loc, i32Ty, ArrayRef<Value>{cstI32, cstI32});
+ verifyOp(std::move(op), {i32Ty}, {cstI32, cstI32}, noAttrs);
+
+ // Test collective params build method.
+ op = builder.create<OpTy>(loc, ArrayRef<Type>{i32Ty},
+ ArrayRef<Value>{cstI32, cstI32});
+ verifyOp(std::move(op), {i32Ty}, {cstI32, cstI32}, noAttrs);
+
+ // Test build method with no result types, default value of attributes.
+ op = builder.create<OpTy>(loc, ArrayRef<Value>{cstI32, cstI32});
+ verifyOp(std::move(op), {i32Ty}, {cstI32, cstI32}, noAttrs);
+
+ // Test build method with no result types and supplied attributes.
+ op = builder.create<OpTy>(loc, ArrayRef<Value>{cstI32, cstI32}, attrs);
+ verifyOp(std::move(op), {i32Ty}, {cstI32, cstI32}, attrs);
+ }
+
protected:
MLIRContext ctx;
OpBuilder builder;
verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32}, attrs);
}
+// The next 2 tests test supression of ambiguious build methods for ops that
+// have a single variadic input, and single non-variadic result, and which
+// support the SameOperandsAndResultType trait and and optionally the
+// InferOpTypeInterface interface. For such ops, the ODS framework generates
+// build methods with no result types as they are inferred from the input types.
+TEST_F(OpBuildGenTest, BuildMethodsSameOperandsAndResultTypeSuppression) {
+ testSingleVariadicInputInferredType<TableGenBuildOp4>();
+}
+
+TEST_F(
+ OpBuildGenTest,
+ BuildMethodsSameOperandsAndResultTypeAndInferOpTypeInterfaceSuppression) {
+ testSingleVariadicInputInferredType<TableGenBuildOp5>();
+}
+
} // namespace mlir