[Mlir-commits] [mlir] 052d24a - [mlir] Introduce support for parametric side-effects

Alex Zinenko llvmlistbot at llvm.org
Wed Nov 18 01:52:26 PST 2020


Author: Alex Zinenko
Date: 2020-11-18T10:52:17+01:00
New Revision: 052d24af2913e8e2a0183bcab8af9c8c9cad94f1

URL: https://github.com/llvm/llvm-project/commit/052d24af2913e8e2a0183bcab8af9c8c9cad94f1
DIFF: https://github.com/llvm/llvm-project/commit/052d24af2913e8e2a0183bcab8af9c8c9cad94f1.diff

LOG: [mlir] Introduce support for parametric side-effects

The side effect infrastructure is based on the Effect and Resource class
templates, instances of instantiations of which are constructed as
thread-local singletons. With this scheme, it is impossible to further
parameterize either of those, or the EffectInstance class that contains
pointers to an Effect and Resource instances. Such a parameterization is
necessary to express more detailed side effects, e.g. those of a loop or
a function call with affine operations inside where it is possible to
precisely specify the slices of accessed buffers.

Include an additional Attribute to EffectInstance class for further
parameterization. This allows to leverage the dialect-specific
registration and uniquing capabilities of the attribute infrastructure
without requiring Effect or Resource instantiations to be attached to a
dialect themselves.

Split out the generic part of the side effect Tablegen classes into a
separate file to avoid generating built-in MemoryEffect interfaces when
processing any .td file that includes SideEffectInterfaceBase.td.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D91493

Added: 
    mlir/include/mlir/Interfaces/SideEffectInterfaceBase.td
    mlir/test/lib/Dialect/Test/TestInterfaces.cpp
    mlir/test/lib/Dialect/Test/TestInterfaces.h

Modified: 
    mlir/include/mlir/Interfaces/SideEffectInterfaces.h
    mlir/include/mlir/Interfaces/SideEffectInterfaces.td
    mlir/test/IR/test-side-effects.mlir
    mlir/test/lib/Dialect/Test/CMakeLists.txt
    mlir/test/lib/Dialect/Test/TestDialect.cpp
    mlir/test/lib/Dialect/Test/TestDialect.h
    mlir/test/lib/Dialect/Test/TestInterfaces.td
    mlir/test/lib/Dialect/Test/TestOps.td
    mlir/test/lib/IR/TestSideEffects.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Interfaces/SideEffectInterfaceBase.td b/mlir/include/mlir/Interfaces/SideEffectInterfaceBase.td
