@@ -211,6 +211,10 @@ static MlirStringRef toMlirStringRef(const std::string &s) {
211
211
return mlirStringRefCreate (s.data (), s.size ());
212
212
}
213
213
214
+ static MlirStringRef toMlirStringRef (std::string_view s) {
215
+ return mlirStringRefCreate (s.data (), s.size ());
216
+ }
217
+
214
218
static MlirStringRef toMlirStringRef (const nb::bytes &s) {
215
219
return mlirStringRefCreate (static_cast <const char *>(s.data ()), s.size ());
216
220
}
@@ -1460,7 +1464,7 @@ static void maybeInsertOperation(PyOperationRef &op,
1460
1464
}
1461
1465
}
1462
1466
1463
- nb::object PyOperation::create (const std::string & name,
1467
+ nb::object PyOperation::create (std::string_view name,
1464
1468
std::optional<std::vector<PyType *>> results,
1465
1469
std::optional<std::vector<PyValue *>> operands,
1466
1470
std::optional<nb::dict> attributes,
@@ -1506,7 +1510,7 @@ nb::object PyOperation::create(const std::string &name,
1506
1510
} catch (nb::cast_error &err) {
1507
1511
std::string msg = " Invalid attribute key (not a string) when "
1508
1512
" attempting to create the operation \" " +
1509
- name + " \" (" + err.what () + " )" ;
1513
+ std::string ( name) + " \" (" + err.what () + " )" ;
1510
1514
throw nb::type_error (msg.c_str ());
1511
1515
}
1512
1516
try {
@@ -1516,13 +1520,14 @@ nb::object PyOperation::create(const std::string &name,
1516
1520
} catch (nb::cast_error &err) {
1517
1521
std::string msg = " Invalid attribute value for the key \" " + key +
1518
1522
" \" when attempting to create the operation \" " +
1519
- name + " \" (" + err.what () + " )" ;
1523
+ std::string ( name) + " \" (" + err.what () + " )" ;
1520
1524
throw nb::type_error (msg.c_str ());
1521
1525
} catch (std::runtime_error &) {
1522
1526
// This exception seems thrown when the value is "None".
1523
1527
std::string msg =
1524
1528
" Found an invalid (`None`?) attribute value for the key \" " + key +
1525
- " \" when attempting to create the operation \" " + name + " \" " ;
1529
+ " \" when attempting to create the operation \" " +
1530
+ std::string (name) + " \" " ;
1526
1531
throw std::runtime_error (msg);
1527
1532
}
1528
1533
}
@@ -1714,27 +1719,25 @@ static void populateResultTypes(StringRef name, nb::list resultTypeList,
1714
1719
}
1715
1720
1716
1721
nb::object PyOpView::buildGeneric (
1717
- const nb::object &cls, std::optional<nb::list> resultTypeList,
1718
- nb::list operandList, std::optional<nb::dict> attributes,
1722
+ std::string_view name, std::tuple<int , bool > opRegionSpec,
1723
+ nb::object operandSegmentSpecObj, nb::object resultSegmentSpecObj,
1724
+ std::optional<nb::list> resultTypeList, nb::list operandList,
1725
+ std::optional<nb::dict> attributes,
1719
1726
std::optional<std::vector<PyBlock *>> successors,
1720
1727
std::optional<int > regions, DefaultingPyLocation location,
1721
1728
const nb::object &maybeIp) {
1722
1729
PyMlirContextRef context = location->getContext ();
1730
+
1723
1731
// Class level operation construction metadata.
1724
- std::string name = nb::cast<std::string>(cls.attr (" OPERATION_NAME" ));
1725
1732
// Operand and result segment specs are either none, which does no
1726
1733
// variadic unpacking, or a list of ints with segment sizes, where each
1727
1734
// element is either a positive number (typically 1 for a scalar) or -1 to
1728
1735
// indicate that it is derived from the length of the same-indexed operand
1729
1736
// or result (implying that it is a list at that position).
1730
- nb::object operandSegmentSpecObj = cls.attr (" _ODS_OPERAND_SEGMENTS" );
1731
- nb::object resultSegmentSpecObj = cls.attr (" _ODS_RESULT_SEGMENTS" );
1732
-
1733
1737
std::vector<int32_t > operandSegmentLengths;
1734
1738
std::vector<int32_t > resultSegmentLengths;
1735
1739
1736
1740
// Validate/determine region count.
1737
- auto opRegionSpec = nb::cast<std::tuple<int , bool >>(cls.attr (" _ODS_REGIONS" ));
1738
1741
int opMinRegionCount = std::get<0 >(opRegionSpec);
1739
1742
bool opHasNoVariadicRegions = std::get<1 >(opRegionSpec);
1740
1743
if (!regions) {
@@ -3236,6 +3239,33 @@ void mlir::python::populateIRCore(nb::module_ &m) {
3236
3239
auto opViewClass =
3237
3240
nb::class_<PyOpView, PyOperationBase>(m, " OpView" )
3238
3241
.def (nb::init<nb::object>(), nb::arg (" operation" ))
3242
+ .def (
3243
+ " __init__" ,
3244
+ [](PyOpView *self, std::string_view name,
3245
+ std::tuple<int , bool > opRegionSpec,
3246
+ nb::object operandSegmentSpecObj,
3247
+ nb::object resultSegmentSpecObj,
3248
+ std::optional<nb::list> resultTypeList, nb::list operandList,
3249
+ std::optional<nb::dict> attributes,
3250
+ std::optional<std::vector<PyBlock *>> successors,
3251
+ std::optional<int > regions, DefaultingPyLocation location,
3252
+ const nb::object &maybeIp) {
3253
+ new (self) PyOpView (PyOpView::buildGeneric (
3254
+ name, opRegionSpec, operandSegmentSpecObj,
3255
+ resultSegmentSpecObj, resultTypeList, operandList,
3256
+ attributes, successors, regions, location, maybeIp));
3257
+ },
3258
+ nb::arg (" name" ), nb::arg (" opRegionSpec" ),
3259
+ nb::arg (" operandSegmentSpecObj" ).none () = nb::none (),
3260
+ nb::arg (" resultSegmentSpecObj" ).none () = nb::none (),
3261
+ nb::arg (" results" ).none () = nb::none (),
3262
+ nb::arg (" operands" ).none () = nb::none (),
3263
+ nb::arg (" attributes" ).none () = nb::none (),
3264
+ nb::arg (" successors" ).none () = nb::none (),
3265
+ nb::arg (" regions" ).none () = nb::none (),
3266
+ nb::arg (" loc" ).none () = nb::none (),
3267
+ nb::arg (" ip" ).none () = nb::none ())
3268
+
3239
3269
.def_prop_ro (" operation" , &PyOpView::getOperationObject)
3240
3270
.def_prop_ro (" opview" , [](nb::object self) { return self; })
3241
3271
.def (
@@ -3250,9 +3280,26 @@ void mlir::python::populateIRCore(nb::module_ &m) {
3250
3280
opViewClass.attr (" _ODS_REGIONS" ) = nb::make_tuple (0 , true );
3251
3281
opViewClass.attr (" _ODS_OPERAND_SEGMENTS" ) = nb::none ();
3252
3282
opViewClass.attr (" _ODS_RESULT_SEGMENTS" ) = nb::none ();
3283
+ // It is faster to pass the operation_name, ods_regions, and
3284
+ // ods_operand_segments/ods_result_segments as arguments to the constructor,
3285
+ // rather than to access them as attributes.
3253
3286
opViewClass.attr (" build_generic" ) = classmethod (
3254
- &PyOpView::buildGeneric, nb::arg (" cls" ),
3255
- nb::arg (" results" ).none () = nb::none (),
3287
+ [](nb::handle cls, std::optional<nb::list> resultTypeList,
3288
+ nb::list operandList, std::optional<nb::dict> attributes,
3289
+ std::optional<std::vector<PyBlock *>> successors,
3290
+ std::optional<int > regions, DefaultingPyLocation location,
3291
+ const nb::object &maybeIp) {
3292
+ std::string name = nb::cast<std::string>(cls.attr (" OPERATION_NAME" ));
3293
+ std::tuple<int , bool > opRegionSpec =
3294
+ nb::cast<std::tuple<int , bool >>(cls.attr (" _ODS_REGIONS" ));
3295
+ nb::object operandSegmentSpec = cls.attr (" _ODS_OPERAND_SEGMENTS" );
3296
+ nb::object resultSegmentSpec = cls.attr (" _ODS_RESULT_SEGMENTS" );
3297
+ return PyOpView::buildGeneric (name, opRegionSpec, operandSegmentSpec,
3298
+ resultSegmentSpec, resultTypeList,
3299
+ operandList, attributes, successors,
3300
+ regions, location, maybeIp);
3301
+ },
3302
+ nb::arg (" cls" ), nb::arg (" results" ).none () = nb::none (),
3256
3303
nb::arg (" operands" ).none () = nb::none (),
3257
3304
nb::arg (" attributes" ).none () = nb::none (),
3258
3305
nb::arg (" successors" ).none () = nb::none (),
0 commit comments