// ODS: F32:$f32_attr,
// ODS: RankedF32ElementsAttr<[4]>:$fvec_attr,
// ODS: I32:$i32_attr,
+// ODS: I64:$i64_attr,
// ODS: RankedI32ElementsAttr<[5, 6]>:$ivec_attr,
// ODS: OptionalAttr<F32>:$optional_attr
//
attr(
f32_attr: f32,
i32_attr: i32,
+ i64_attr: i64,
fvec_attr: 4xf32,
ivec_attr: 5x6xi32,
array_attr : f32[],
I(n, h * strides[0] + kh, w * strides[1] + kw, c), K(f, kh, kw, c)));
}
+// Test documentation
// ODS-LABEL: def Test6Op
// ODS: let summary = [{ My magic op. }];
// ODS-NEXT: let description = [{
{
C(m) = std_addf<k>(std_mulf(A(m, k), B(k)));
}
+
+// Test attribute builder
+// ODS-LABEL: def Test7Op
+// ODS: OpBuilderDAG<
+// ODS: (ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs,
+// ODS: "ValueRange":$outputs, "Attribute":$attr_a, "Attribute":$attr_b)
+// ODS: $_state.addAttribute("attr_a", attr_a);
+// ODS: $_state.addAttribute("attr_b", attr_b);
+//
+ods_def<Test7Op>:
+def test7(A: f32(M, K), B: f32(K)) -> (C: f32(M))
+ attr(attr_a: f32, attr_b: 4xi32)
+{
+ C(m) = std_addf<k>(std_mulf(A(m, k), B(k)));
+}
std::string odsType = llvm::StringSwitch<std::string>(elementType)
.Case("f32", "F32")
.Case("i32", "I32")
+ .Case("i64", "I64")
.Default("");
if (odsType.empty()) {
parser.emitError("unimplemented support for attribute element type: " +
let regions = (region AnyRegion:$region);
let skipDefaultBuilders = 1;
- let builders = [ OpBuilderDAG<
+ let builders = [
+ OpBuilderDAG<
(ins "ValueRange":$inputs, "ValueRange":$outputs),
[{{
$_state.addOperands(inputs);
$_state,
TypeRange(inputs),
TypeRange(outputs));
- }]>, OpBuilderDAG<
+ }]>,
+ OpBuilderDAG<
(ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs,
"ValueRange":$outputs),
[{{
$_state,
TypeRange(inputs),
TypeRange(outputs));
- }]>, OpBuilderDAG<
+ }]>,
+ OpBuilderDAG<
(ins "TypeRange":$resultTensorTypes, "ValueRange":$operands,
CArg<"ArrayRef<NamedAttribute>", "{{}">:$attributes),
[{{
$_state.addTypes(resultTensorTypes);
(void)$_state.addRegion();
}]>
+ {5}
];
let printer = [{{ return ::printNamedStructuredOp(p, *this); }];
let parser = [{{ return ::parseNamedStructuredOp<{0}>(parser, result); }];
}];
})FMT";
+ // Generate documentation.
std::string doc;
-
if (!docString.empty()) {
const char *docFmt = R"FMT(
let summary = [{ {0} }];
doc = llvm::formatv(docFmt, summary.trim(), description.trim());
}
+ // Generate an additional builder that has parameters for attributes.
+ std::string attrBuilder;
+ if (!registeredAttrs.empty()) {
+ SmallVector<std::string, 4> attrParams, attrStmts;
+ for (const auto &attr : registeredAttrs) {
+ llvm::StringRef name = attr.first;
+ attrParams.push_back(llvm::formatv("\"Attribute\":${0}", name));
+ attrStmts.push_back(
+ llvm::formatv("$_state.addAttribute(\"{0}\", {0});", name));
+ }
+ std::string attrParamsList = llvm::join(attrParams, ", ");
+ std::string attrStmtsList = llvm::join(attrStmts, "\n");
+
+ const char *builderFmt = R"FMT(
+ , OpBuilderDAG<
+ (ins "TypeRange":$resultTensorTypes, "ValueRange":$inputs,
+ "ValueRange":$outputs, {1}),
+ [{{
+ $_state.addOperands(inputs);
+ $_state.addOperands(outputs);
+ $_state.addTypes(resultTensorTypes);
+ $_state.addAttribute(
+ "operand_segment_sizes",
+ $_builder.getI32VectorAttr({{
+ static_cast<int32_t>(inputs.size()),
+ static_cast<int32_t>(outputs.size())}));
+ buildNamedStructuredOpRegionAndAttributes<{0}>(
+ $_builder,
+ $_state,
+ TypeRange(inputs),
+ TypeRange(outputs));
+ {2}
+ }]>
+ )FMT";
+ attrBuilder =
+ llvm::formatv(builderFmt, cppOpName, attrParamsList, attrStmtsList);
+ }
+
+ // Finally put everything together.
os << llvm::formatv(header, cppOpName, linalgOpName, doc, attrList,
- state.orderedTensorArgs.size());
+ state.orderedTensorArgs.size(), attrBuilder);
}
/// Print the C++ StructuredOpsInterface impl of `iterator_types`.
return llvm::formatv("getValue<float>({ {0} })", indexList);
if (elementType == "i32")
return llvm::formatv("getValue<int>({ {0} })", indexList);
+ if (elementType == "i64")
+ return llvm::formatv("getValue<int64_t>({ {0} })", indexList);
return "";
}
if (elementType == "f32")
return "getValue().convertToFloat()";
- if (elementType == "i32")
+ if (elementType == "i32" || elementType == "i64")
return "getInt()";
return "";
}