new file mode 100644
index 000000000000..41b07bcedc35
--- /dev/null
+++ b/mlir/include/mlir/Interfaces/SideEffectInterfaceBase.td
@@ -0,0 +1,166 @@
+//===-- SideEffectInterfaceBase.td - Side Effect Base ------*- tablegen -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains base class definitions for side effect interfaces, i.e.
+// the customizable interfaces that provide information about which effects are
+// applied by an operation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_INTERFACES_SIDEEFFECTS_BASE
+#define MLIR_INTERFACES_SIDEEFFECTS_BASE
+
+include "mlir/IR/OpBase.td"
+
+//===----------------------------------------------------------------------===//
+// Resource Bindings
+//===----------------------------------------------------------------------===//
+
+// A generic resource that can be attached to a general base side effect.
+class Resource<string resourceName> {
+  /// The resource that the associated effect is being applied to.
+  string name = resourceName;
+}
+
+// An intrinsic resource that lives in the ::mlir::SideEffects namespace.
+class IntrinsicResource<string resourceName> :
+  Resource<!strconcat("::mlir::SideEffects::", resourceName)> {
+}
+
+// A link to the DefaultResource class.
+def DefaultResource : IntrinsicResource<"DefaultResource">;
+// A link to the AutomaticAllocationScopeResource class.
+def AutomaticAllocationScopeResource :
+  IntrinsicResource<"AutomaticAllocationScopeResource">;
+
+//===----------------------------------------------------------------------===//
+// EffectOpInterface
+//===----------------------------------------------------------------------===//
+
+// A base interface used to query information about the side effects applied to
+// an operation. This template class takes the name of the derived interface
+// class, as well as the name of the base effect class.
+class EffectOpInterfaceBase<string name, string baseEffect>
+    : OpInterface<name> {
+  let methods = [
+    InterfaceMethod<[{
+        Collects all of the operation's effects into `effects`.
+      }],
+      "void", "getEffects",
+         (ins "SmallVectorImpl<::mlir::SideEffects::EffectInstance<"
+              # baseEffect # ">> &":$effects)
+    >,
+  ];
+
+  let extraClassDeclaration = [{
+    /// Collect all of the effect instances that correspond to the given
+    /// `Effect` and place them in 'effects'.
+    template <typename Effect> void getEffects(
+      SmallVectorImpl<::mlir::SideEffects::EffectInstance<
+                                              }] # baseEffect # [{>> &effects) {
+      getEffects(effects);
+      llvm::erase_if(effects, [&](auto &it) {
+        return !llvm::isa<Effect>(it.getEffect());
+      });
+    }
+
+    /// Returns true if this operation exhibits the given effect.
+    template <typename Effect> bool hasEffect() {
+      SmallVector<SideEffects::EffectInstance<}] # baseEffect # [{>, 4> effects;
+      getEffects(effects);
+      return llvm::any_of(effects, [](const auto &it) {
+        return llvm::isa<Effect>(it.getEffect());
+      });
+    }
+
+    /// Returns true if this operation only has the given effect.
+    template <typename Effect> bool onlyHasEffect() {
+      SmallVector<SideEffects::EffectInstance<}] # baseEffect # [{>, 4> effects;
+      getEffects(effects);
+      return !effects.empty() && llvm::all_of(effects, [](const auto &it) {
+        return isa<Effect>(it.getEffect());
+      });
+    }
+
+    /// Returns true if this operation has no effects.
+    bool hasNoEffect() {
+      SmallVector<::mlir::SideEffects::EffectInstance<}] # baseEffect # [{>, 4> effects;
+      getEffects(effects);
+      return effects.empty();
+    }
+
+    /// Returns true if the given operation has no effects for this interface.
+    static bool hasNoEffect(Operation *op) {
+      if (auto interface = dyn_cast<}] # name # [{>(op))
+        return interface.hasNoEffect();
+      return op->hasTrait<::mlir::OpTrait::HasRecursiveSideEffects>();
+    }
+
+    /// Collect all of the effect instances that operate on the provided value
+    /// and place them in 'effects'.
+    void getEffectsOnValue(::mlir::Value value,
+              llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<
+              }] # baseEffect # [{>> & effects) {
+      getEffects(effects);
+      llvm::erase_if(effects, [&](auto &it) { return it.getValue() != value; });
+    }
+
+    /// Collect all of the effect instances that operate on the provided
+    /// resource and place them in 'effects'.
+    void getEffectsOnValue(::mlir::SideEffects::Resource *resource,
+              llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<
+              }] # baseEffect # [{>> & effects) {
+      getEffects(effects);
+      llvm::erase_if(effects, [&](auto &it) {
+        return it.getResource() != resource;
+      });
+    }
+  }];
+
+  // The base effect name of this interface.
+  string baseEffectName = baseEffect;
+}
+
+// This class is the general base side effect class. This is used by derived
+// effect interfaces to define their effects.
+class SideEffect<EffectOpInterfaceBase interface, string effectName,
+                 Resource resourceReference> : OpVariableDecorator {
+  /// The name of the base effects class.
+  string baseEffectName = interface.baseEffectName;
+
+  /// The parent interface that the effect belongs to.
+  string interfaceTrait = interface.trait;
+
+  /// The cpp namespace of the interface trait.
+  string cppNamespace = interface.cppNamespace;
+
+  /// The derived effect that is being applied.
+  string effect = effectName;
+
+  /// The resource that the effect is being applied to.
+  string resource = resourceReference.name;
+}
+
+// This class is the base used for specifying effects applied to an operation.
+class SideEffectsTraitBase<EffectOpInterfaceBase parentInterface,
+                           list<SideEffect> staticEffects>
+    : OpInterfaceTrait<""> {
+  /// The name of the interface trait to use.
+  let trait = parentInterface.trait;
+
+  /// The cpp namespace of the interface trait.
+  string cppNamespace = parentInterface.cppNamespace;
+
+  /// The name of the base effects class.
+  string baseEffectName = parentInterface.baseEffectName;
+
+  /// The derived effects being applied.
+  list<SideEffect> effects = staticEffects;
+}
+
+#endif // MLIR_INTERFACES_SIDEEFFECTS_BASE

