[Mlir-commits] [mlir] [MLIR][Affine] Reject affine-loop-unroll-jam on dependence-violating nests (PR #196554)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri May 8 08:42:12 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: Soowon Jeong (swjng)
<details>
<summary>Changes</summary>
## Summary
`mlir::affine::loopUnrollJamByFactor` performs no memory-dependence
legality check. Loops whose distance vector becomes negative-leading
under unroll-and-jam's new iteration order are silently miscompiled
(no diagnostic, no warning). This patch adds a factor-aware gate that
refuses the transformation only when the unroll-jam factor `F` is large
enough to actually reorder the dep.
## Reproducer
```mlir
func.func @<!-- -->stencil(%arr: memref<5x5xi32>) {
affine.for %i = 1 to 5 {
affine.for %j = 0 to 4 {
%v = affine.load %arr[%i - 1, %j + 1] : memref<5x5xi32>
affine.store %v, %arr[%i, %j] : memref<5x5xi32>
}
}
return
}
```
Initialize \`arr[i, j] = 10*i + j\` and run end-to-end via
\`mlir-opt -lower-affine ... | mlir-runner\`:
| Pipeline | Row 2 of output |
| --- | --- |
| no \`-affine-loop-unroll-jam\` | \`[2, 3, 4, 14, 24]\` (correct) |
| \`-affine-loop-unroll-jam=unroll-jam-factor=2\` | \`[11, 12, 13, 14, 24]\` |
| \`unroll-jam-factor=4\` | \`[11, 12, 13, 14, 24]\` (no propagation) |
Reproduces on LLVM 17, LLVM 22, and current \`origin/main\`.
## Why
Unroll-and-jam at factor \`F\` strip-mines the outer loop into
\`F\`-iteration stripes and interchanges the intra-stripe iv with the
inner ivs of the perfectly nested band. For a dependence with outer
distance \`d_outer\` and any inner component \`d_inner_k\`:
- \`d_outer >= F\`: the stripe never spans the dep; the interchange does
not reorder it. Safe.
- \`d_outer == 0\`: the dep is intra-iteration and is preserved by the
jammed body order. Safe.
- \`0 < d_outer < F\` and any \`d_inner_k < 0\`: backward distance after
interchange. **Unsafe**.
## Fix
Inline a dependence walk over the perfectly nested band rooted at
\`forOp\` and apply the factor-aware test above. The check is more
precise than reusing \`isTilingValid\`, which ignores \`F\` and would, for
example, refuse \`(2, -1)\` even at \`F = 2\` where the stripe never spans
the dep.
## Test
Two cases appended to \`mlir/test/Dialect/Affine/unroll-jam.mlir\`
(reusing the existing \`factor=2\` RUN line):
- \`@<!-- -->unroll_jam_illegal_flow_dep_1_neg1\` — \`(1, -1)\` stencil; expects
the loop to remain unchanged.
- \`@<!-- -->unroll_jam_legal_outer_distance_geq_factor\` — \`(2, -1)\` stencil at
\`F = 2\`; expects \`step 2\` (demonstrates the factor-aware precision
win over an \`isTilingValid\`-style check).
\`mlir/test/Dialect/Affine/\` (69 tests) regresses cleanly.
---
Patch is 46.57 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/196554.diff
8 Files Affected:
- (modified) mlir/include/mlir-c/IR.h (+6)
- (modified) mlir/include/mlir/Bindings/Python/IRCore.h (+129)
- (modified) mlir/lib/Bindings/Python/IRCore.cpp (+283-117)
- (modified) mlir/lib/CAPI/IR/IR.cpp (+8)
- (modified) mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp (+41)
- (modified) mlir/test/CAPI/ir.c (+19)
- (modified) mlir/test/Dialect/Affine/unroll-jam.mlir (+40)
- (modified) mlir/test/python/ir/location.py (+104-55)
``````````diff
diff --git a/mlir/include/mlir-c/IR.h b/mlir/include/mlir-c/IR.h
index 8d30051d615f4..fdff79f8b67dd 100644
--- a/mlir/include/mlir-c/IR.h
+++ b/mlir/include/mlir-c/IR.h
@@ -363,6 +363,12 @@ MLIR_CAPI_EXPORTED bool mlirLocationIsAName(MlirLocation location);
/// Creates a location with unknown position owned by the given context.
MLIR_CAPI_EXPORTED MlirLocation mlirLocationUnknownGet(MlirContext context);
+/// TypeID Getter for Unknown.
+MLIR_CAPI_EXPORTED MlirTypeID mlirLocationUnknownGetTypeID(void);
+
+/// Checks whether the given location is an Unknown.
+MLIR_CAPI_EXPORTED bool mlirLocationIsAUnknown(MlirLocation location);
+
/// Gets the context that a location was created with.
MLIR_CAPI_EXPORTED MlirContext mlirLocationGetContext(MlirLocation location);
diff --git a/mlir/include/mlir/Bindings/Python/IRCore.h b/mlir/include/mlir/Bindings/Python/IRCore.h
index b2edcace7298e..0b758d4061d67 100644
--- a/mlir/include/mlir/Bindings/Python/IRCore.h
+++ b/mlir/include/mlir/Bindings/Python/IRCore.h
@@ -337,6 +337,10 @@ class MLIR_PYTHON_API_EXPORTED PyLocation : public BaseContextObject {
/// is taken by calling this function.
static PyLocation createFromCapsule(nanobind::object capsule);
+ /// Returns the most-derived Location subclass registered for this TypeID,
+ /// or self.
+ nanobind::typed<nanobind::object, PyLocation> maybeDownCast();
+
private:
MlirLocation loc;
};
@@ -1164,6 +1168,131 @@ class MLIR_PYTHON_API_EXPORTED PyStringAttribute
static void bindDerived(ClassTy &c);
};
+/// CRTP base class for Python classes that subclass Location and should be
+/// castable from it (i.e. via something like FileLineColLoc(loc)).
+template <typename DerivedTy, typename BaseTy = PyLocation>
+class MLIR_PYTHON_API_EXPORTED PyConcreteLocation : public BaseTy {
+public:
+ // Derived classes must define statics for:
+ // IsAFunctionTy isaFunction
+ // const char *pyClassName
+ using ClassTy = nanobind::class_<DerivedTy, BaseTy>;
+ using IsAFunctionTy = bool (*)(MlirLocation);
+ using GetTypeIDFunctionTy = MlirTypeID (*)();
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction = nullptr;
+ using Base = PyConcreteLocation;
+
+ PyConcreteLocation() = default;
+ PyConcreteLocation(PyMlirContextRef contextRef, MlirLocation loc)
+ : BaseTy(std::move(contextRef), loc) {}
+ PyConcreteLocation(PyLocation &orig)
+ : PyConcreteLocation(orig.getContext(), castFrom(orig)) {}
+
+ static MlirLocation castFrom(PyLocation &orig) {
+ if (!DerivedTy::isaFunction(orig.get())) {
+ auto origRepr =
+ nanobind::cast<std::string>(nanobind::repr(nanobind::cast(orig)));
+ throw nanobind::value_error((std::string("Cannot cast location to ") +
+ DerivedTy::pyClassName + " (from " +
+ origRepr + ")")
+ .c_str());
+ }
+ return orig.get();
+ }
+
+ static void bind(nanobind::module_ &m) {
+ ClassTy cls(m, DerivedTy::pyClassName, nanobind::is_generic());
+ cls.def(nanobind::init<PyLocation &>(), nanobind::keep_alive<0, 1>(),
+ nanobind::arg("cast_from_loc"));
+ cls.def_prop_ro_static("static_typeid", [](nanobind::object & /*class*/) {
+ if (DerivedTy::getTypeIdFunction)
+ return PyTypeID(DerivedTy::getTypeIdFunction());
+ throw nanobind::attribute_error(
+ (DerivedTy::pyClassName + std::string(" has no typeid.")).c_str());
+ });
+ cls.def("__repr__", [](DerivedTy &self) {
+ PyPrintAccumulator printAccum;
+ printAccum.parts.append(DerivedTy::pyClassName);
+ printAccum.parts.append("(");
+ mlirLocationPrint(self, printAccum.getCallback(),
+ printAccum.getUserData());
+ printAccum.parts.append(")");
+ return printAccum.join();
+ });
+ if (DerivedTy::getTypeIdFunction) {
+ PyGlobals::get().registerTypeCaster(
+ DerivedTy::getTypeIdFunction(),
+ nanobind::cast<nanobind::callable>(nanobind::cpp_function(
+ [](PyLocation pyLoc) -> DerivedTy { return pyLoc; })),
+ /*replace*/ true);
+ }
+ DerivedTy::bindDerived(cls);
+ }
+
+ /// Implemented by derived classes to add methods to the Python subclass.
+ static void bindDerived(ClassTy &m) {}
+};
+
+class MLIR_PYTHON_API_EXPORTED PyUnknownLocation
+ : public PyConcreteLocation<PyUnknownLocation> {
+public:
+ static constexpr IsAFunctionTy isaFunction = mlirLocationIsAUnknown;
+ static constexpr const char *pyClassName = "UnknownLoc";
+ using PyConcreteLocation::PyConcreteLocation;
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction =
+ mlirLocationUnknownGetTypeID;
+
+ static void bindDerived(ClassTy &c);
+};
+
+class MLIR_PYTHON_API_EXPORTED PyFileLineColLocation
+ : public PyConcreteLocation<PyFileLineColLocation> {
+public:
+ static constexpr IsAFunctionTy isaFunction = mlirLocationIsAFileLineColRange;
+ static constexpr const char *pyClassName = "FileLineColLoc";
+ using PyConcreteLocation::PyConcreteLocation;
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction =
+ mlirLocationFileLineColRangeGetTypeID;
+
+ static void bindDerived(ClassTy &c);
+};
+
+class MLIR_PYTHON_API_EXPORTED PyNameLocation
+ : public PyConcreteLocation<PyNameLocation> {
+public:
+ static constexpr IsAFunctionTy isaFunction = mlirLocationIsAName;
+ static constexpr const char *pyClassName = "NameLoc";
+ using PyConcreteLocation::PyConcreteLocation;
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction =
+ mlirLocationNameGetTypeID;
+
+ static void bindDerived(ClassTy &c);
+};
+
+class MLIR_PYTHON_API_EXPORTED PyCallSiteLocation
+ : public PyConcreteLocation<PyCallSiteLocation> {
+public:
+ static constexpr IsAFunctionTy isaFunction = mlirLocationIsACallSite;
+ static constexpr const char *pyClassName = "CallSiteLoc";
+ using PyConcreteLocation::PyConcreteLocation;
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction =
+ mlirLocationCallSiteGetTypeID;
+
+ static void bindDerived(ClassTy &c);
+};
+
+class MLIR_PYTHON_API_EXPORTED PyFusedLocation
+ : public PyConcreteLocation<PyFusedLocation> {
+public:
+ static constexpr IsAFunctionTy isaFunction = mlirLocationIsAFused;
+ static constexpr const char *pyClassName = "FusedLoc";
+ using PyConcreteLocation::PyConcreteLocation;
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction =
+ mlirLocationFusedGetTypeID;
+
+ static void bindDerived(ClassTy &c);
+};
+
/// Wrapper around the generic MlirValue.
/// Values are managed completely by the operation that resulted in their
/// definition. For op result value, this is the operation that defines the
diff --git a/mlir/lib/Bindings/Python/IRCore.cpp b/mlir/lib/Bindings/Python/IRCore.cpp
index 0fa84a11f2f35..f92d4c14ceb16 100644
--- a/mlir/lib/Bindings/Python/IRCore.cpp
+++ b/mlir/lib/Bindings/Python/IRCore.cpp
@@ -1888,6 +1888,23 @@ nb::typed<nb::object, PyAttribute> PyAttribute::maybeDownCast() {
return typeCaster.value()(thisObj);
}
+//------------------------------------------------------------------------------
+// PyLocation::maybeDownCast.
+//------------------------------------------------------------------------------
+
+nb::typed<nb::object, PyLocation> PyLocation::maybeDownCast() {
+ MlirAttribute locAttr = mlirLocationGetAttribute(this->get());
+ MlirTypeID mlirTypeID = mlirAttributeGetTypeID(locAttr);
+ assert(!mlirTypeIDIsNull(mlirTypeID) &&
+ "mlirTypeID was expected to be non-null.");
+ std::optional<nb::callable> typeCaster = PyGlobals::get().lookupTypeCaster(
+ mlirTypeID, mlirAttributeGetDialect(locAttr));
+ nb::object thisObj = nb::cast(this, nb::rv_policy::move);
+ if (!typeCaster)
+ return thisObj;
+ return typeCaster.value()(thisObj);
+}
+
//------------------------------------------------------------------------------
// PyNamedAttribute.
//------------------------------------------------------------------------------
@@ -3051,6 +3068,191 @@ void populateRoot(nb::module_ &m) {
"Register a value caster for casting MLIR values to custom user values.");
}
+//------------------------------------------------------------------------------
+// Location subclass bindDerived implementations.
+//------------------------------------------------------------------------------
+
+void PyUnknownLocation::bindDerived(ClassTy &c) {
+ c.def_static(
+ "get",
+ [](DefaultingPyMlirContext context) {
+ return PyUnknownLocation(context->getRef(),
+ mlirLocationUnknownGet(context->get()));
+ },
+ "context"_a = nb::none(),
+ "Gets a Location representing an unknown location.");
+}
+
+void PyFileLineColLocation::bindDerived(ClassTy &c) {
+ c.def_static(
+ "get",
+ [](std::string filename, int line, int col,
+ DefaultingPyMlirContext context) {
+ return PyFileLineColLocation(
+ context->getRef(),
+ mlirLocationFileLineColGet(context->get(),
+ toMlirStringRef(filename), line, col));
+ },
+ "filename"_a, "line"_a, "col"_a, "context"_a = nb::none(),
+ "Gets a FileLineColLoc for a file, line, and column.");
+ c.def_static(
+ "get",
+ [](std::string filename, int startLine, int startCol, int endLine,
+ int endCol, DefaultingPyMlirContext context) {
+ return PyFileLineColLocation(
+ context->getRef(), mlirLocationFileLineColRangeGet(
+ context->get(), toMlirStringRef(filename),
+ startLine, startCol, endLine, endCol));
+ },
+ "filename"_a, "start_line"_a, "start_col"_a, "end_line"_a, "end_col"_a,
+ "context"_a = nb::none(),
+ "Gets a FileLineColLoc spanning a file and line/column range.");
+ c.def_prop_ro(
+ "filename",
+ [](PyFileLineColLocation &self) {
+ return mlirIdentifierStr(
+ mlirLocationFileLineColRangeGetFilename(self.get()));
+ },
+ "Gets the filename from a `FileLineColLoc`.");
+ c.def_prop_ro(
+ "start_line",
+ [](PyFileLineColLocation &self) {
+ return mlirLocationFileLineColRangeGetStartLine(self.get());
+ },
+ "Gets the start line number from a `FileLineColLoc`.");
+ c.def_prop_ro(
+ "start_col",
+ [](PyFileLineColLocation &self) {
+ return mlirLocationFileLineColRangeGetStartColumn(self.get());
+ },
+ "Gets the start column number from a `FileLineColLoc`.");
+ c.def_prop_ro(
+ "end_line",
+ [](PyFileLineColLocation &self) {
+ return mlirLocationFileLineColRangeGetEndLine(self.get());
+ },
+ "Gets the end line number from a `FileLineColLoc`.");
+ c.def_prop_ro(
+ "end_col",
+ [](PyFileLineColLocation &self) {
+ return mlirLocationFileLineColRangeGetEndColumn(self.get());
+ },
+ "Gets the end column number from a `FileLineColLoc`.");
+}
+
+void PyNameLocation::bindDerived(ClassTy &c) {
+ c.def_static(
+ "get",
+ [](std::string name, std::optional<PyLocation> childLoc,
+ DefaultingPyMlirContext context) {
+ return PyNameLocation(
+ context->getRef(),
+ mlirLocationNameGet(context->get(), toMlirStringRef(name),
+ childLoc
+ ? childLoc->get()
+ : mlirLocationUnknownGet(context->get())));
+ },
+ "name"_a, "child_loc"_a = nb::none(), "context"_a = nb::none(),
+ "Gets a NameLoc with an optional child location.");
+ c.def_prop_ro(
+ "name_str",
+ [](PyNameLocation &self) {
+ return mlirIdentifierStr(mlirLocationNameGetName(self.get()));
+ },
+ "Gets the name string from a `NameLoc`.");
+ c.def_prop_ro(
+ "child_loc",
+ [](PyNameLocation &self) {
+ return PyLocation(self.getContext(),
+ mlirLocationNameGetChildLoc(self.get()))
+ .maybeDownCast();
+ },
+ "Gets the child location from a `NameLoc`.");
+}
+
+void PyCallSiteLocation::bindDerived(ClassTy &c) {
+ c.def_static(
+ "get",
+ [](PyLocation callee, const std::vector<PyLocation> &frames,
+ DefaultingPyMlirContext context) {
+ if (frames.empty())
+ throw nb::value_error("No caller frames provided.");
+ MlirLocation caller = frames.back().get();
+ for (size_t index = frames.size() - 1; index-- > 0;) {
+ caller = mlirLocationCallSiteGet(frames[index].get(), caller);
+ }
+ return PyCallSiteLocation(
+ context->getRef(), mlirLocationCallSiteGet(callee.get(), caller));
+ },
+ "callee"_a, "frames"_a, "context"_a = nb::none(),
+ "Gets a CallSiteLoc chaining a callee and one or more caller frames.");
+ c.def_prop_ro(
+ "callee",
+ [](PyCallSiteLocation &self) {
+ return PyLocation(self.getContext(),
+ mlirLocationCallSiteGetCallee(self.get()))
+ .maybeDownCast();
+ },
+ "Gets the callee location from a `CallSiteLoc`.");
+ c.def_prop_ro(
+ "caller",
+ [](PyCallSiteLocation &self) {
+ return PyLocation(self.getContext(),
+ mlirLocationCallSiteGetCaller(self.get()))
+ .maybeDownCast();
+ },
+ "Gets the caller location from a `CallSiteLoc`.");
+}
+
+void PyFusedLocation::bindDerived(ClassTy &c) {
+ c.def_static(
+ "get",
+ [](const std::vector<PyLocation> &pyLocations,
+ std::optional<PyAttribute> metadata, DefaultingPyMlirContext context) {
+ std::vector<MlirLocation> locations;
+ locations.reserve(pyLocations.size());
+ for (const PyLocation &pyLocation : pyLocations)
+ locations.push_back(pyLocation.get());
+ MlirLocation location = mlirLocationFusedGet(
+ context->get(), locations.size(), locations.data(),
+ metadata ? metadata->get() : MlirAttribute{0});
+ // Strict: `Location.fused(...)` handles the collapse case.
+ if (!mlirLocationIsAFused(location))
+ throw nb::value_error(
+ "FusedLoc.get would collapse to a non-fused location; use "
+ "Location.fused(...) for the permissive variant.");
+ return PyFusedLocation(context->getRef(), location);
+ },
+ "locations"_a, "metadata"_a = nb::none(), "context"_a = nb::none(),
+ "Gets a FusedLoc from an array of locations and optional metadata. "
+ "Raises if the fuse would collapse to a non-fused location; use "
+ "`Location.fused(...)` for the permissive variant.");
+ c.def_prop_ro(
+ "locations",
+ [](PyFusedLocation &self) {
+ unsigned numLocations = mlirLocationFusedGetNumLocations(self.get());
+ std::vector<MlirLocation> locations(numLocations);
+ if (numLocations)
+ mlirLocationFusedGetLocations(self.get(), locations.data());
+ std::vector<nb::object> pyLocations;
+ pyLocations.reserve(numLocations);
+ for (unsigned i = 0; i < numLocations; ++i)
+ pyLocations.push_back(
+ PyLocation(self.getContext(), locations[i]).maybeDownCast());
+ return pyLocations;
+ },
+ "Gets the list of locations from a `FusedLoc`.");
+ c.def_prop_ro(
+ "metadata",
+ [](PyFusedLocation &self) -> std::optional<PyAttribute> {
+ MlirAttribute metadata = mlirLocationFusedGetMetadata(self.get());
+ if (mlirAttributeIsNull(metadata))
+ return std::nullopt;
+ return PyAttribute(self.getContext(), metadata);
+ },
+ "Gets the metadata attribute from a `FusedLoc`, or None if absent.");
+}
+
//------------------------------------------------------------------------------
// Populates the core exports of the 'ir' submodule.
//------------------------------------------------------------------------------
@@ -3423,122 +3625,52 @@ void populateIRCore(nb::module_ &m) {
// clang-format on
"Gets the Location bound to the current thread or raises ValueError.")
.def_static(
- "unknown",
- [](DefaultingPyMlirContext context) {
+ "from_attr",
+ [](PyAttribute &attribute, DefaultingPyMlirContext context) {
return PyLocation(context->getRef(),
- mlirLocationUnknownGet(context->get()));
+ mlirLocationFromAttribute(attribute))
+ .maybeDownCast();
},
- "context"_a = nb::none(),
- "Gets a Location representing an unknown location.")
+ "attribute"_a, "context"_a = nb::none(),
+ "Gets a Location from a `LocationAttr`.")
+ // Factory shims kept for backward compatibility; return the concrete
+ // subclass. New code should use the subclass `.get()` directly.
.def_static(
- "callsite",
- [](PyLocation callee, const std::vector<PyLocation> &frames,
- DefaultingPyMlirContext context) {
- if (frames.empty())
- throw nb::value_error("No caller frames provided.");
- MlirLocation caller = frames.back().get();
- for (size_t index = frames.size() - 1; index-- > 0;) {
- caller = mlirLocationCallSiteGet(frames[index].get(), caller);
- }
- return PyLocation(context->getRef(),
- mlirLocationCallSiteGet(callee.get(), caller));
- },
- "callee"_a, "frames"_a, "context"_a = nb::none(),
- "Gets a Location representing a caller and callsite.")
- .def("is_a_callsite", mlirLocationIsACallSite,
- "Returns True if this location is a CallSiteLoc.")
- .def_prop_ro(
- "callee",
- [](PyLocation &self) {
- return PyLocation(self.getContext(),
- mlirLocationCallSiteGetCallee(self));
- },
- "Gets the callee location from a CallSiteLoc.")
- .def_prop_ro(
- "caller",
- [](PyLocation &self) {
- return PyLocation(self.getContext(),
- mlirLocationCallSiteGetCaller(self));
+ "unknown",
+ [](DefaultingPyMlirContext context) {
+ return PyUnknownLocation(context->getRef(),
+ mlirLocationUnknownGet(context->get()));
},
- "Gets the caller location from a CallSiteLoc.")
+ "context"_a = nb::none(), "Alias for `UnknownLoc.get()`.")
.def_static(
"file",
[](std::string filename, int line, int col,
DefaultingPyMlirContext context) {
- return PyLocation(
+ return PyFileLineColLocation(
context->getRef(),
mlirLocationFileLineColGet(
context->get(), toMlirStringRef(filename), line, col));
},
"filename"_a, "line"_a, "col"_a, "context"_a = nb::none(),
- "Gets a Location representing a file, line and column.")
+ "Alias for `FileLineColLoc.get()`.")
.def_static(
"file",
[](std::string filename, int startLine, int startCol, int endLine,
int endCol, DefaultingPyMlirContext context) {
- return PyLocation(context->getRef(),
- mlirLocationFileLineColRangeGet(
- context->get(), toMlirStringRef(filename),
- startLine, startCol, endLine, endCol));
+ return PyFileLineColLocation(
+ context->getRef(),
+ mlirLocationFileLineColRangeGet(
+ context->get(), toMlirStringRef(filename), startLine,
+ startCol, endLine, endCol));
},
"filename"_a, "start_line"_a, "start_col"_a, "end_line"_a,
"end_col"_a, "context"_a = nb::none(),
- "Gets a Location representing a file, line and column range.")
- .def("is_a_file", mlirLocationIsAFileLineColRange,
- "Returns True if this location is a FileLineColLoc.")
- .def_prop_ro(
- "filename",
- [](PyLocation loc) {
- return mlirIdentifierStr(
- mlirLocationFileLineColRangeGetFilename(loc));
- },
- "Gets the...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/196554
More information about the Mlir-commits
mailing list