947 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			947 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- IRAffine.cpp - Exports 'ir' module affine related bindings ---------===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "IRModule.h"
 | 
						|
 | 
						|
#include "PybindUtils.h"
 | 
						|
 | 
						|
#include "mlir-c/AffineMap.h"
 | 
						|
#include "mlir-c/Bindings/Python/Interop.h"
 | 
						|
#include "mlir-c/IntegerSet.h"
 | 
						|
 | 
						|
namespace py = pybind11;
 | 
						|
using namespace mlir;
 | 
						|
using namespace mlir::python;
 | 
						|
 | 
						|
using llvm::SmallVector;
 | 
						|
using llvm::StringRef;
 | 
						|
using llvm::Twine;
 | 
						|
 | 
						|
static const char kDumpDocstring[] =
 | 
						|
    R"(Dumps a debug representation of the object to stderr.)";
 | 
						|
 | 
						|
/// Attempts to populate `result` with the content of `list` casted to the
 | 
						|
/// appropriate type (Python and C types are provided as template arguments).
 | 
						|
/// Throws errors in case of failure, using "action" to describe what the caller
 | 
						|
/// was attempting to do.
 | 
						|
template <typename PyType, typename CType>
 | 
						|
static void pyListToVector(py::list list, llvm::SmallVectorImpl<CType> &result,
 | 
						|
                           StringRef action) {
 | 
						|
  result.reserve(py::len(list));
 | 
						|
  for (py::handle item : list) {
 | 
						|
    try {
 | 
						|
      result.push_back(item.cast<PyType>());
 | 
						|
    } catch (py::cast_error &err) {
 | 
						|
      std::string msg = (llvm::Twine("Invalid expression when ") + action +
 | 
						|
                         " (" + err.what() + ")")
 | 
						|
                            .str();
 | 
						|
      throw py::cast_error(msg);
 | 
						|
    } catch (py::reference_cast_error &err) {
 | 
						|
      std::string msg = (llvm::Twine("Invalid expression (None?) when ") +
 | 
						|
                         action + " (" + err.what() + ")")
 | 
						|
                            .str();
 | 
						|
      throw py::cast_error(msg);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
template <typename PermutationTy>
 | 
						|
static bool isPermutation(std::vector<PermutationTy> permutation) {
 | 
						|
  llvm::SmallVector<bool, 8> seen(permutation.size(), false);
 | 
						|
  for (auto val : permutation) {
 | 
						|
    if (val < permutation.size()) {
 | 
						|
      if (seen[val])
 | 
						|
        return false;
 | 
						|
      seen[val] = true;
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
/// CRTP base class for Python MLIR affine expressions that subclass AffineExpr
 | 
						|
/// and should be castable from it. Intermediate hierarchy classes can be
 | 
						|
/// modeled by specifying BaseTy.
 | 
						|
template <typename DerivedTy, typename BaseTy = PyAffineExpr>
 | 
						|
class PyConcreteAffineExpr : public BaseTy {
 | 
						|
public:
 | 
						|
  // Derived classes must define statics for:
 | 
						|
  //   IsAFunctionTy isaFunction
 | 
						|
  //   const char *pyClassName
 | 
						|
  // and redefine bindDerived.
 | 
						|
  using ClassTy = py::class_<DerivedTy, BaseTy>;
 | 
						|
  using IsAFunctionTy = bool (*)(MlirAffineExpr);
 | 
						|
 | 
						|
  PyConcreteAffineExpr() = default;
 | 
						|
  PyConcreteAffineExpr(PyMlirContextRef contextRef, MlirAffineExpr affineExpr)
 | 
						|
      : BaseTy(std::move(contextRef), affineExpr) {}
 | 
						|
  PyConcreteAffineExpr(PyAffineExpr &orig)
 | 
						|
      : PyConcreteAffineExpr(orig.getContext(), castFrom(orig)) {}
 | 
						|
 | 
						|
  static MlirAffineExpr castFrom(PyAffineExpr &orig) {
 | 
						|
    if (!DerivedTy::isaFunction(orig)) {
 | 
						|
      auto origRepr = py::repr(py::cast(orig)).cast<std::string>();
 | 
						|
      throw SetPyError(PyExc_ValueError,
 | 
						|
                       Twine("Cannot cast affine expression to ") +
 | 
						|
                           DerivedTy::pyClassName + " (from " + origRepr + ")");
 | 
						|
    }
 | 
						|
    return orig;
 | 
						|
  }
 | 
						|
 | 
						|
  static void bind(py::module &m) {
 | 
						|
    auto cls = ClassTy(m, DerivedTy::pyClassName, py::module_local());
 | 
						|
    cls.def(py::init<PyAffineExpr &>(), py::arg("expr"));
 | 
						|
    cls.def_static(
 | 
						|
        "isinstance",
 | 
						|
        [](PyAffineExpr &otherAffineExpr) -> bool {
 | 
						|
          return DerivedTy::isaFunction(otherAffineExpr);
 | 
						|
        },
 | 
						|
        py::arg("other"));
 | 
						|
    DerivedTy::bindDerived(cls);
 | 
						|
  }
 | 
						|
 | 
						|
  /// Implemented by derived classes to add methods to the Python subclass.
 | 
						|
  static void bindDerived(ClassTy &m) {}
 | 
						|
};
 | 
						|
 | 
						|
class PyAffineConstantExpr : public PyConcreteAffineExpr<PyAffineConstantExpr> {
 | 
						|
public:
 | 
						|
  static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsAConstant;
 | 
						|
  static constexpr const char *pyClassName = "AffineConstantExpr";
 | 
						|
  using PyConcreteAffineExpr::PyConcreteAffineExpr;
 | 
						|
 | 
						|
  static PyAffineConstantExpr get(intptr_t value,
 | 
						|
                                  DefaultingPyMlirContext context) {
 | 
						|
    MlirAffineExpr affineExpr =
 | 
						|
        mlirAffineConstantExprGet(context->get(), static_cast<int64_t>(value));
 | 
						|
    return PyAffineConstantExpr(context->getRef(), affineExpr);
 | 
						|
  }
 | 
						|
 | 
						|
  static void bindDerived(ClassTy &c) {
 | 
						|
    c.def_static("get", &PyAffineConstantExpr::get, py::arg("value"),
 | 
						|
                 py::arg("context") = py::none());
 | 
						|
    c.def_property_readonly("value", [](PyAffineConstantExpr &self) {
 | 
						|
      return mlirAffineConstantExprGetValue(self);
 | 
						|
    });
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class PyAffineDimExpr : public PyConcreteAffineExpr<PyAffineDimExpr> {
 | 
						|
public:
 | 
						|
  static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsADim;
 | 
						|
  static constexpr const char *pyClassName = "AffineDimExpr";
 | 
						|
  using PyConcreteAffineExpr::PyConcreteAffineExpr;
 | 
						|
 | 
						|
  static PyAffineDimExpr get(intptr_t pos, DefaultingPyMlirContext context) {
 | 
						|
    MlirAffineExpr affineExpr = mlirAffineDimExprGet(context->get(), pos);
 | 
						|
    return PyAffineDimExpr(context->getRef(), affineExpr);
 | 
						|
  }
 | 
						|
 | 
						|
  static void bindDerived(ClassTy &c) {
 | 
						|
    c.def_static("get", &PyAffineDimExpr::get, py::arg("position"),
 | 
						|
                 py::arg("context") = py::none());
 | 
						|
    c.def_property_readonly("position", [](PyAffineDimExpr &self) {
 | 
						|
      return mlirAffineDimExprGetPosition(self);
 | 
						|
    });
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class PyAffineSymbolExpr : public PyConcreteAffineExpr<PyAffineSymbolExpr> {
 | 
						|
public:
 | 
						|
  static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsASymbol;
 | 
						|
  static constexpr const char *pyClassName = "AffineSymbolExpr";
 | 
						|
  using PyConcreteAffineExpr::PyConcreteAffineExpr;
 | 
						|
 | 
						|
  static PyAffineSymbolExpr get(intptr_t pos, DefaultingPyMlirContext context) {
 | 
						|
    MlirAffineExpr affineExpr = mlirAffineSymbolExprGet(context->get(), pos);
 | 
						|
    return PyAffineSymbolExpr(context->getRef(), affineExpr);
 | 
						|
  }
 | 
						|
 | 
						|
  static void bindDerived(ClassTy &c) {
 | 
						|
    c.def_static("get", &PyAffineSymbolExpr::get, py::arg("position"),
 | 
						|
                 py::arg("context") = py::none());
 | 
						|
    c.def_property_readonly("position", [](PyAffineSymbolExpr &self) {
 | 
						|
      return mlirAffineSymbolExprGetPosition(self);
 | 
						|
    });
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class PyAffineBinaryExpr : public PyConcreteAffineExpr<PyAffineBinaryExpr> {
 | 
						|
public:
 | 
						|
  static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsABinary;
 | 
						|
  static constexpr const char *pyClassName = "AffineBinaryExpr";
 | 
						|
  using PyConcreteAffineExpr::PyConcreteAffineExpr;
 | 
						|
 | 
						|
  PyAffineExpr lhs() {
 | 
						|
    MlirAffineExpr lhsExpr = mlirAffineBinaryOpExprGetLHS(get());
 | 
						|
    return PyAffineExpr(getContext(), lhsExpr);
 | 
						|
  }
 | 
						|
 | 
						|
  PyAffineExpr rhs() {
 | 
						|
    MlirAffineExpr rhsExpr = mlirAffineBinaryOpExprGetRHS(get());
 | 
						|
    return PyAffineExpr(getContext(), rhsExpr);
 | 
						|
  }
 | 
						|
 | 
						|
  static void bindDerived(ClassTy &c) {
 | 
						|
    c.def_property_readonly("lhs", &PyAffineBinaryExpr::lhs);
 | 
						|
    c.def_property_readonly("rhs", &PyAffineBinaryExpr::rhs);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class PyAffineAddExpr
 | 
						|
    : public PyConcreteAffineExpr<PyAffineAddExpr, PyAffineBinaryExpr> {
 | 
						|
public:
 | 
						|
  static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsAAdd;
 | 
						|
  static constexpr const char *pyClassName = "AffineAddExpr";
 | 
						|
  using PyConcreteAffineExpr::PyConcreteAffineExpr;
 | 
						|
 | 
						|
  static PyAffineAddExpr get(PyAffineExpr lhs, PyAffineExpr rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineAddExprGet(lhs, rhs);
 | 
						|
    return PyAffineAddExpr(lhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static PyAffineAddExpr getRHSConstant(PyAffineExpr lhs, intptr_t rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineAddExprGet(
 | 
						|
        lhs, mlirAffineConstantExprGet(mlirAffineExprGetContext(lhs), rhs));
 | 
						|
    return PyAffineAddExpr(lhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static PyAffineAddExpr getLHSConstant(intptr_t lhs, PyAffineExpr rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineAddExprGet(
 | 
						|
        mlirAffineConstantExprGet(mlirAffineExprGetContext(rhs), lhs), rhs);
 | 
						|
    return PyAffineAddExpr(rhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static void bindDerived(ClassTy &c) {
 | 
						|
    c.def_static("get", &PyAffineAddExpr::get);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class PyAffineMulExpr
 | 
						|
    : public PyConcreteAffineExpr<PyAffineMulExpr, PyAffineBinaryExpr> {
 | 
						|
public:
 | 
						|
  static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsAMul;
 | 
						|
  static constexpr const char *pyClassName = "AffineMulExpr";
 | 
						|
  using PyConcreteAffineExpr::PyConcreteAffineExpr;
 | 
						|
 | 
						|
  static PyAffineMulExpr get(PyAffineExpr lhs, PyAffineExpr rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineMulExprGet(lhs, rhs);
 | 
						|
    return PyAffineMulExpr(lhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static PyAffineMulExpr getRHSConstant(PyAffineExpr lhs, intptr_t rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineMulExprGet(
 | 
						|
        lhs, mlirAffineConstantExprGet(mlirAffineExprGetContext(lhs), rhs));
 | 
						|
    return PyAffineMulExpr(lhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static PyAffineMulExpr getLHSConstant(intptr_t lhs, PyAffineExpr rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineMulExprGet(
 | 
						|
        mlirAffineConstantExprGet(mlirAffineExprGetContext(rhs), lhs), rhs);
 | 
						|
    return PyAffineMulExpr(rhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static void bindDerived(ClassTy &c) {
 | 
						|
    c.def_static("get", &PyAffineMulExpr::get);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class PyAffineModExpr
 | 
						|
    : public PyConcreteAffineExpr<PyAffineModExpr, PyAffineBinaryExpr> {
 | 
						|
public:
 | 
						|
  static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsAMod;
 | 
						|
  static constexpr const char *pyClassName = "AffineModExpr";
 | 
						|
  using PyConcreteAffineExpr::PyConcreteAffineExpr;
 | 
						|
 | 
						|
  static PyAffineModExpr get(PyAffineExpr lhs, PyAffineExpr rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineModExprGet(lhs, rhs);
 | 
						|
    return PyAffineModExpr(lhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static PyAffineModExpr getRHSConstant(PyAffineExpr lhs, intptr_t rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineModExprGet(
 | 
						|
        lhs, mlirAffineConstantExprGet(mlirAffineExprGetContext(lhs), rhs));
 | 
						|
    return PyAffineModExpr(lhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static PyAffineModExpr getLHSConstant(intptr_t lhs, PyAffineExpr rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineModExprGet(
 | 
						|
        mlirAffineConstantExprGet(mlirAffineExprGetContext(rhs), lhs), rhs);
 | 
						|
    return PyAffineModExpr(rhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static void bindDerived(ClassTy &c) {
 | 
						|
    c.def_static("get", &PyAffineModExpr::get);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class PyAffineFloorDivExpr
 | 
						|
    : public PyConcreteAffineExpr<PyAffineFloorDivExpr, PyAffineBinaryExpr> {
 | 
						|
public:
 | 
						|
  static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsAFloorDiv;
 | 
						|
  static constexpr const char *pyClassName = "AffineFloorDivExpr";
 | 
						|
  using PyConcreteAffineExpr::PyConcreteAffineExpr;
 | 
						|
 | 
						|
  static PyAffineFloorDivExpr get(PyAffineExpr lhs, PyAffineExpr rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineFloorDivExprGet(lhs, rhs);
 | 
						|
    return PyAffineFloorDivExpr(lhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static PyAffineFloorDivExpr getRHSConstant(PyAffineExpr lhs, intptr_t rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineFloorDivExprGet(
 | 
						|
        lhs, mlirAffineConstantExprGet(mlirAffineExprGetContext(lhs), rhs));
 | 
						|
    return PyAffineFloorDivExpr(lhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static PyAffineFloorDivExpr getLHSConstant(intptr_t lhs, PyAffineExpr rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineFloorDivExprGet(
 | 
						|
        mlirAffineConstantExprGet(mlirAffineExprGetContext(rhs), lhs), rhs);
 | 
						|
    return PyAffineFloorDivExpr(rhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static void bindDerived(ClassTy &c) {
 | 
						|
    c.def_static("get", &PyAffineFloorDivExpr::get);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class PyAffineCeilDivExpr
 | 
						|
    : public PyConcreteAffineExpr<PyAffineCeilDivExpr, PyAffineBinaryExpr> {
 | 
						|
public:
 | 
						|
  static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsACeilDiv;
 | 
						|
  static constexpr const char *pyClassName = "AffineCeilDivExpr";
 | 
						|
  using PyConcreteAffineExpr::PyConcreteAffineExpr;
 | 
						|
 | 
						|
  static PyAffineCeilDivExpr get(PyAffineExpr lhs, PyAffineExpr rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineCeilDivExprGet(lhs, rhs);
 | 
						|
    return PyAffineCeilDivExpr(lhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static PyAffineCeilDivExpr getRHSConstant(PyAffineExpr lhs, intptr_t rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineCeilDivExprGet(
 | 
						|
        lhs, mlirAffineConstantExprGet(mlirAffineExprGetContext(lhs), rhs));
 | 
						|
    return PyAffineCeilDivExpr(lhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static PyAffineCeilDivExpr getLHSConstant(intptr_t lhs, PyAffineExpr rhs) {
 | 
						|
    MlirAffineExpr expr = mlirAffineCeilDivExprGet(
 | 
						|
        mlirAffineConstantExprGet(mlirAffineExprGetContext(rhs), lhs), rhs);
 | 
						|
    return PyAffineCeilDivExpr(rhs.getContext(), expr);
 | 
						|
  }
 | 
						|
 | 
						|
  static void bindDerived(ClassTy &c) {
 | 
						|
    c.def_static("get", &PyAffineCeilDivExpr::get);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
} // namespace
 | 
						|
 | 
						|
bool PyAffineExpr::operator==(const PyAffineExpr &other) {
 | 
						|
  return mlirAffineExprEqual(affineExpr, other.affineExpr);
 | 
						|
}
 | 
						|
 | 
						|
py::object PyAffineExpr::getCapsule() {
 | 
						|
  return py::reinterpret_steal<py::object>(
 | 
						|
      mlirPythonAffineExprToCapsule(*this));
 | 
						|
}
 | 
						|
 | 
						|
PyAffineExpr PyAffineExpr::createFromCapsule(py::object capsule) {
 | 
						|
  MlirAffineExpr rawAffineExpr = mlirPythonCapsuleToAffineExpr(capsule.ptr());
 | 
						|
  if (mlirAffineExprIsNull(rawAffineExpr))
 | 
						|
    throw py::error_already_set();
 | 
						|
  return PyAffineExpr(
 | 
						|
      PyMlirContext::forContext(mlirAffineExprGetContext(rawAffineExpr)),
 | 
						|
      rawAffineExpr);
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
// PyAffineMap and utilities.
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
namespace {
 | 
						|
 | 
						|
/// A list of expressions contained in an affine map. Internally these are
 | 
						|
/// stored as a consecutive array leading to inexpensive random access. Both
 | 
						|
/// the map and the expression are owned by the context so we need not bother
 | 
						|
/// with lifetime extension.
 | 
						|
class PyAffineMapExprList
 | 
						|
    : public Sliceable<PyAffineMapExprList, PyAffineExpr> {
 | 
						|
public:
 | 
						|
  static constexpr const char *pyClassName = "AffineExprList";
 | 
						|
 | 
						|
  PyAffineMapExprList(PyAffineMap map, intptr_t startIndex = 0,
 | 
						|
                      intptr_t length = -1, intptr_t step = 1)
 | 
						|
      : Sliceable(startIndex,
 | 
						|
                  length == -1 ? mlirAffineMapGetNumResults(map) : length,
 | 
						|
                  step),
 | 
						|
        affineMap(map) {}
 | 
						|
 | 
						|
  intptr_t getNumElements() { return mlirAffineMapGetNumResults(affineMap); }
 | 
						|
 | 
						|
  PyAffineExpr getElement(intptr_t pos) {
 | 
						|
    return PyAffineExpr(affineMap.getContext(),
 | 
						|
                        mlirAffineMapGetResult(affineMap, pos));
 | 
						|
  }
 | 
						|
 | 
						|
  PyAffineMapExprList slice(intptr_t startIndex, intptr_t length,
 | 
						|
                            intptr_t step) {
 | 
						|
    return PyAffineMapExprList(affineMap, startIndex, length, step);
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  PyAffineMap affineMap;
 | 
						|
};
 | 
						|
} // namespace
 | 
						|
 | 
						|
bool PyAffineMap::operator==(const PyAffineMap &other) {
 | 
						|
  return mlirAffineMapEqual(affineMap, other.affineMap);
 | 
						|
}
 | 
						|
 | 
						|
py::object PyAffineMap::getCapsule() {
 | 
						|
  return py::reinterpret_steal<py::object>(mlirPythonAffineMapToCapsule(*this));
 | 
						|
}
 | 
						|
 | 
						|
PyAffineMap PyAffineMap::createFromCapsule(py::object capsule) {
 | 
						|
  MlirAffineMap rawAffineMap = mlirPythonCapsuleToAffineMap(capsule.ptr());
 | 
						|
  if (mlirAffineMapIsNull(rawAffineMap))
 | 
						|
    throw py::error_already_set();
 | 
						|
  return PyAffineMap(
 | 
						|
      PyMlirContext::forContext(mlirAffineMapGetContext(rawAffineMap)),
 | 
						|
      rawAffineMap);
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
// PyIntegerSet and utilities.
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
namespace {
 | 
						|
 | 
						|
class PyIntegerSetConstraint {
 | 
						|
public:
 | 
						|
  PyIntegerSetConstraint(PyIntegerSet set, intptr_t pos) : set(set), pos(pos) {}
 | 
						|
 | 
						|
  PyAffineExpr getExpr() {
 | 
						|
    return PyAffineExpr(set.getContext(),
 | 
						|
                        mlirIntegerSetGetConstraint(set, pos));
 | 
						|
  }
 | 
						|
 | 
						|
  bool isEq() { return mlirIntegerSetIsConstraintEq(set, pos); }
 | 
						|
 | 
						|
  static void bind(py::module &m) {
 | 
						|
    py::class_<PyIntegerSetConstraint>(m, "IntegerSetConstraint",
 | 
						|
                                       py::module_local())
 | 
						|
        .def_property_readonly("expr", &PyIntegerSetConstraint::getExpr)
 | 
						|
        .def_property_readonly("is_eq", &PyIntegerSetConstraint::isEq);
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  PyIntegerSet set;
 | 
						|
  intptr_t pos;
 | 
						|
};
 | 
						|
 | 
						|
class PyIntegerSetConstraintList
 | 
						|
    : public Sliceable<PyIntegerSetConstraintList, PyIntegerSetConstraint> {
 | 
						|
public:
 | 
						|
  static constexpr const char *pyClassName = "IntegerSetConstraintList";
 | 
						|
 | 
						|
  PyIntegerSetConstraintList(PyIntegerSet set, intptr_t startIndex = 0,
 | 
						|
                             intptr_t length = -1, intptr_t step = 1)
 | 
						|
      : Sliceable(startIndex,
 | 
						|
                  length == -1 ? mlirIntegerSetGetNumConstraints(set) : length,
 | 
						|
                  step),
 | 
						|
        set(set) {}
 | 
						|
 | 
						|
  intptr_t getNumElements() { return mlirIntegerSetGetNumConstraints(set); }
 | 
						|
 | 
						|
  PyIntegerSetConstraint getElement(intptr_t pos) {
 | 
						|
    return PyIntegerSetConstraint(set, pos);
 | 
						|
  }
 | 
						|
 | 
						|
  PyIntegerSetConstraintList slice(intptr_t startIndex, intptr_t length,
 | 
						|
                                   intptr_t step) {
 | 
						|
    return PyIntegerSetConstraintList(set, startIndex, length, step);
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  PyIntegerSet set;
 | 
						|
};
 | 
						|
} // namespace
 | 
						|
 | 
						|
bool PyIntegerSet::operator==(const PyIntegerSet &other) {
 | 
						|
  return mlirIntegerSetEqual(integerSet, other.integerSet);
 | 
						|
}
 | 
						|
 | 
						|
py::object PyIntegerSet::getCapsule() {
 | 
						|
  return py::reinterpret_steal<py::object>(
 | 
						|
      mlirPythonIntegerSetToCapsule(*this));
 | 
						|
}
 | 
						|
 | 
						|
PyIntegerSet PyIntegerSet::createFromCapsule(py::object capsule) {
 | 
						|
  MlirIntegerSet rawIntegerSet = mlirPythonCapsuleToIntegerSet(capsule.ptr());
 | 
						|
  if (mlirIntegerSetIsNull(rawIntegerSet))
 | 
						|
    throw py::error_already_set();
 | 
						|
  return PyIntegerSet(
 | 
						|
      PyMlirContext::forContext(mlirIntegerSetGetContext(rawIntegerSet)),
 | 
						|
      rawIntegerSet);
 | 
						|
}
 | 
						|
 | 
						|
void mlir::python::populateIRAffine(py::module &m) {
 | 
						|
  //----------------------------------------------------------------------------
 | 
						|
  // Mapping of PyAffineExpr and derived classes.
 | 
						|
  //----------------------------------------------------------------------------
 | 
						|
  py::class_<PyAffineExpr>(m, "AffineExpr", py::module_local())
 | 
						|
      .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR,
 | 
						|
                             &PyAffineExpr::getCapsule)
 | 
						|
      .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyAffineExpr::createFromCapsule)
 | 
						|
      .def("__add__", &PyAffineAddExpr::get)
 | 
						|
      .def("__add__", &PyAffineAddExpr::getRHSConstant)
 | 
						|
      .def("__radd__", &PyAffineAddExpr::getRHSConstant)
 | 
						|
      .def("__mul__", &PyAffineMulExpr::get)
 | 
						|
      .def("__mul__", &PyAffineMulExpr::getRHSConstant)
 | 
						|
      .def("__rmul__", &PyAffineMulExpr::getRHSConstant)
 | 
						|
      .def("__mod__", &PyAffineModExpr::get)
 | 
						|
      .def("__mod__", &PyAffineModExpr::getRHSConstant)
 | 
						|
      .def("__rmod__",
 | 
						|
           [](PyAffineExpr &self, intptr_t other) {
 | 
						|
             return PyAffineModExpr::get(
 | 
						|
                 PyAffineConstantExpr::get(other, *self.getContext().get()),
 | 
						|
                 self);
 | 
						|
           })
 | 
						|
      .def("__sub__",
 | 
						|
           [](PyAffineExpr &self, PyAffineExpr &other) {
 | 
						|
             auto negOne =
 | 
						|
                 PyAffineConstantExpr::get(-1, *self.getContext().get());
 | 
						|
             return PyAffineAddExpr::get(self,
 | 
						|
                                         PyAffineMulExpr::get(negOne, other));
 | 
						|
           })
 | 
						|
      .def("__sub__",
 | 
						|
           [](PyAffineExpr &self, intptr_t other) {
 | 
						|
             return PyAffineAddExpr::get(
 | 
						|
                 self,
 | 
						|
                 PyAffineConstantExpr::get(-other, *self.getContext().get()));
 | 
						|
           })
 | 
						|
      .def("__rsub__",
 | 
						|
           [](PyAffineExpr &self, intptr_t other) {
 | 
						|
             return PyAffineAddExpr::getLHSConstant(
 | 
						|
                 other, PyAffineMulExpr::getLHSConstant(-1, self));
 | 
						|
           })
 | 
						|
      .def("__eq__", [](PyAffineExpr &self,
 | 
						|
                        PyAffineExpr &other) { return self == other; })
 | 
						|
      .def("__eq__",
 | 
						|
           [](PyAffineExpr &self, py::object &other) { return false; })
 | 
						|
      .def("__str__",
 | 
						|
           [](PyAffineExpr &self) {
 | 
						|
             PyPrintAccumulator printAccum;
 | 
						|
             mlirAffineExprPrint(self, printAccum.getCallback(),
 | 
						|
                                 printAccum.getUserData());
 | 
						|
             return printAccum.join();
 | 
						|
           })
 | 
						|
      .def("__repr__",
 | 
						|
           [](PyAffineExpr &self) {
 | 
						|
             PyPrintAccumulator printAccum;
 | 
						|
             printAccum.parts.append("AffineExpr(");
 | 
						|
             mlirAffineExprPrint(self, printAccum.getCallback(),
 | 
						|
                                 printAccum.getUserData());
 | 
						|
             printAccum.parts.append(")");
 | 
						|
             return printAccum.join();
 | 
						|
           })
 | 
						|
      .def("__hash__",
 | 
						|
           [](PyAffineExpr &self) {
 | 
						|
             return static_cast<size_t>(llvm::hash_value(self.get().ptr));
 | 
						|
           })
 | 
						|
      .def_property_readonly(
 | 
						|
          "context",
 | 
						|
          [](PyAffineExpr &self) { return self.getContext().getObject(); })
 | 
						|
      .def("compose",
 | 
						|
           [](PyAffineExpr &self, PyAffineMap &other) {
 | 
						|
             return PyAffineExpr(self.getContext(),
 | 
						|
                                 mlirAffineExprCompose(self, other));
 | 
						|
           })
 | 
						|
      .def_static(
 | 
						|
          "get_add", &PyAffineAddExpr::get,
 | 
						|
          "Gets an affine expression containing a sum of two expressions.")
 | 
						|
      .def_static("get_add", &PyAffineAddExpr::getLHSConstant,
 | 
						|
                  "Gets an affine expression containing a sum of a constant "
 | 
						|
                  "and another expression.")
 | 
						|
      .def_static("get_add", &PyAffineAddExpr::getRHSConstant,
 | 
						|
                  "Gets an affine expression containing a sum of an expression "
 | 
						|
                  "and a constant.")
 | 
						|
      .def_static(
 | 
						|
          "get_mul", &PyAffineMulExpr::get,
 | 
						|
          "Gets an affine expression containing a product of two expressions.")
 | 
						|
      .def_static("get_mul", &PyAffineMulExpr::getLHSConstant,
 | 
						|
                  "Gets an affine expression containing a product of a "
 | 
						|
                  "constant and another expression.")
 | 
						|
      .def_static("get_mul", &PyAffineMulExpr::getRHSConstant,
 | 
						|
                  "Gets an affine expression containing a product of an "
 | 
						|
                  "expression and a constant.")
 | 
						|
      .def_static("get_mod", &PyAffineModExpr::get,
 | 
						|
                  "Gets an affine expression containing the modulo of dividing "
 | 
						|
                  "one expression by another.")
 | 
						|
      .def_static("get_mod", &PyAffineModExpr::getLHSConstant,
 | 
						|
                  "Gets a semi-affine expression containing the modulo of "
 | 
						|
                  "dividing a constant by an expression.")
 | 
						|
      .def_static("get_mod", &PyAffineModExpr::getRHSConstant,
 | 
						|
                  "Gets an affine expression containing the module of dividing"
 | 
						|
                  "an expression by a constant.")
 | 
						|
      .def_static("get_floor_div", &PyAffineFloorDivExpr::get,
 | 
						|
                  "Gets an affine expression containing the rounded-down "
 | 
						|
                  "result of dividing one expression by another.")
 | 
						|
      .def_static("get_floor_div", &PyAffineFloorDivExpr::getLHSConstant,
 | 
						|
                  "Gets a semi-affine expression containing the rounded-down "
 | 
						|
                  "result of dividing a constant by an expression.")
 | 
						|
      .def_static("get_floor_div", &PyAffineFloorDivExpr::getRHSConstant,
 | 
						|
                  "Gets an affine expression containing the rounded-down "
 | 
						|
                  "result of dividing an expression by a constant.")
 | 
						|
      .def_static("get_ceil_div", &PyAffineCeilDivExpr::get,
 | 
						|
                  "Gets an affine expression containing the rounded-up result "
 | 
						|
                  "of dividing one expression by another.")
 | 
						|
      .def_static("get_ceil_div", &PyAffineCeilDivExpr::getLHSConstant,
 | 
						|
                  "Gets a semi-affine expression containing the rounded-up "
 | 
						|
                  "result of dividing a constant by an expression.")
 | 
						|
      .def_static("get_ceil_div", &PyAffineCeilDivExpr::getRHSConstant,
 | 
						|
                  "Gets an affine expression containing the rounded-up result "
 | 
						|
                  "of dividing an expression by a constant.")
 | 
						|
      .def_static("get_constant", &PyAffineConstantExpr::get, py::arg("value"),
 | 
						|
                  py::arg("context") = py::none(),
 | 
						|
                  "Gets a constant affine expression with the given value.")
 | 
						|
      .def_static(
 | 
						|
          "get_dim", &PyAffineDimExpr::get, py::arg("position"),
 | 
						|
          py::arg("context") = py::none(),
 | 
						|
          "Gets an affine expression of a dimension at the given position.")
 | 
						|
      .def_static(
 | 
						|
          "get_symbol", &PyAffineSymbolExpr::get, py::arg("position"),
 | 
						|
          py::arg("context") = py::none(),
 | 
						|
          "Gets an affine expression of a symbol at the given position.")
 | 
						|
      .def(
 | 
						|
          "dump", [](PyAffineExpr &self) { mlirAffineExprDump(self); },
 | 
						|
          kDumpDocstring);
 | 
						|
  PyAffineConstantExpr::bind(m);
 | 
						|
  PyAffineDimExpr::bind(m);
 | 
						|
  PyAffineSymbolExpr::bind(m);
 | 
						|
  PyAffineBinaryExpr::bind(m);
 | 
						|
  PyAffineAddExpr::bind(m);
 | 
						|
  PyAffineMulExpr::bind(m);
 | 
						|
  PyAffineModExpr::bind(m);
 | 
						|
  PyAffineFloorDivExpr::bind(m);
 | 
						|
  PyAffineCeilDivExpr::bind(m);
 | 
						|
 | 
						|
  //----------------------------------------------------------------------------
 | 
						|
  // Mapping of PyAffineMap.
 | 
						|
  //----------------------------------------------------------------------------
 | 
						|
  py::class_<PyAffineMap>(m, "AffineMap", py::module_local())
 | 
						|
      .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR,
 | 
						|
                             &PyAffineMap::getCapsule)
 | 
						|
      .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyAffineMap::createFromCapsule)
 | 
						|
      .def("__eq__",
 | 
						|
           [](PyAffineMap &self, PyAffineMap &other) { return self == other; })
 | 
						|
      .def("__eq__", [](PyAffineMap &self, py::object &other) { return false; })
 | 
						|
      .def("__str__",
 | 
						|
           [](PyAffineMap &self) {
 | 
						|
             PyPrintAccumulator printAccum;
 | 
						|
             mlirAffineMapPrint(self, printAccum.getCallback(),
 | 
						|
                                printAccum.getUserData());
 | 
						|
             return printAccum.join();
 | 
						|
           })
 | 
						|
      .def("__repr__",
 | 
						|
           [](PyAffineMap &self) {
 | 
						|
             PyPrintAccumulator printAccum;
 | 
						|
             printAccum.parts.append("AffineMap(");
 | 
						|
             mlirAffineMapPrint(self, printAccum.getCallback(),
 | 
						|
                                printAccum.getUserData());
 | 
						|
             printAccum.parts.append(")");
 | 
						|
             return printAccum.join();
 | 
						|
           })
 | 
						|
      .def("__hash__",
 | 
						|
           [](PyAffineMap &self) {
 | 
						|
             return static_cast<size_t>(llvm::hash_value(self.get().ptr));
 | 
						|
           })
 | 
						|
      .def_static("compress_unused_symbols",
 | 
						|
                  [](py::list affineMaps, DefaultingPyMlirContext context) {
 | 
						|
                    SmallVector<MlirAffineMap> maps;
 | 
						|
                    pyListToVector<PyAffineMap, MlirAffineMap>(
 | 
						|
                        affineMaps, maps, "attempting to create an AffineMap");
 | 
						|
                    std::vector<MlirAffineMap> compressed(affineMaps.size());
 | 
						|
                    auto populate = [](void *result, intptr_t idx,
 | 
						|
                                       MlirAffineMap m) {
 | 
						|
                      static_cast<MlirAffineMap *>(result)[idx] = (m);
 | 
						|
                    };
 | 
						|
                    mlirAffineMapCompressUnusedSymbols(
 | 
						|
                        maps.data(), maps.size(), compressed.data(), populate);
 | 
						|
                    std::vector<PyAffineMap> res;
 | 
						|
                    res.reserve(compressed.size());
 | 
						|
                    for (auto m : compressed)
 | 
						|
                      res.push_back(PyAffineMap(context->getRef(), m));
 | 
						|
                    return res;
 | 
						|
                  })
 | 
						|
      .def_property_readonly(
 | 
						|
          "context",
 | 
						|
          [](PyAffineMap &self) { return self.getContext().getObject(); },
 | 
						|
          "Context that owns the Affine Map")
 | 
						|
      .def(
 | 
						|
          "dump", [](PyAffineMap &self) { mlirAffineMapDump(self); },
 | 
						|
          kDumpDocstring)
 | 
						|
      .def_static(
 | 
						|
          "get",
 | 
						|
          [](intptr_t dimCount, intptr_t symbolCount, py::list exprs,
 | 
						|
             DefaultingPyMlirContext context) {
 | 
						|
            SmallVector<MlirAffineExpr> affineExprs;
 | 
						|
            pyListToVector<PyAffineExpr, MlirAffineExpr>(
 | 
						|
                exprs, affineExprs, "attempting to create an AffineMap");
 | 
						|
            MlirAffineMap map =
 | 
						|
                mlirAffineMapGet(context->get(), dimCount, symbolCount,
 | 
						|
                                 affineExprs.size(), affineExprs.data());
 | 
						|
            return PyAffineMap(context->getRef(), map);
 | 
						|
          },
 | 
						|
          py::arg("dim_count"), py::arg("symbol_count"), py::arg("exprs"),
 | 
						|
          py::arg("context") = py::none(),
 | 
						|
          "Gets a map with the given expressions as results.")
 | 
						|
      .def_static(
 | 
						|
          "get_constant",
 | 
						|
          [](intptr_t value, DefaultingPyMlirContext context) {
 | 
						|
            MlirAffineMap affineMap =
 | 
						|
                mlirAffineMapConstantGet(context->get(), value);
 | 
						|
            return PyAffineMap(context->getRef(), affineMap);
 | 
						|
          },
 | 
						|
          py::arg("value"), py::arg("context") = py::none(),
 | 
						|
          "Gets an affine map with a single constant result")
 | 
						|
      .def_static(
 | 
						|
          "get_empty",
 | 
						|
          [](DefaultingPyMlirContext context) {
 | 
						|
            MlirAffineMap affineMap = mlirAffineMapEmptyGet(context->get());
 | 
						|
            return PyAffineMap(context->getRef(), affineMap);
 | 
						|
          },
 | 
						|
          py::arg("context") = py::none(), "Gets an empty affine map.")
 | 
						|
      .def_static(
 | 
						|
          "get_identity",
 | 
						|
          [](intptr_t nDims, DefaultingPyMlirContext context) {
 | 
						|
            MlirAffineMap affineMap =
 | 
						|
                mlirAffineMapMultiDimIdentityGet(context->get(), nDims);
 | 
						|
            return PyAffineMap(context->getRef(), affineMap);
 | 
						|
          },
 | 
						|
          py::arg("n_dims"), py::arg("context") = py::none(),
 | 
						|
          "Gets an identity map with the given number of dimensions.")
 | 
						|
      .def_static(
 | 
						|
          "get_minor_identity",
 | 
						|
          [](intptr_t nDims, intptr_t nResults,
 | 
						|
             DefaultingPyMlirContext context) {
 | 
						|
            MlirAffineMap affineMap =
 | 
						|
                mlirAffineMapMinorIdentityGet(context->get(), nDims, nResults);
 | 
						|
            return PyAffineMap(context->getRef(), affineMap);
 | 
						|
          },
 | 
						|
          py::arg("n_dims"), py::arg("n_results"),
 | 
						|
          py::arg("context") = py::none(),
 | 
						|
          "Gets a minor identity map with the given number of dimensions and "
 | 
						|
          "results.")
 | 
						|
      .def_static(
 | 
						|
          "get_permutation",
 | 
						|
          [](std::vector<unsigned> permutation,
 | 
						|
             DefaultingPyMlirContext context) {
 | 
						|
            if (!isPermutation(permutation))
 | 
						|
              throw py::cast_error("Invalid permutation when attempting to "
 | 
						|
                                   "create an AffineMap");
 | 
						|
            MlirAffineMap affineMap = mlirAffineMapPermutationGet(
 | 
						|
                context->get(), permutation.size(), permutation.data());
 | 
						|
            return PyAffineMap(context->getRef(), affineMap);
 | 
						|
          },
 | 
						|
          py::arg("permutation"), py::arg("context") = py::none(),
 | 
						|
          "Gets an affine map that permutes its inputs.")
 | 
						|
      .def(
 | 
						|
          "get_submap",
 | 
						|
          [](PyAffineMap &self, std::vector<intptr_t> &resultPos) {
 | 
						|
            intptr_t numResults = mlirAffineMapGetNumResults(self);
 | 
						|
            for (intptr_t pos : resultPos) {
 | 
						|
              if (pos < 0 || pos >= numResults)
 | 
						|
                throw py::value_error("result position out of bounds");
 | 
						|
            }
 | 
						|
            MlirAffineMap affineMap = mlirAffineMapGetSubMap(
 | 
						|
                self, resultPos.size(), resultPos.data());
 | 
						|
            return PyAffineMap(self.getContext(), affineMap);
 | 
						|
          },
 | 
						|
          py::arg("result_positions"))
 | 
						|
      .def(
 | 
						|
          "get_major_submap",
 | 
						|
          [](PyAffineMap &self, intptr_t nResults) {
 | 
						|
            if (nResults >= mlirAffineMapGetNumResults(self))
 | 
						|
              throw py::value_error("number of results out of bounds");
 | 
						|
            MlirAffineMap affineMap =
 | 
						|
                mlirAffineMapGetMajorSubMap(self, nResults);
 | 
						|
            return PyAffineMap(self.getContext(), affineMap);
 | 
						|
          },
 | 
						|
          py::arg("n_results"))
 | 
						|
      .def(
 | 
						|
          "get_minor_submap",
 | 
						|
          [](PyAffineMap &self, intptr_t nResults) {
 | 
						|
            if (nResults >= mlirAffineMapGetNumResults(self))
 | 
						|
              throw py::value_error("number of results out of bounds");
 | 
						|
            MlirAffineMap affineMap =
 | 
						|
                mlirAffineMapGetMinorSubMap(self, nResults);
 | 
						|
            return PyAffineMap(self.getContext(), affineMap);
 | 
						|
          },
 | 
						|
          py::arg("n_results"))
 | 
						|
      .def(
 | 
						|
          "replace",
 | 
						|
          [](PyAffineMap &self, PyAffineExpr &expression,
 | 
						|
             PyAffineExpr &replacement, intptr_t numResultDims,
 | 
						|
             intptr_t numResultSyms) {
 | 
						|
            MlirAffineMap affineMap = mlirAffineMapReplace(
 | 
						|
                self, expression, replacement, numResultDims, numResultSyms);
 | 
						|
            return PyAffineMap(self.getContext(), affineMap);
 | 
						|
          },
 | 
						|
          py::arg("expr"), py::arg("replacement"), py::arg("n_result_dims"),
 | 
						|
          py::arg("n_result_syms"))
 | 
						|
      .def_property_readonly(
 | 
						|
          "is_permutation",
 | 
						|
          [](PyAffineMap &self) { return mlirAffineMapIsPermutation(self); })
 | 
						|
      .def_property_readonly("is_projected_permutation",
 | 
						|
                             [](PyAffineMap &self) {
 | 
						|
                               return mlirAffineMapIsProjectedPermutation(self);
 | 
						|
                             })
 | 
						|
      .def_property_readonly(
 | 
						|
          "n_dims",
 | 
						|
          [](PyAffineMap &self) { return mlirAffineMapGetNumDims(self); })
 | 
						|
      .def_property_readonly(
 | 
						|
          "n_inputs",
 | 
						|
          [](PyAffineMap &self) { return mlirAffineMapGetNumInputs(self); })
 | 
						|
      .def_property_readonly(
 | 
						|
          "n_symbols",
 | 
						|
          [](PyAffineMap &self) { return mlirAffineMapGetNumSymbols(self); })
 | 
						|
      .def_property_readonly("results", [](PyAffineMap &self) {
 | 
						|
        return PyAffineMapExprList(self);
 | 
						|
      });
 | 
						|
  PyAffineMapExprList::bind(m);
 | 
						|
 | 
						|
  //----------------------------------------------------------------------------
 | 
						|
  // Mapping of PyIntegerSet.
 | 
						|
  //----------------------------------------------------------------------------
 | 
						|
  py::class_<PyIntegerSet>(m, "IntegerSet", py::module_local())
 | 
						|
      .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR,
 | 
						|
                             &PyIntegerSet::getCapsule)
 | 
						|
      .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyIntegerSet::createFromCapsule)
 | 
						|
      .def("__eq__", [](PyIntegerSet &self,
 | 
						|
                        PyIntegerSet &other) { return self == other; })
 | 
						|
      .def("__eq__", [](PyIntegerSet &self, py::object other) { return false; })
 | 
						|
      .def("__str__",
 | 
						|
           [](PyIntegerSet &self) {
 | 
						|
             PyPrintAccumulator printAccum;
 | 
						|
             mlirIntegerSetPrint(self, printAccum.getCallback(),
 | 
						|
                                 printAccum.getUserData());
 | 
						|
             return printAccum.join();
 | 
						|
           })
 | 
						|
      .def("__repr__",
 | 
						|
           [](PyIntegerSet &self) {
 | 
						|
             PyPrintAccumulator printAccum;
 | 
						|
             printAccum.parts.append("IntegerSet(");
 | 
						|
             mlirIntegerSetPrint(self, printAccum.getCallback(),
 | 
						|
                                 printAccum.getUserData());
 | 
						|
             printAccum.parts.append(")");
 | 
						|
             return printAccum.join();
 | 
						|
           })
 | 
						|
      .def("__hash__",
 | 
						|
           [](PyIntegerSet &self) {
 | 
						|
             return static_cast<size_t>(llvm::hash_value(self.get().ptr));
 | 
						|
           })
 | 
						|
      .def_property_readonly(
 | 
						|
          "context",
 | 
						|
          [](PyIntegerSet &self) { return self.getContext().getObject(); })
 | 
						|
      .def(
 | 
						|
          "dump", [](PyIntegerSet &self) { mlirIntegerSetDump(self); },
 | 
						|
          kDumpDocstring)
 | 
						|
      .def_static(
 | 
						|
          "get",
 | 
						|
          [](intptr_t numDims, intptr_t numSymbols, py::list exprs,
 | 
						|
             std::vector<bool> eqFlags, DefaultingPyMlirContext context) {
 | 
						|
            if (exprs.size() != eqFlags.size())
 | 
						|
              throw py::value_error(
 | 
						|
                  "Expected the number of constraints to match "
 | 
						|
                  "that of equality flags");
 | 
						|
            if (exprs.empty())
 | 
						|
              throw py::value_error("Expected non-empty list of constraints");
 | 
						|
 | 
						|
            // Copy over to a SmallVector because std::vector has a
 | 
						|
            // specialization for booleans that packs data and does not
 | 
						|
            // expose a `bool *`.
 | 
						|
            SmallVector<bool, 8> flags(eqFlags.begin(), eqFlags.end());
 | 
						|
 | 
						|
            SmallVector<MlirAffineExpr> affineExprs;
 | 
						|
            pyListToVector<PyAffineExpr>(exprs, affineExprs,
 | 
						|
                                         "attempting to create an IntegerSet");
 | 
						|
            MlirIntegerSet set = mlirIntegerSetGet(
 | 
						|
                context->get(), numDims, numSymbols, exprs.size(),
 | 
						|
                affineExprs.data(), flags.data());
 | 
						|
            return PyIntegerSet(context->getRef(), set);
 | 
						|
          },
 | 
						|
          py::arg("num_dims"), py::arg("num_symbols"), py::arg("exprs"),
 | 
						|
          py::arg("eq_flags"), py::arg("context") = py::none())
 | 
						|
      .def_static(
 | 
						|
          "get_empty",
 | 
						|
          [](intptr_t numDims, intptr_t numSymbols,
 | 
						|
             DefaultingPyMlirContext context) {
 | 
						|
            MlirIntegerSet set =
 | 
						|
                mlirIntegerSetEmptyGet(context->get(), numDims, numSymbols);
 | 
						|
            return PyIntegerSet(context->getRef(), set);
 | 
						|
          },
 | 
						|
          py::arg("num_dims"), py::arg("num_symbols"),
 | 
						|
          py::arg("context") = py::none())
 | 
						|
      .def(
 | 
						|
          "get_replaced",
 | 
						|
          [](PyIntegerSet &self, py::list dimExprs, py::list symbolExprs,
 | 
						|
             intptr_t numResultDims, intptr_t numResultSymbols) {
 | 
						|
            if (static_cast<intptr_t>(dimExprs.size()) !=
 | 
						|
                mlirIntegerSetGetNumDims(self))
 | 
						|
              throw py::value_error(
 | 
						|
                  "Expected the number of dimension replacement expressions "
 | 
						|
                  "to match that of dimensions");
 | 
						|
            if (static_cast<intptr_t>(symbolExprs.size()) !=
 | 
						|
                mlirIntegerSetGetNumSymbols(self))
 | 
						|
              throw py::value_error(
 | 
						|
                  "Expected the number of symbol replacement expressions "
 | 
						|
                  "to match that of symbols");
 | 
						|
 | 
						|
            SmallVector<MlirAffineExpr> dimAffineExprs, symbolAffineExprs;
 | 
						|
            pyListToVector<PyAffineExpr>(
 | 
						|
                dimExprs, dimAffineExprs,
 | 
						|
                "attempting to create an IntegerSet by replacing dimensions");
 | 
						|
            pyListToVector<PyAffineExpr>(
 | 
						|
                symbolExprs, symbolAffineExprs,
 | 
						|
                "attempting to create an IntegerSet by replacing symbols");
 | 
						|
            MlirIntegerSet set = mlirIntegerSetReplaceGet(
 | 
						|
                self, dimAffineExprs.data(), symbolAffineExprs.data(),
 | 
						|
                numResultDims, numResultSymbols);
 | 
						|
            return PyIntegerSet(self.getContext(), set);
 | 
						|
          },
 | 
						|
          py::arg("dim_exprs"), py::arg("symbol_exprs"),
 | 
						|
          py::arg("num_result_dims"), py::arg("num_result_symbols"))
 | 
						|
      .def_property_readonly("is_canonical_empty",
 | 
						|
                             [](PyIntegerSet &self) {
 | 
						|
                               return mlirIntegerSetIsCanonicalEmpty(self);
 | 
						|
                             })
 | 
						|
      .def_property_readonly(
 | 
						|
          "n_dims",
 | 
						|
          [](PyIntegerSet &self) { return mlirIntegerSetGetNumDims(self); })
 | 
						|
      .def_property_readonly(
 | 
						|
          "n_symbols",
 | 
						|
          [](PyIntegerSet &self) { return mlirIntegerSetGetNumSymbols(self); })
 | 
						|
      .def_property_readonly(
 | 
						|
          "n_inputs",
 | 
						|
          [](PyIntegerSet &self) { return mlirIntegerSetGetNumInputs(self); })
 | 
						|
      .def_property_readonly("n_equalities",
 | 
						|
                             [](PyIntegerSet &self) {
 | 
						|
                               return mlirIntegerSetGetNumEqualities(self);
 | 
						|
                             })
 | 
						|
      .def_property_readonly("n_inequalities",
 | 
						|
                             [](PyIntegerSet &self) {
 | 
						|
                               return mlirIntegerSetGetNumInequalities(self);
 | 
						|
                             })
 | 
						|
      .def_property_readonly("constraints", [](PyIntegerSet &self) {
 | 
						|
        return PyIntegerSetConstraintList(self);
 | 
						|
      });
 | 
						|
  PyIntegerSetConstraint::bind(m);
 | 
						|
  PyIntegerSetConstraintList::bind(m);
 | 
						|
}
 |