diff  --git a/mlir/include/mlir/Interfaces/SideEffectInterfaces.h b/mlir/include/mlir/Interfaces/SideEffectInterfaces.h
index 181d218838ff..c19f7f4f03ee 100644
--- a/mlir/include/mlir/Interfaces/SideEffectInterfaces.h
+++ b/mlir/include/mlir/Interfaces/SideEffectInterfaces.h
@@ -131,8 +131,9 @@ struct AutomaticAllocationScopeResource
 
 /// This class represents a specific instance of an effect. It contains the
 /// effect being applied, a resource that corresponds to where the effect is
-/// applied, and an optional value(either operand, result, or region entry
-/// argument) that the effect is applied to.
+/// applied, an optional value (either operand, result, or region entry
+/// argument) that the effect is applied to, and an optional parameters
+/// attribute further specifying the details of the effect.
 template <typename EffectT> class EffectInstance {
 public:
   EffectInstance(EffectT *effect, Resource *resource = DefaultResource::get())
@@ -140,6 +141,13 @@ template <typename EffectT> class EffectInstance {
   EffectInstance(EffectT *effect, Value value,
                  Resource *resource = DefaultResource::get())
       : effect(effect), resource(resource), value(value) {}
+  EffectInstance(EffectT *effect, Attribute parameters,
+                 Resource *resource = DefaultResource::get())
+      : effect(effect), resource(resource), parameters(parameters) {}
+  EffectInstance(EffectT *effect, Value value, Attribute parameters,
+                 Resource *resource = DefaultResource::get())
+      : effect(effect), resource(resource), value(value),
+        parameters(parameters) {}
 
   /// Return the effect being applied.
   EffectT *getEffect() const { return effect; }
@@ -151,6 +159,9 @@ template <typename EffectT> class EffectInstance {
   /// Return the resource that the effect applies to.
   Resource *getResource() const { return resource; }
 
+  /// Return the parameters of the effect, if any.
+  Attribute getParameters() const { return parameters; }
+
 private:
   /// The specific effect being applied.
   EffectT *effect;
@@ -160,6 +171,11 @@ template <typename EffectT> class EffectInstance {
 
   /// The value that the effect applies to. This is optionally null.
   Value value;
+
+  /// Additional parameters of the effect instance. An attribute is used for
+  /// type-safe structured storage and context-based uniquing. Concrete effects
+  /// can use this at their convenience. This is optionally null.
+  Attribute parameters;
 };
 } // namespace SideEffects
 

diff  --git a/mlir/include/mlir/Interfaces/SideEffectInterfaces.td b/mlir/include/mlir/Interfaces/SideEffectInterfaces.td
index 4f26cb98a41b..9c4aee895c26 100644
--- a/mlir/include/mlir/Interfaces/SideEffectInterfaces.td
+++ b/mlir/include/mlir/Interfaces/SideEffectInterfaces.td
@@ -1,4 +1,4 @@
-//===-- SideEffectInterfaces.td - Side Effect Interfaces ------------*- tablegen -*-===//
+//===-- SideEffectInterfaces.td - Side Effect Interfaces ---*- tablegen -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -14,153 +14,7 @@
 #ifndef MLIR_INTERFACES_SIDEEFFECTS
 #define MLIR_INTERFACES_SIDEEFFECTS
 
-include "mlir/IR/OpBase.td"
-
-//===----------------------------------------------------------------------===//
-// Resource Bindings
-//===----------------------------------------------------------------------===//
-
-// A generic resource that can be attached to a general base side effect.
-class Resource<string resourceName> {
-  /// The resource that the associated effect is being applied to.
-  string name = resourceName;
-}
-
-// An intrinsic resource that lives in the ::mlir::SideEffects namespace.
-class IntrinsicResource<string resourceName> :
-  Resource<!strconcat("::mlir::SideEffects::", resourceName)> {
-}
-
-// A link to the DefaultResource class.
-def DefaultResource : IntrinsicResource<"DefaultResource">;
-// A link to the AutomaticAllocationScopeResource class.
-def AutomaticAllocationScopeResource :
-  IntrinsicResource<"AutomaticAllocationScopeResource">;
-
-//===----------------------------------------------------------------------===//
-// EffectOpInterface
-//===----------------------------------------------------------------------===//
-
-// A base interface used to query information about the side effects applied to
-// an operation. This template class takes the name of the derived interface
-// class, as well as the name of the base effect class.
-class EffectOpInterfaceBase<string name, string baseEffect>
-    : OpInterface<name> {
-  let methods = [
-    InterfaceMethod<[{
-        Collects all of the operation's effects into `effects`.
-      }],
-      "void", "getEffects",
-         (ins "SmallVectorImpl<::mlir::SideEffects::EffectInstance<"
-              # baseEffect # ">> &":$effects)
-    >,
-  ];
-
-  let extraClassDeclaration = [{
-    /// Collect all of the effect instances that correspond to the given
-    /// `Effect` and place them in 'effects'.
-    template <typename Effect> void getEffects(
-      SmallVectorImpl<::mlir::SideEffects::EffectInstance<
-                                              }] # baseEffect # [{>> &effects) {
-      getEffects(effects);
-      llvm::erase_if(effects, [&](auto &it) {
-        return !llvm::isa<Effect>(it.getEffect());
-      });
-    }
-
-    /// Returns true if this operation exhibits the given effect.
-    template <typename Effect> bool hasEffect() {
-      SmallVector<SideEffects::EffectInstance<}] # baseEffect # [{>, 4> effects;
-      getEffects(effects);
-      return llvm::any_of(effects, [](const auto &it) {
-        return llvm::isa<Effect>(it.getEffect());
-      });
-    }
-
-    /// Returns true if this operation only has the given effect.
-    template <typename Effect> bool onlyHasEffect() {
-      SmallVector<SideEffects::EffectInstance<}] # baseEffect # [{>, 4> effects;
-      getEffects(effects);
-      return !effects.empty() && llvm::all_of(effects, [](const auto &it) {
-        return isa<Effect>(it.getEffect());
-      });
-    }
-
-    /// Returns true if this operation has no effects.
-    bool hasNoEffect() {
-      SmallVector<::mlir::SideEffects::EffectInstance<}] # baseEffect # [{>, 4> effects;
-      getEffects(effects);
-      return effects.empty();
-    }
-
-    /// Returns true if the given operation has no effects for this interface.
-    static bool hasNoEffect(Operation *op) {
-      if (auto interface = dyn_cast<}] # name # [{>(op))
-        return interface.hasNoEffect();
-      return op->hasTrait<::mlir::OpTrait::HasRecursiveSideEffects>();
-    }
-
-    /// Collect all of the effect instances that operate on the provided value
-    /// and place them in 'effects'.
-    void getEffectsOnValue(::mlir::Value value,
-              llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<
-              }] # baseEffect # [{>> & effects) {
-      getEffects(effects);
-      llvm::erase_if(effects, [&](auto &it) { return it.getValue() != value; });
-    }
-
-    /// Collect all of the effect instances that operate on the provided
-    /// resource and place them in 'effects'.
-    void getEffectsOnValue(::mlir::SideEffects::Resource *resource,
-              llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<
-              }] # baseEffect # [{>> & effects) {
-      getEffects(effects);
-      llvm::erase_if(effects, [&](auto &it) {
-        return it.getResource() != resource;
-      });
-    }
-  }];
-
-  // The base effect name of this interface.
-  string baseEffectName = baseEffect;
-}
-
-// This class is the general base side effect class. This is used by derived
-// effect interfaces to define their effects.
-class SideEffect<EffectOpInterfaceBase interface, string effectName,
-                 Resource resourceReference> : OpVariableDecorator {
-  /// The name of the base effects class.
-  string baseEffectName = interface.baseEffectName;
-
-  /// The parent interface that the effect belongs to.
-  string interfaceTrait = interface.trait;
-
-  /// The cpp namespace of the interface trait.
-  string cppNamespace = interface.cppNamespace;
-
-  /// The derived effect that is being applied.
-  string effect = effectName;
-
-  /// The resource that the effect is being applied to.
-  string resource = resourceReference.name;
-}
-
-// This class is the base used for specifying effects applied to an operation.
-class SideEffectsTraitBase<EffectOpInterfaceBase parentInterface,
-                           list<SideEffect> staticEffects>
-    : OpInterfaceTrait<""> {
-  /// The name of the interface trait to use.
-  let trait = parentInterface.trait;
-
-  /// The cpp namespace of the interface trait.
-  string cppNamespace = parentInterface.cppNamespace;
-
-  /// The name of the base effects class.
-  string baseEffectName = parentInterface.baseEffectName;
-
-  /// The derived effects being applied.
-  list<SideEffect> effects = staticEffects;
-}
+include "mlir/Interfaces/SideEffectInterfaceBase.td"
 
 //===----------------------------------------------------------------------===//
 // MemoryEffects

