Skip to content

Commit

Permalink
Add python bindings for ArrayAttr, AffineMapAttr.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 283561252
  • Loading branch information
MLIR Team authored and tensorflower-gardener committed Dec 3, 2019
1 parent 993e79e commit 1df7f4e
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 2 deletions.
124 changes: 122 additions & 2 deletions mlir/bindings/python/pybind.cpp
Expand Up @@ -31,6 +31,8 @@
#include "mlir/EDSC/Intrinsics.h"
#include "mlir/ExecutionEngine/ExecutionEngine.h"
#include "mlir/ExecutionEngine/OptUtils.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Function.h"
#include "mlir/IR/Module.h"
Expand Down Expand Up @@ -62,6 +64,8 @@ struct PythonExpr;
struct PythonFunctionContext;
struct PythonStmt;
struct PythonBlock;
struct PythonAffineExpr;
struct PythonAffineMap;

struct PythonType {
PythonType() : type{nullptr} {}
Expand Down Expand Up @@ -191,6 +195,25 @@ struct PythonMLIRModule {
// Create a boolean attribute.
PythonAttribute boolAttr(bool value);

// Creates an Array attribute.
PythonAttribute arrayAttr(const std::vector<PythonAttribute> &values);

// Creates an AffineMap attribute.
PythonAttribute affineMapAttr(PythonAffineMap value);

// Creates an affine constant expression.
PythonAffineExpr affineConstantExpr(int64_t value);

// Creates an affine symbol expression.
PythonAffineExpr affineSymbolExpr(unsigned position);

// Creates a single constant result affine map.
PythonAffineMap affineConstantMap(int64_t value);

// Creates an affine map.
PythonAffineMap affineMap(unsigned dimCount, unsigned symbolCount,
const std::vector<PythonAffineExpr> &results);

// Compile the module save the execution engine. "optLevel" and
// "codegenOptLevel" contain the levels of optimization to run (0 to 3) for
// transformations and codegen. -1 means ExecutionEngine default.
Expand Down Expand Up @@ -467,14 +490,15 @@ struct PythonAttribute {
PythonAttribute(const PythonAttribute &other) = default;
operator mlir_attr_t() { return attr; }

operator Attribute() const { return Attribute::getFromOpaquePointer(attr); }

std::string str() const {
if (!attr)
return "##null attr##";

std::string res;
llvm::raw_string_ostream os(res);
Attribute::getFromOpaquePointer(reinterpret_cast<const void *>(attr))
.print(os);
Attribute().print(os);
return res;
}

Expand Down Expand Up @@ -532,6 +556,46 @@ struct PythonAttributedType {
std::unordered_map<std::string, PythonAttribute> attrs;
};

// Wraps mlir::AffineExpr.
struct PythonAffineExpr {
PythonAffineExpr() : affine_expr() {}
PythonAffineExpr(const AffineExpr &a) : affine_expr(a) {}
PythonAffineExpr(const PythonAffineExpr &other) = default;

operator AffineExpr() const { return affine_expr; }
operator AffineExpr &() { return affine_expr; }

std::string str() const {
std::string res;
llvm::raw_string_ostream os(res);
affine_expr.print(os);
return res;
}

private:
AffineExpr affine_expr;
};

// Wraps mlir::AffineMap.
struct PythonAffineMap {
PythonAffineMap() : affine_map() {}
PythonAffineMap(const AffineMap &a) : affine_map(a) {}
PythonAffineMap(const PythonAffineMap &other) = default;

operator AffineMap() const { return affine_map; }
operator AffineMap &() { return affine_map; }

std::string str() const {
std::string res;
llvm::raw_string_ostream os(res);
affine_map.print(os);
return res;
}

private:
AffineMap affine_map;
};

struct PythonIndexedValue {
explicit PythonIndexedValue(PythonType type)
: indexed(Type::getFromOpaquePointer(type.type)) {}
Expand Down Expand Up @@ -640,6 +704,38 @@ PythonAttribute PythonMLIRModule::boolAttr(bool value) {
return PythonAttribute(::makeBoolAttr(&mlirContext, value));
}

PythonAttribute
PythonMLIRModule::arrayAttr(const std::vector<PythonAttribute> &values) {
std::vector<mlir::Attribute> mlir_attributes(values.begin(), values.end());
auto array_attr = ArrayAttr::get(
llvm::ArrayRef<mlir::Attribute>(mlir_attributes), &mlirContext);
return PythonAttribute(array_attr.getAsOpaquePointer());
}

PythonAttribute PythonMLIRModule::affineMapAttr(PythonAffineMap value) {
return PythonAttribute(AffineMapAttr::get(value).getAsOpaquePointer());
}

PythonAffineExpr PythonMLIRModule::affineConstantExpr(int64_t value) {
return PythonAffineExpr(getAffineConstantExpr(value, &mlirContext));
}

PythonAffineExpr PythonMLIRModule::affineSymbolExpr(unsigned position) {
return PythonAffineExpr(getAffineSymbolExpr(position, &mlirContext));
}

PythonAffineMap PythonMLIRModule::affineConstantMap(int64_t value) {
return PythonAffineMap(AffineMap::getConstantMap(value, &mlirContext));
}

PythonAffineMap
PythonMLIRModule::affineMap(unsigned dimCount, unsigned SymbolCount,
const std::vector<PythonAffineExpr> &results) {
std::vector<AffineExpr> mlir_results(results.begin(), results.end());
return PythonAffineMap(AffineMap::get(
dimCount, SymbolCount, llvm::ArrayRef<AffineExpr>(mlir_results)));
}

PYBIND11_MODULE(pybind, m) {
m.doc() =
"Python bindings for MLIR Embedded Domain-Specific Components (EDSCs)";
Expand Down Expand Up @@ -801,6 +897,12 @@ PYBIND11_MODULE(pybind, m) {
"integerAttr", &PythonMLIRModule::integerAttr,
"Creates an mlir::IntegerAttr of the given type with the given value "
"in the context associated with this MLIR module.")
.def("arrayAttr", &PythonMLIRModule::arrayAttr,
"Creates an mlir::ArrayAttr of the given type with the given values "
"in the context associated with this MLIR module.")
.def("affineMapAttr", &PythonMLIRModule::affineMapAttr,
"Creates an mlir::AffineMapAttr of the given type with the given "
"value in the context associated with this MLIR module.")
.def("declare_function", &PythonMLIRModule::declareFunction,
"Declares a new mlir::FuncOp in the current mlir::ModuleOp. The "
"function arguments can have attributes. The function has no "
Expand Down Expand Up @@ -831,6 +933,14 @@ PYBIND11_MODULE(pybind, m) {
.def("get_engine_address", &PythonMLIRModule::getEngineAddress,
"Returns the address of the compiled ExecutionEngine. This is used "
"for in-process execution.")
.def("affine_constant_expr", &PythonMLIRModule::affineConstantExpr,
"Returns an affine constant expression.")
.def("affine_symbol_expr", &PythonMLIRModule::affineSymbolExpr,
"Returns an affine symbol expression.")
.def("affine_constant_map", &PythonMLIRModule::affineConstantMap,
"Returns an affine map with single constant result.")
.def("affine_map", &PythonMLIRModule::affineMap, "Returns an affine map.",
py::arg("dimCount"), py::arg("symbolCount"), py::arg("resuls"))
.def("__str__", &PythonMLIRModule::getIR,
"Get the string representation of the module");

Expand Down Expand Up @@ -940,6 +1050,16 @@ PYBIND11_MODULE(pybind, m) {
.def(py::init<PythonValueHandle>())
.def("load", &PythonIndexedValue::load)
.def("store", &PythonIndexedValue::store);

py::class_<PythonAffineExpr>(m, "AffineExpr",
"A wrapper around mlir::AffineExpr")
.def(py::init<PythonAffineExpr>())
.def("__str__", &PythonAffineExpr::str);

py::class_<PythonAffineMap>(m, "AffineMap",
"A wrapper around mlir::AffineMap")
.def(py::init<PythonAffineMap>())
.def("__str__", &PythonAffineMap::str);
}

} // namespace python
Expand Down
35 changes: 35 additions & 0 deletions mlir/bindings/python/test/test_py2and3.py
Expand Up @@ -285,6 +285,41 @@ def testFunctionDeclaration(self):
# CHECK-LABEL: testFunctionDeclaration
# CHECK: func @foo(memref<10xf32>, memref<10xf32> {llvm.noalias = true}, memref<10xf32> {readonly = true})

def testFunctionDeclarationWithAffineAttr(self):
self.setUp()
a1 = self.module.affine_constant_expr(23)
a2 = self.module.affine_constant_expr(44)
s0 = self.module.affine_symbol_expr(0)
aMap1 = self.module.affine_map(2, 0, [a1, a2, s0])
aMap2 = self.module.affine_constant_map(42)
affineAttr1 = self.module.affineMapAttr(aMap1)
affineAttr2 = self.module.affineMapAttr(aMap2)

t = self.module.make_memref_type(self.f32Type, [10])
t_with_attr = t({
"affine_attr_1": affineAttr1,
"affine_attr_2": affineAttr2
})

f = self.module.declare_function("foo", [t, t_with_attr], [])
printWithCurrentFunctionName(str(self.module))
# CHECK-LABEL: testFunctionDeclarationWithAffineAttr
# CHECK: func @foo(memref<10xf32>, memref<10xf32> {affine_attr_1 = (d0, d1) -> (23, 44, s0), affine_attr_2 = () -> (42)})

def testFunctionDeclarationWithArrayAttr(self):
self.setUp()
arrayAttr = self.module.arrayAttr([
self.module.integerAttr(self.i32Type, 43),
self.module.integerAttr(self.i32Type, 33),
])
t = self.module.make_memref_type(self.f32Type, [10])
t_with_attr = t({"array_attr": arrayAttr})

f = self.module.declare_function("foo", [t, t_with_attr], [])
printWithCurrentFunctionName(str(self.module))
# CHECK-LABEL: testFunctionDeclarationWithArrayAttr
# CHECK: func @foo(memref<10xf32>, memref<10xf32> {array_attr = [43 : i32, 33 : i32]})

def testFunctionMultiple(self):
self.setUp()
with self.module.function_context("foo", [], []):
Expand Down

0 comments on commit 1df7f4e

Please sign in to comment.