[mlir][tblgen] Generate builders with inferred return types and unwrapped attributes

This diff causes mlir-tblgen to generate code for an additional builder for an
operation argument with a return type that can be inferred *AND* an attribute in
the argument list can be "unwrapped." (Previously, the unwrapped build function
was only generated for builders with explicit return types in separate or
aggregate form.) As an example, this builder might be used by code that creates
operations that implement the `SameOperandsAndResultType` interface. A test case
was created.

Reviewed By: jpienaar

Differential Revision: https://reviews.llvm.org/D124043
This commit is contained in:
jfurtek 2022-04-25 19:00:20 +00:00 committed by Mogball
parent a266a21000
commit c4caa90b15
3 changed files with 50 additions and 24 deletions

View File

@ -388,7 +388,7 @@ The following builders are generated:
```c++
// All result-types/operands/attributes have one aggregate parameter.
static void build(OpBuilder &odsBuilder, OperationState &odsState,
ArrayRef<Type> resultTypes,
TypeRange resultTypes,
ValueRange operands,
ArrayRef<NamedAttribute> attributes);
@ -410,7 +410,7 @@ static void build(OpBuilder &odsBuilder, OperationState &odsState,
// Each operand/attribute has a separate parameter but result type is aggregate.
static void build(OpBuilder &odsBuilder, OperationState &odsState,
ArrayRef<Type> resultTypes,
TypeRange resultTypes,
Value i32_operand, Value f32_operand, ...,
IntegerAttr i32_attr, FloatAttr f32_attr, ...);

View File

@ -94,7 +94,9 @@ def NS_AOp : NS_Op<"a_op", [IsolatedFromAbove, IsolatedFromAbove]> {
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, Value val);
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, int integer = 0);
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type r, ::mlir::TypeRange s, ::mlir::Value a, ::mlir::ValueRange b, ::mlir::IntegerAttr attr1, /*optional*/::mlir::FloatAttr attr2, unsigned someRegionsCount)
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value a, ::mlir::ValueRange b, ::mlir::IntegerAttr attr1, /*optional*/::mlir::FloatAttr attr2, unsigned someRegionsCount);
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type r, ::mlir::TypeRange s, ::mlir::Value a, ::mlir::ValueRange b, uint32_t attr1, /*optional*/::mlir::FloatAttr attr2, unsigned someRegionsCount)
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value a, ::mlir::ValueRange b, uint32_t attr1, /*optional*/::mlir::FloatAttr attr2, unsigned someRegionsCount);
// CHECK: static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes, unsigned numRegions)
// CHECK: static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result);
// CHECK: void print(::mlir::OpAsmPrinter &p);
@ -286,6 +288,21 @@ def NS_KWithTraitOp : NS_Op<"KWithTrait", [NS_TestTrait]>;
// CHECK: class KWithTraitOp : public ::mlir::Op<KWithTraitOp
// CHECK-SAME: SomeNamespace::TestTrait
def NS_LOp : NS_Op<"op_with_same_operands_and_result_types_unwrapped_attr", [SameOperandsAndResultType]> {
let arguments = (ins AnyType:$a, AnyType:$b, I32Attr:$attr1);
let results = (outs AnyType:$r);
}
// CHECK_LABEL: class NS_LOp :
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type r, ::mlir::Value a, ::mlir::Value b, ::mlir::IntegerAttr attr1);
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value a, ::mlir::Value b, ::mlir::IntegerAttr attr1);
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type r, ::mlir::Value a, ::mlir::Value b, uint32_t attr1);
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value a, ::mlir::Value b, uint32_t attr1);
// CHECK: static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {});
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value a, ::mlir::Value b, ::mlir::IntegerAttr attr1);
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value a, ::mlir::Value b, uint32_t attr1);
// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {});
// Test that type defs have the proper namespaces when used as a constraint.
// ---

View File

@ -1651,31 +1651,40 @@ void OpEmitter::genInferredTypeCollectiveParamBuilder() {
}
void OpEmitter::genUseOperandAsResultTypeSeparateParamBuilder() {
SmallVector<MethodParameter> paramList;
SmallVector<std::string, 4> resultNames;
llvm::StringSet<> inferredAttributes;
buildParamList(paramList, inferredAttributes, resultNames,
TypeParamKind::None);
auto emit = [&](AttrParamKind attrType) {
SmallVector<MethodParameter> paramList;
SmallVector<std::string, 4> resultNames;
llvm::StringSet<> inferredAttributes;
buildParamList(paramList, inferredAttributes, resultNames,
TypeParamKind::None, attrType);
auto *m = opClass.addStaticMethod("void", "build", std::move(paramList));
// If the builder is redundant, skip generating the method
if (!m)
return;
auto &body = m->body();
genCodeForAddingArgAndRegionForBuilder(body, inferredAttributes);
auto *m = opClass.addStaticMethod("void", "build", std::move(paramList));
// If the builder is redundant, skip generating the method
if (!m)
return;
auto &body = m->body();
genCodeForAddingArgAndRegionForBuilder(body, inferredAttributes,
/*isRawValueAttr=*/attrType ==
AttrParamKind::UnwrappedValue);
auto numResults = op.getNumResults();
if (numResults == 0)
return;
auto numResults = op.getNumResults();
if (numResults == 0)
return;
// Push all result types to the operation state
const char *index = op.getOperand(0).isVariadic() ? ".front()" : "";
std::string resultType =
formatv("{0}{1}.getType()", getArgumentName(op, 0), index).str();
body << " " << builderOpState << ".addTypes({" << resultType;
for (int i = 1; i != numResults; ++i)
body << ", " << resultType;
body << "});\n\n";
// Push all result types to the operation state
const char *index = op.getOperand(0).isVariadic() ? ".front()" : "";
std::string resultType =
formatv("{0}{1}.getType()", getArgumentName(op, 0), index).str();
body << " " << builderOpState << ".addTypes({" << resultType;
for (int i = 1; i != numResults; ++i)
body << ", " << resultType;
body << "});\n\n";
};
emit(AttrParamKind::WrappedAttr);
// Generate additional builder(s) if any attributes can be "unwrapped"
if (canGenerateUnwrappedBuilder(op))
emit(AttrParamKind::UnwrappedValue);
}
void OpEmitter::genUseAttrAsResultTypeBuilder() {