diff  --git a/mlir/test/IR/test-side-effects.mlir b/mlir/test/IR/test-side-effects.mlir
index 6832483ff353..ca2e32c9a768 100644
--- a/mlir/test/IR/test-side-effects.mlir
+++ b/mlir/test/IR/test-side-effects.mlir
@@ -18,3 +18,10 @@
 %3 = "test.side_effect_op"() {effects = [
   {effect="allocate", on_result, test_resource}
 ]} : () -> i32
+
+// No _memory_ effects, but a parametric test effect.
+// expected-remark at +2 {{operation has no memory effects}}
+// expected-remark at +1 {{found a parametric effect with affine_map<(d0, d1) -> (d1, d0)>}}
+%4 = "test.side_effect_op"() {
+  effect_parameter = affine_map<(i, j) -> (j, i)>
+} : () -> i32

diff  --git a/mlir/test/lib/Dialect/Test/CMakeLists.txt b/mlir/test/lib/Dialect/Test/CMakeLists.txt
index d1d84f9ce83a..895b7755029c 100644
--- a/mlir/test/lib/Dialect/Test/CMakeLists.txt
+++ b/mlir/test/lib/Dialect/Test/CMakeLists.txt
@@ -7,6 +7,8 @@ set(LLVM_OPTIONAL_SOURCES
 set(LLVM_TARGET_DEFINITIONS TestInterfaces.td)
 mlir_tablegen(TestTypeInterfaces.h.inc -gen-type-interface-decls)
 mlir_tablegen(TestTypeInterfaces.cpp.inc -gen-type-interface-defs)
+mlir_tablegen(TestOpInterfaces.h.inc -gen-op-interface-decls)
+mlir_tablegen(TestOpInterfaces.cpp.inc -gen-op-interface-defs)
 add_public_tablegen_target(MLIRTestInterfaceIncGen)
 
 set(LLVM_TARGET_DEFINITIONS TestTypeDefs.td)
@@ -29,6 +31,7 @@ add_public_tablegen_target(MLIRTestOpsIncGen)
 # Exclude tests from libMLIR.so
 add_mlir_library(MLIRTestDialect
   TestDialect.cpp
+  TestInterfaces.cpp
   TestPatterns.cpp
   TestTraits.cpp
   TestTypes.cpp

diff  --git a/mlir/test/lib/Dialect/Test/TestDialect.cpp b/mlir/test/lib/Dialect/Test/TestDialect.cpp
index d445644a2435..e71fceb9fa3d 100644
--- a/mlir/test/lib/Dialect/Test/TestDialect.cpp
+++ b/mlir/test/lib/Dialect/Test/TestDialect.cpp
@@ -758,6 +758,15 @@ void SideEffectOp::getEffects(
   }
 }
 
+void SideEffectOp::getEffects(
+    SmallVectorImpl<TestEffects::EffectInstance> &effects) {
+  auto effectsAttr = getAttrOfType<AffineMapAttr>("effect_parameter");
+  if (!effectsAttr)
+    return;
+
+  effects.emplace_back(TestEffects::Concrete::get(), effectsAttr);
+}
+
 //===----------------------------------------------------------------------===//
 // StringAttrPrettyNameOp
 //===----------------------------------------------------------------------===//
@@ -911,6 +920,7 @@ void RegionIfOp::getSuccessorRegions(
 }
 
 #include "TestOpEnums.cpp.inc"
+#include "TestOpInterfaces.cpp.inc"
 #include "TestOpStructs.cpp.inc"
 #include "TestTypeInterfaces.cpp.inc"
 

diff  --git a/mlir/test/lib/Dialect/Test/TestDialect.h b/mlir/test/lib/Dialect/Test/TestDialect.h
index 84ec1fb00d59..28572ec0acaf 100644
--- a/mlir/test/lib/Dialect/Test/TestDialect.h
+++ b/mlir/test/lib/Dialect/Test/TestDialect.h
@@ -14,6 +14,7 @@
 #ifndef MLIR_TESTDIALECT_H
 #define MLIR_TESTDIALECT_H
 
+#include "TestInterfaces.h"
 #include "mlir/Dialect/Traits.h"
 #include "mlir/IR/BuiltinDialect.h"
 #include "mlir/IR/Dialect.h"
@@ -30,7 +31,7 @@
 #include "mlir/Interfaces/SideEffectInterfaces.h"
 
 #include "TestOpEnums.h.inc"
-
+#include "TestOpInterfaces.h.inc"
 #include "TestOpStructs.h.inc"
 #include "TestOpsDialect.h.inc"
 

diff  --git a/mlir/test/lib/Dialect/Test/TestInterfaces.cpp b/mlir/test/lib/Dialect/Test/TestInterfaces.cpp
new file mode 100644
index 000000000000..64ec82ecb24f
--- /dev/null
+++ b/mlir/test/lib/Dialect/Test/TestInterfaces.cpp
@@ -0,0 +1,8 @@
+#include "TestInterfaces.h"
+
+using namespace mlir;
+
+bool mlir::TestEffects::Effect::classof(
+    const mlir::SideEffects::Effect *effect) {
+  return isa<mlir::TestEffects::Concrete>(effect);
+}

diff  --git a/mlir/test/lib/Dialect/Test/TestInterfaces.h b/mlir/test/lib/Dialect/Test/TestInterfaces.h
new file mode 100644
index 000000000000..3239584a9332
--- /dev/null
+++ b/mlir/test/lib/Dialect/Test/TestInterfaces.h
@@ -0,0 +1,37 @@
+//===- TestInterfaces.h - MLIR interfaces for testing -----------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares interfaces for the 'test' dialect that can be used for
+// testing the interface infrastructure.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TEST_LIB_DIALECT_TEST_TESTINTERFACES_H
+#define MLIR_TEST_LIB_DIALECT_TEST_TESTINTERFACES_H
+
+#include "mlir/Interfaces/SideEffectInterfaces.h"
+
+namespace mlir {
+namespace TestEffects {
+struct Effect : public SideEffects::Effect {
+  using SideEffects::Effect::Effect;
+
+  template <typename Derived>
+  using Base = SideEffects::Effect::Base<Derived, Effect>;
+
+  static bool classof(const SideEffects::Effect *effect);
+};
+
+using EffectInstance = SideEffects::EffectInstance<Effect>;
+
+struct Concrete : public Effect::Base<Concrete> {};
+
+} // namespace TestEffects
+} // namespace mlir
+
+#endif // MLIR_TEST_LIB_DIALECT_TEST_TESTINTERFACES_H

diff  --git a/mlir/test/lib/Dialect/Test/TestInterfaces.td b/mlir/test/lib/Dialect/Test/TestInterfaces.td
index 19a779d0a81c..d4c9650e8512 100644
--- a/mlir/test/lib/Dialect/Test/TestInterfaces.td
+++ b/mlir/test/lib/Dialect/Test/TestInterfaces.td
@@ -6,10 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef TEST_INTERFACES
-#define TEST_INTERFACES
+#ifndef MLIR_TEST_DIALECT_TEST_INTERFACES
+#define MLIR_TEST_DIALECT_TEST_INTERFACES
 
 include "mlir/IR/OpBase.td"
+include "mlir/Interfaces/SideEffectInterfaceBase.td"
 
 // A type interface used to test the ODS generation of type interfaces.
 def TestTypeInterface : TypeInterface<"TestTypeInterface"> {
@@ -52,4 +53,18 @@ def TestTypeInterface : TypeInterface<"TestTypeInterface"> {
   }];
 }
 
-#endif // TEST_INTERFACES
+def TestEffectOpInterface
+    : EffectOpInterfaceBase<"TestEffectOpInterface",
+                            "::mlir::TestEffects::Effect"> {
+  let cppNamespace = "::mlir";
+}
+
+class TestEffect<string effectName>
+    : SideEffect<TestEffectOpInterface, effectName, DefaultResource>;
+
+class TestEffects<list<TestEffect> effects = []>
+   : SideEffectsTraitBase<TestEffectOpInterface, effects>;
+
+def TestConcreteEffect : TestEffect<"TestEffects::Concrete">;
+
+#endif // MLIR_TEST_DIALECT_TEST_INTERFACES

diff  --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td
index a1f3246075dd..aef5b5166ae2 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.td
+++ b/mlir/test/lib/Dialect/Test/TestOps.td
@@ -18,6 +18,7 @@ include "mlir/Interfaces/ControlFlowInterfaces.td"
 include "mlir/Interfaces/CopyOpInterface.td"
 include "mlir/Interfaces/InferTypeOpInterface.td"
 include "mlir/Interfaces/SideEffectInterfaces.td"
+include "TestInterfaces.td"
 
 def Test_Dialect : Dialect {
   let name = "test";
@@ -1721,7 +1722,8 @@ def FormatTypesMatchAttrOp : TEST_Op<"format_types_match_attr", [
 //===----------------------------------------------------------------------===//
 
 def SideEffectOp : TEST_Op<"side_effect_op",
-    [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
+    [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
+     DeclareOpInterfaceMethods<TestEffectOpInterface>]> {
   let results = (outs AnyType:$result);
 }
 

diff  --git a/mlir/test/lib/IR/TestSideEffects.cpp b/mlir/test/lib/IR/TestSideEffects.cpp
index 1ac9e82a7f7e..d9d6aed59215 100644
--- a/mlir/test/lib/IR/TestSideEffects.cpp
+++ b/mlir/test/lib/IR/TestSideEffects.cpp
@@ -47,6 +47,20 @@ struct SideEffectsPass
         diag << " on resource '" << instance.getResource()->getName() << "'";
       }
     });
+
+    SmallVector<TestEffects::EffectInstance, 1> testEffects;
+    module.walk([&](TestEffectOpInterface op) {
+      testEffects.clear();
+      op.getEffects(testEffects);
+
+      if (testEffects.empty())
+        return;
+
+      for (const TestEffects::EffectInstance &instance : testEffects) {
+        op.emitRemark() << "found a parametric effect with "
+                        << instance.getParameters();
+      }
+    });
   }
 };
 } // end anonymous namespace


        


More information about the Mlir-commits mailing list