diff --git a/mlir/examples/toy/Ch2/CMakeLists.txt b/mlir/examples/toy/Ch2/CMakeLists.txt --- a/mlir/examples/toy/Ch2/CMakeLists.txt +++ b/mlir/examples/toy/Ch2/CMakeLists.txt @@ -21,4 +21,5 @@ MLIRAnalysis MLIRIR MLIRParser + MLIRSideEffects MLIRTransforms) diff --git a/mlir/examples/toy/Ch2/include/toy/Dialect.h b/mlir/examples/toy/Ch2/include/toy/Dialect.h --- a/mlir/examples/toy/Ch2/include/toy/Dialect.h +++ b/mlir/examples/toy/Ch2/include/toy/Dialect.h @@ -16,6 +16,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/Function.h" +#include "mlir/Interfaces/SideEffects.h" namespace mlir { namespace toy { diff --git a/mlir/examples/toy/Ch3/CMakeLists.txt b/mlir/examples/toy/Ch3/CMakeLists.txt --- a/mlir/examples/toy/Ch3/CMakeLists.txt +++ b/mlir/examples/toy/Ch3/CMakeLists.txt @@ -29,5 +29,6 @@ MLIRIR MLIRParser MLIRPass + MLIRSideEffects MLIRTransforms) diff --git a/mlir/examples/toy/Ch3/include/toy/Dialect.h b/mlir/examples/toy/Ch3/include/toy/Dialect.h --- a/mlir/examples/toy/Ch3/include/toy/Dialect.h +++ b/mlir/examples/toy/Ch3/include/toy/Dialect.h @@ -16,6 +16,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/Function.h" +#include "mlir/Interfaces/SideEffects.h" namespace mlir { namespace toy { diff --git a/mlir/examples/toy/Ch4/CMakeLists.txt b/mlir/examples/toy/Ch4/CMakeLists.txt --- a/mlir/examples/toy/Ch4/CMakeLists.txt +++ b/mlir/examples/toy/Ch4/CMakeLists.txt @@ -32,5 +32,6 @@ MLIRIR MLIRParser MLIRPass + MLIRSideEffects MLIRTransforms) diff --git a/mlir/examples/toy/Ch4/include/toy/Dialect.h b/mlir/examples/toy/Ch4/include/toy/Dialect.h --- a/mlir/examples/toy/Ch4/include/toy/Dialect.h +++ b/mlir/examples/toy/Ch4/include/toy/Dialect.h @@ -17,6 +17,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/Function.h" #include "mlir/IR/StandardTypes.h" +#include "mlir/Interfaces/SideEffects.h" #include "toy/ShapeInferenceInterface.h" namespace mlir { diff --git a/mlir/examples/toy/Ch5/CMakeLists.txt b/mlir/examples/toy/Ch5/CMakeLists.txt --- a/mlir/examples/toy/Ch5/CMakeLists.txt +++ b/mlir/examples/toy/Ch5/CMakeLists.txt @@ -35,5 +35,6 @@ MLIRIR MLIRParser MLIRPass + MLIRSideEffects MLIRSupport MLIRTransforms) diff --git a/mlir/examples/toy/Ch5/include/toy/Dialect.h b/mlir/examples/toy/Ch5/include/toy/Dialect.h --- a/mlir/examples/toy/Ch5/include/toy/Dialect.h +++ b/mlir/examples/toy/Ch5/include/toy/Dialect.h @@ -17,6 +17,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/Function.h" #include "mlir/IR/StandardTypes.h" +#include "mlir/Interfaces/SideEffects.h" #include "toy/ShapeInferenceInterface.h" namespace mlir { diff --git a/mlir/examples/toy/Ch6/CMakeLists.txt b/mlir/examples/toy/Ch6/CMakeLists.txt --- a/mlir/examples/toy/Ch6/CMakeLists.txt +++ b/mlir/examples/toy/Ch6/CMakeLists.txt @@ -41,6 +41,7 @@ MLIRLLVMIR MLIRParser MLIRPass + MLIRSideEffects MLIRSupport MLIRTargetLLVMIR MLIRTransforms diff --git a/mlir/examples/toy/Ch6/include/toy/Dialect.h b/mlir/examples/toy/Ch6/include/toy/Dialect.h --- a/mlir/examples/toy/Ch6/include/toy/Dialect.h +++ b/mlir/examples/toy/Ch6/include/toy/Dialect.h @@ -17,6 +17,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/Function.h" #include "mlir/IR/StandardTypes.h" +#include "mlir/Interfaces/SideEffects.h" #include "toy/ShapeInferenceInterface.h" namespace mlir { diff --git a/mlir/examples/toy/Ch7/CMakeLists.txt b/mlir/examples/toy/Ch7/CMakeLists.txt --- a/mlir/examples/toy/Ch7/CMakeLists.txt +++ b/mlir/examples/toy/Ch7/CMakeLists.txt @@ -40,6 +40,7 @@ MLIRIR MLIRParser MLIRPass + MLIRSideEffects MLIRTargetLLVMIR MLIRTransforms ) diff --git a/mlir/examples/toy/Ch7/include/toy/Dialect.h b/mlir/examples/toy/Ch7/include/toy/Dialect.h --- a/mlir/examples/toy/Ch7/include/toy/Dialect.h +++ b/mlir/examples/toy/Ch7/include/toy/Dialect.h @@ -17,6 +17,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/Function.h" #include "mlir/IR/StandardTypes.h" +#include "mlir/Interfaces/SideEffects.h" #include "toy/ShapeInferenceInterface.h" namespace mlir { diff --git a/mlir/include/mlir/Dialect/AffineOps/AffineOps.h b/mlir/include/mlir/Dialect/AffineOps/AffineOps.h --- a/mlir/include/mlir/Dialect/AffineOps/AffineOps.h +++ b/mlir/include/mlir/Dialect/AffineOps/AffineOps.h @@ -19,6 +19,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/StandardTypes.h" +#include "mlir/Interfaces/SideEffects.h" #include "mlir/Transforms/LoopLikeInterface.h" namespace mlir { diff --git a/mlir/include/mlir/Dialect/FxpMathOps/FxpMathOps.h b/mlir/include/mlir/Dialect/FxpMathOps/FxpMathOps.h --- a/mlir/include/mlir/Dialect/FxpMathOps/FxpMathOps.h +++ b/mlir/include/mlir/Dialect/FxpMathOps/FxpMathOps.h @@ -12,6 +12,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/StandardTypes.h" +#include "mlir/Interfaces/SideEffects.h" namespace mlir { namespace fxpmath { diff --git a/mlir/include/mlir/Dialect/GPU/GPUDialect.h b/mlir/include/mlir/Dialect/GPU/GPUDialect.h --- a/mlir/include/mlir/Dialect/GPU/GPUDialect.h +++ b/mlir/include/mlir/Dialect/GPU/GPUDialect.h @@ -19,6 +19,7 @@ #include "mlir/IR/OpDefinition.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/SymbolTable.h" +#include "mlir/Interfaces/SideEffects.h" namespace mlir { class FuncOp; diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h @@ -21,6 +21,7 @@ #include "mlir/IR/TypeSupport.h" #include "mlir/IR/Types.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" +#include "mlir/Interfaces/SideEffects.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" diff --git a/mlir/include/mlir/Dialect/LLVMIR/NVVMDialect.h b/mlir/include/mlir/Dialect/LLVMIR/NVVMDialect.h --- a/mlir/include/mlir/Dialect/LLVMIR/NVVMDialect.h +++ b/mlir/include/mlir/Dialect/LLVMIR/NVVMDialect.h @@ -16,6 +16,8 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/OpDefinition.h" +#include "mlir/Interfaces/SideEffects.h" + namespace mlir { namespace NVVM { diff --git a/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.h b/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.h --- a/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.h +++ b/mlir/include/mlir/Dialect/LLVMIR/ROCDLDialect.h @@ -24,6 +24,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/OpDefinition.h" +#include "mlir/Interfaces/SideEffects.h" namespace mlir { namespace ROCDL { diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.h b/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.h --- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.h +++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.h @@ -22,6 +22,7 @@ #include "mlir/IR/StandardTypes.h" #include "mlir/IR/TypeUtilities.h" #include "mlir/IR/Types.h" +#include "mlir/Interfaces/SideEffects.h" #include "mlir/Support/LLVM.h" namespace mlir { diff --git a/mlir/include/mlir/Dialect/LoopOps/LoopOps.h b/mlir/include/mlir/Dialect/LoopOps/LoopOps.h --- a/mlir/include/mlir/Dialect/LoopOps/LoopOps.h +++ b/mlir/include/mlir/Dialect/LoopOps/LoopOps.h @@ -17,6 +17,7 @@ #include "mlir/IR/Builders.h" #include "mlir/IR/Dialect.h" #include "mlir/IR/OpDefinition.h" +#include "mlir/Interfaces/SideEffects.h" #include "mlir/Transforms/LoopLikeInterface.h" namespace mlir { diff --git a/mlir/include/mlir/Dialect/QuantOps/QuantOps.h b/mlir/include/mlir/Dialect/QuantOps/QuantOps.h --- a/mlir/include/mlir/Dialect/QuantOps/QuantOps.h +++ b/mlir/include/mlir/Dialect/QuantOps/QuantOps.h @@ -15,6 +15,7 @@ #include "mlir/IR/OpDefinition.h" #include "mlir/IR/StandardTypes.h" #include "mlir/IR/Types.h" +#include "mlir/Interfaces/SideEffects.h" #include "llvm/Support/MathExtras.h" namespace mlir { diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVOps.h b/mlir/include/mlir/Dialect/SPIRV/SPIRVOps.h --- a/mlir/include/mlir/Dialect/SPIRV/SPIRVOps.h +++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVOps.h @@ -16,6 +16,7 @@ #include "mlir/Dialect/SPIRV/SPIRVTypes.h" #include "mlir/IR/Function.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" +#include "mlir/Interfaces/SideEffects.h" #include "llvm/Support/PointerLikeTypeTraits.h" namespace mlir { diff --git a/mlir/include/mlir/Dialect/Shape/IR/Shape.h b/mlir/include/mlir/Dialect/Shape/IR/Shape.h --- a/mlir/include/mlir/Dialect/Shape/IR/Shape.h +++ b/mlir/include/mlir/Dialect/Shape/IR/Shape.h @@ -16,6 +16,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/OpDefinition.h" +#include "mlir/Interfaces/SideEffects.h" namespace mlir { namespace shape { diff --git a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.h b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.h --- a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.h +++ b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.h @@ -20,6 +20,7 @@ #include "mlir/IR/StandardTypes.h" #include "mlir/Interfaces/CallInterfaces.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" +#include "mlir/Interfaces/SideEffects.h" // Pull in all enum type definitions and utility function declarations. #include "mlir/Dialect/StandardOps/IR/OpsEnums.h.inc" diff --git a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td --- a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td +++ b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td @@ -16,7 +16,7 @@ include "mlir/Interfaces/CallInterfaces.td" include "mlir/Interfaces/ControlFlowInterfaces.td" include "mlir/IR/OpAsmInterface.td" -include "mlir/IR/SideEffects.td" +include "mlir/Interfaces/SideEffects.td" def Std_Dialect : Dialect { let name = "std"; diff --git a/mlir/include/mlir/Dialect/VectorOps/VectorOps.h b/mlir/include/mlir/Dialect/VectorOps/VectorOps.h --- a/mlir/include/mlir/Dialect/VectorOps/VectorOps.h +++ b/mlir/include/mlir/Dialect/VectorOps/VectorOps.h @@ -17,6 +17,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/StandardTypes.h" +#include "mlir/Interfaces/SideEffects.h" namespace mlir { class MLIRContext; diff --git a/mlir/include/mlir/IR/CMakeLists.txt b/mlir/include/mlir/IR/CMakeLists.txt --- a/mlir/include/mlir/IR/CMakeLists.txt +++ b/mlir/include/mlir/IR/CMakeLists.txt @@ -2,8 +2,3 @@ mlir_tablegen(OpAsmInterface.h.inc -gen-op-interface-decls) mlir_tablegen(OpAsmInterface.cpp.inc -gen-op-interface-defs) add_public_tablegen_target(MLIROpAsmInterfacesIncGen) - -set(LLVM_TARGET_DEFINITIONS SideEffects.td) -mlir_tablegen(SideEffectInterfaces.h.inc -gen-op-interface-decls) -mlir_tablegen(SideEffectInterfaces.cpp.inc -gen-op-interface-defs) -add_public_tablegen_target(MLIRSideEffectOpInterfacesIncGen) diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h --- a/mlir/include/mlir/IR/OpDefinition.h +++ b/mlir/include/mlir/IR/OpDefinition.h @@ -1278,218 +1278,6 @@ }; //===----------------------------------------------------------------------===// -// Operation Side-Effect Modeling -//===----------------------------------------------------------------------===// - -// TODO(riverriddle) This should be in its own file in a proper -// traits/interfaces directory. Move it there when we have one. - -namespace SideEffects { -//===--------------------------------------------------------------------===// -// Effects - -/// This class represents a base class for a specific effect type. -class Effect { -public: - /// This base class is used for derived effects that are non-parametric. - template - class Base : public BaseEffect { - public: - using BaseT = Base; - - /// Return the unique identifier for the base effects class. - static ClassID *getEffectID() { return ClassID::getID(); } - - /// 'classof' used to support llvm style cast functionality. - static bool classof(const ::mlir::SideEffects::Effect *effect) { - return effect->getEffectID() == BaseT::getEffectID(); - } - - /// Returns a unique instance for the derived effect class. - static DerivedEffect *get() { - return BaseEffect::template get(); - } - using BaseEffect::get; - - protected: - Base() : BaseEffect(BaseT::getEffectID()){}; - }; - - /// Return the unique identifier for the base effects class. - ClassID *getEffectID() const { return id; } - - /// Returns a unique instance for the given effect class. - template static DerivedEffect *get() { - static_assert(std::is_base_of::value, - "expected DerivedEffect to inherit from Effect"); - - static DerivedEffect instance; - return &instance; - } - -protected: - Effect(ClassID *id) : id(id) {} - -private: - /// The id of the derived effect class. - ClassID *id; -}; - -//===--------------------------------------------------------------------===// -// Resources - -/// This class represents a specific resource that an effect applies to. This -/// class represents an abstract interface for a given resource. -class Resource { -public: - virtual ~Resource() {} - - /// This base class is used for derived effects that are non-parametric. - template - class Base : public BaseResource { - public: - using BaseT = Base; - - /// Returns a unique instance for the given effect class. - static DerivedResource *get() { - static DerivedResource instance; - return &instance; - } - - /// Return the unique identifier for the base resource class. - static ClassID *getResourceID() { - return ClassID::getID(); - } - - /// 'classof' used to support llvm style cast functionality. - static bool classof(const Resource *resource) { - return resource->getResourceID() == BaseT::getResourceID(); - } - - protected: - Base() : BaseResource(BaseT::getResourceID()){}; - }; - - /// Return the unique identifier for the base resource class. - ClassID *getResourceID() const { return id; } - - /// Return a string name of the resource. - virtual StringRef getName() = 0; - -protected: - Resource(ClassID *id) : id(id) {} - -private: - /// The id of the derived resource class. - ClassID *id; -}; - -/// A conservative default resource kind. -struct DefaultResource : public Resource::Base { - StringRef getName() final { return ""; } -}; - -/// 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. -template class EffectInstance { -public: - EffectInstance(EffectT *effect, Resource *resource = DefaultResource::get()) - : effect(effect), resource(resource) {} - EffectInstance(EffectT *effect, Value value, - Resource *resource = DefaultResource::get()) - : effect(effect), resource(resource), value(value) {} - - /// Return the effect being applied. - EffectT *getEffect() const { return effect; } - - /// Return the value the effect is applied on, or nullptr if there isn't a - /// known value being affected. - Value getValue() const { return value; } - - /// Return the resource that the effect applies to. - Resource *getResource() const { return resource; } - -private: - /// The specific effect being applied. - EffectT *effect; - - /// The resource that the given value resides in. - Resource *resource; - - /// The value that the effect applies to. This is optionally null. - Value value; -}; -} // namespace SideEffects - -//===----------------------------------------------------------------------===// -// SideEffect Traits - -namespace OpTrait { -/// This trait indicates that an operation never has side effects. -template -class HasNoSideEffect : public TraitBase { -public: - static AbstractOperation::OperationProperties getTraitProperties() { - return static_cast( - OperationProperty::NoSideEffect); - } -}; -/// This trait indicates that the side effects of an operation includes the -/// effects of operations nested within its regions. If the operation has no -/// derived effects interfaces, the operation itself can be assumed to have no -/// side effects. -template -class HasRecursiveSideEffects - : public TraitBase {}; -} // namespace OpTrait - -//===----------------------------------------------------------------------===// -// Operation Memory-Effect Modeling -//===----------------------------------------------------------------------===// - -namespace MemoryEffects { -/// This class represents the base class used for memory effects. -struct Effect : public SideEffects::Effect { - using SideEffects::Effect::Effect; - - /// A base class for memory effects that provides helper utilities. - template - using Base = SideEffects::Effect::Base; - - static bool classof(const SideEffects::Effect *effect); -}; -using EffectInstance = SideEffects::EffectInstance; - -/// The following effect indicates that the operation allocates from some -/// resource. An 'allocate' effect implies only allocation of the resource, and -/// not any visible mutation or dereference. -struct Allocate : public Effect::Base {}; - -/// The following effect indicates that the operation frees some resource that -/// has been allocated. An 'allocate' effect implies only de-allocation of the -/// resource, and not any visible allocation, mutation or dereference. -struct Free : public Effect::Base {}; - -/// The following effect indicates that the operation reads from some resource. -/// A 'read' effect implies only dereferencing of the resource, and not any -/// visible mutation. -struct Read : public Effect::Base {}; - -/// The following effect indicates that the operation writes to some resource. A -/// 'write' effect implies only mutating a resource, and not any visible -/// dereference or read. -struct Write : public Effect::Base {}; -} // namespace MemoryEffects - -//===----------------------------------------------------------------------===// -// SideEffect Interfaces - -/// Include the definitions of the side effect interfaces. -#include "mlir/IR/SideEffectInterfaces.h.inc" - -//===----------------------------------------------------------------------===// // Common Operation Folders/Parsers/Printers //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Interfaces/CMakeLists.txt b/mlir/include/mlir/Interfaces/CMakeLists.txt --- a/mlir/include/mlir/Interfaces/CMakeLists.txt +++ b/mlir/include/mlir/Interfaces/CMakeLists.txt @@ -12,3 +12,8 @@ mlir_tablegen(InferTypeOpInterface.h.inc -gen-op-interface-decls) mlir_tablegen(InferTypeOpInterface.cpp.inc -gen-op-interface-defs) add_public_tablegen_target(MLIRInferTypeOpInterfaceIncGen) + +set(LLVM_TARGET_DEFINITIONS SideEffects.td) +mlir_tablegen(SideEffectInterfaces.h.inc -gen-op-interface-decls) +mlir_tablegen(SideEffectInterfaces.cpp.inc -gen-op-interface-defs) +add_public_tablegen_target(MLIRSideEffectOpInterfacesIncGen) diff --git a/mlir/include/mlir/Interfaces/SideEffects.h b/mlir/include/mlir/Interfaces/SideEffects.h new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Interfaces/SideEffects.h @@ -0,0 +1,230 @@ +//===- SideEffects.h - SideEffect in MLIR -----------------------*- 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 contains traits, interfaces, and utilities for defining and +// querying the side effects of an operation. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_INTERFACES_SIDEEFFECTS_H +#define MLIR_INTERFACES_SIDEEFFECTS_H + +#include "mlir/IR/OpDefinition.h" + +namespace mlir { +namespace SideEffects { +//===----------------------------------------------------------------------===// +// Effects +//===----------------------------------------------------------------------===// + +/// This class represents a base class for a specific effect type. +class Effect { +public: + /// This base class is used for derived effects that are non-parametric. + template + class Base : public BaseEffect { + public: + using BaseT = Base; + + /// Return the unique identifier for the base effects class. + static ClassID *getEffectID() { return ClassID::getID(); } + + /// 'classof' used to support llvm style cast functionality. + static bool classof(const ::mlir::SideEffects::Effect *effect) { + return effect->getEffectID() == BaseT::getEffectID(); + } + + /// Returns a unique instance for the derived effect class. + static DerivedEffect *get() { + return BaseEffect::template get(); + } + using BaseEffect::get; + + protected: + Base() : BaseEffect(BaseT::getEffectID()){}; + }; + + /// Return the unique identifier for the base effects class. + ClassID *getEffectID() const { return id; } + + /// Returns a unique instance for the given effect class. + template static DerivedEffect *get() { + static_assert(std::is_base_of::value, + "expected DerivedEffect to inherit from Effect"); + + static DerivedEffect instance; + return &instance; + } + +protected: + Effect(ClassID *id) : id(id) {} + +private: + /// The id of the derived effect class. + ClassID *id; +}; + +//===----------------------------------------------------------------------===// +// Resources +//===----------------------------------------------------------------------===// + +/// This class represents a specific resource that an effect applies to. This +/// class represents an abstract interface for a given resource. +class Resource { +public: + virtual ~Resource() {} + + /// This base class is used for derived effects that are non-parametric. + template + class Base : public BaseResource { + public: + using BaseT = Base; + + /// Returns a unique instance for the given effect class. + static DerivedResource *get() { + static DerivedResource instance; + return &instance; + } + + /// Return the unique identifier for the base resource class. + static ClassID *getResourceID() { + return ClassID::getID(); + } + + /// 'classof' used to support llvm style cast functionality. + static bool classof(const Resource *resource) { + return resource->getResourceID() == BaseT::getResourceID(); + } + + protected: + Base() : BaseResource(BaseT::getResourceID()){}; + }; + + /// Return the unique identifier for the base resource class. + ClassID *getResourceID() const { return id; } + + /// Return a string name of the resource. + virtual StringRef getName() = 0; + +protected: + Resource(ClassID *id) : id(id) {} + +private: + /// The id of the derived resource class. + ClassID *id; +}; + +/// A conservative default resource kind. +struct DefaultResource : public Resource::Base { + StringRef getName() final { return ""; } +}; + +/// 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. +template class EffectInstance { +public: + EffectInstance(EffectT *effect, Resource *resource = DefaultResource::get()) + : effect(effect), resource(resource) {} + EffectInstance(EffectT *effect, Value value, + Resource *resource = DefaultResource::get()) + : effect(effect), resource(resource), value(value) {} + + /// Return the effect being applied. + EffectT *getEffect() const { return effect; } + + /// Return the value the effect is applied on, or nullptr if there isn't a + /// known value being affected. + Value getValue() const { return value; } + + /// Return the resource that the effect applies to. + Resource *getResource() const { return resource; } + +private: + /// The specific effect being applied. + EffectT *effect; + + /// The resource that the given value resides in. + Resource *resource; + + /// The value that the effect applies to. This is optionally null. + Value value; +}; +} // namespace SideEffects + +//===----------------------------------------------------------------------===// +// SideEffect Traits +//===----------------------------------------------------------------------===// + +namespace OpTrait { +/// This trait indicates that an operation never has side effects. +template +class HasNoSideEffect : public TraitBase { +public: + static AbstractOperation::OperationProperties getTraitProperties() { + return static_cast( + OperationProperty::NoSideEffect); + } +}; +/// This trait indicates that the side effects of an operation includes the +/// effects of operations nested within its regions. If the operation has no +/// derived effects interfaces, the operation itself can be assumed to have no +/// side effects. +template +class HasRecursiveSideEffects + : public TraitBase {}; +} // namespace OpTrait + +//===----------------------------------------------------------------------===// +// Operation Memory-Effect Modeling +//===----------------------------------------------------------------------===// + +namespace MemoryEffects { +/// This class represents the base class used for memory effects. +struct Effect : public SideEffects::Effect { + using SideEffects::Effect::Effect; + + /// A base class for memory effects that provides helper utilities. + template + using Base = SideEffects::Effect::Base; + + static bool classof(const SideEffects::Effect *effect); +}; +using EffectInstance = SideEffects::EffectInstance; + +/// The following effect indicates that the operation allocates from some +/// resource. An 'allocate' effect implies only allocation of the resource, and +/// not any visible mutation or dereference. +struct Allocate : public Effect::Base {}; + +/// The following effect indicates that the operation frees some resource that +/// has been allocated. An 'allocate' effect implies only de-allocation of the +/// resource, and not any visible allocation, mutation or dereference. +struct Free : public Effect::Base {}; + +/// The following effect indicates that the operation reads from some resource. +/// A 'read' effect implies only dereferencing of the resource, and not any +/// visible mutation. +struct Read : public Effect::Base {}; + +/// The following effect indicates that the operation writes to some resource. A +/// 'write' effect implies only mutating a resource, and not any visible +/// dereference or read. +struct Write : public Effect::Base {}; +} // namespace MemoryEffects + +//===----------------------------------------------------------------------===// +// SideEffect Interfaces + +/// Include the definitions of the side effect interfaces. +#include "mlir/Interfaces/SideEffectInterfaces.h.inc" + +} // end namespace mlir + +#endif // MLIR_INTERFACES_SIDEEFFECTS_H diff --git a/mlir/include/mlir/IR/SideEffects.td b/mlir/include/mlir/Interfaces/SideEffects.td rename from mlir/include/mlir/IR/SideEffects.td rename to mlir/include/mlir/Interfaces/SideEffects.td --- a/mlir/include/mlir/IR/SideEffects.td +++ b/mlir/include/mlir/Interfaces/SideEffects.td @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MLIR_IR_SIDEEFFECTS -#define MLIR_IR_SIDEEFFECTS +#ifndef MLIR_INTERFACES_SIDEEFFECTS +#define MLIR_INTERFACES_SIDEEFFECTS include "mlir/IR/OpBase.td" @@ -188,4 +188,4 @@ : MemoryEffect<"MemoryEffects::Write", resourceName>; def MemWrite : MemWrite<"">; -#endif // MLIR_IR_SIDEEFFECTS +#endif // MLIR_INTERFACES_SIDEEFFECTS diff --git a/mlir/lib/Dialect/AffineOps/CMakeLists.txt b/mlir/lib/Dialect/AffineOps/CMakeLists.txt --- a/mlir/lib/Dialect/AffineOps/CMakeLists.txt +++ b/mlir/lib/Dialect/AffineOps/CMakeLists.txt @@ -14,5 +14,6 @@ PUBLIC MLIREDSC MLIRIR + MLIRSideEffects MLIRStandardOps ) diff --git a/mlir/lib/Dialect/FxpMathOps/CMakeLists.txt b/mlir/lib/Dialect/FxpMathOps/CMakeLists.txt --- a/mlir/lib/Dialect/FxpMathOps/CMakeLists.txt +++ b/mlir/lib/Dialect/FxpMathOps/CMakeLists.txt @@ -14,6 +14,7 @@ MLIRQuantOps MLIRIR MLIRPass + MLIRSideEffects MLIRSupport MLIRStandardOps ) diff --git a/mlir/lib/Dialect/GPU/CMakeLists.txt b/mlir/lib/Dialect/GPU/CMakeLists.txt --- a/mlir/lib/Dialect/GPU/CMakeLists.txt +++ b/mlir/lib/Dialect/GPU/CMakeLists.txt @@ -18,6 +18,7 @@ MLIRLLVMIR MLIRLoopOps MLIRPass + MLIRSideEffects MLIRStandardOps MLIRSupport MLIRTransformUtils diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt --- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt +++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt @@ -18,6 +18,7 @@ MLIRControlFlowInterfaces MLIROpenMP MLIRIR + MLIRSideEffects MLIRSupport ) @@ -36,6 +37,7 @@ LLVMAsmParser MLIRIR MLIRLLVMIR + MLIRSideEffects LLVMSupport LLVMCore ) @@ -56,4 +58,5 @@ LLVMCore LLVMSupport MLIRIR + MLIRSideEffects ) diff --git a/mlir/lib/Dialect/Linalg/IR/CMakeLists.txt b/mlir/lib/Dialect/Linalg/IR/CMakeLists.txt --- a/mlir/lib/Dialect/Linalg/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/Linalg/IR/CMakeLists.txt @@ -16,5 +16,6 @@ target_link_libraries(MLIRLinalgOps PUBLIC MLIRIR + MLIRSideEffects MLIRStandardOps ) diff --git a/mlir/lib/Dialect/LoopOps/CMakeLists.txt b/mlir/lib/Dialect/LoopOps/CMakeLists.txt --- a/mlir/lib/Dialect/LoopOps/CMakeLists.txt +++ b/mlir/lib/Dialect/LoopOps/CMakeLists.txt @@ -14,6 +14,7 @@ PUBLIC MLIREDSC MLIRIR + MLIRSideEffects MLIRStandardOps LLVMSupport ) diff --git a/mlir/lib/Dialect/QuantOps/CMakeLists.txt b/mlir/lib/Dialect/QuantOps/CMakeLists.txt --- a/mlir/lib/Dialect/QuantOps/CMakeLists.txt +++ b/mlir/lib/Dialect/QuantOps/CMakeLists.txt @@ -19,6 +19,7 @@ PUBLIC MLIRIR MLIRPass + MLIRSideEffects MLIRSupport MLIRStandardOps MLIRTransformUtils diff --git a/mlir/lib/Dialect/SPIRV/CMakeLists.txt b/mlir/lib/Dialect/SPIRV/CMakeLists.txt --- a/mlir/lib/Dialect/SPIRV/CMakeLists.txt +++ b/mlir/lib/Dialect/SPIRV/CMakeLists.txt @@ -28,6 +28,7 @@ MLIRControlFlowInterfaces MLIRIR MLIRParser + MLIRSideEffects MLIRSupport MLIRTransforms ) diff --git a/mlir/lib/Dialect/Shape/CMakeLists.txt b/mlir/lib/Dialect/Shape/CMakeLists.txt --- a/mlir/lib/Dialect/Shape/CMakeLists.txt +++ b/mlir/lib/Dialect/Shape/CMakeLists.txt @@ -8,4 +8,5 @@ add_dependencies(MLIRShape MLIRShapeOpsIncGen LLVMSupport) target_link_libraries(MLIRShape PUBLIC + MLIRSideEffects LLVMSupport) diff --git a/mlir/lib/Dialect/StandardOps/CMakeLists.txt b/mlir/lib/Dialect/StandardOps/CMakeLists.txt --- a/mlir/lib/Dialect/StandardOps/CMakeLists.txt +++ b/mlir/lib/Dialect/StandardOps/CMakeLists.txt @@ -15,5 +15,6 @@ MLIRControlFlowInterfaces MLIREDSC MLIRIR + MLIRSideEffects LLVMSupport ) diff --git a/mlir/lib/Dialect/VectorOps/CMakeLists.txt b/mlir/lib/Dialect/VectorOps/CMakeLists.txt --- a/mlir/lib/Dialect/VectorOps/CMakeLists.txt +++ b/mlir/lib/Dialect/VectorOps/CMakeLists.txt @@ -19,4 +19,5 @@ MLIRAffineOps MLIRLoopOps MLIRLoopAnalysis + MLIRSideEffects ) diff --git a/mlir/lib/IR/CMakeLists.txt b/mlir/lib/IR/CMakeLists.txt --- a/mlir/lib/IR/CMakeLists.txt +++ b/mlir/lib/IR/CMakeLists.txt @@ -7,7 +7,6 @@ DEPENDS MLIRCallInterfacesIncGen - MLIRSideEffectOpInterfacesIncGen MLIROpAsmInterfacesIncGen ) target_link_libraries(MLIRIR diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp --- a/mlir/lib/IR/Operation.cpp +++ b/mlir/lib/IR/Operation.cpp @@ -958,17 +958,6 @@ } //===----------------------------------------------------------------------===// -// SideEffect Interfaces - -/// Include the definitions of the side effect interfaces. -#include "mlir/IR/SideEffectInterfaces.cpp.inc" - -bool MemoryEffects::Effect::classof(const SideEffects::Effect *effect) { - return isa(effect) || isa(effect) || isa(effect) || - isa(effect); -} - -//===----------------------------------------------------------------------===// // BinaryOp implementation //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Interfaces/CMakeLists.txt b/mlir/lib/Interfaces/CMakeLists.txt --- a/mlir/lib/Interfaces/CMakeLists.txt +++ b/mlir/lib/Interfaces/CMakeLists.txt @@ -2,6 +2,7 @@ CallInterfaces.cpp ControlFlowInterfaces.cpp InferTypeOpInterface.cpp + SideEffects.cpp ) add_llvm_library(MLIRCallInterfaces @@ -45,3 +46,17 @@ PUBLIC MLIRIR ) + +add_llvm_library(MLIRSideEffects + SideEffects.cpp + + ADDITIONAL_HEADER_DIRS + ${MLIR_MAIN_INCLUDE_DIR}/mlir/Interfaces + ) +add_dependencies(MLIRSideEffects + MLIRSideEffectOpInterfacesIncGen + ) +target_link_libraries(MLIRSideEffects + PUBLIC + MLIRIR + ) diff --git a/mlir/lib/Interfaces/SideEffects.cpp b/mlir/lib/Interfaces/SideEffects.cpp new file mode 100644 --- /dev/null +++ b/mlir/lib/Interfaces/SideEffects.cpp @@ -0,0 +1,27 @@ +//===- SideEffects.cpp - SideEffects in MLIR ------------------------------===// +// +// 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 "mlir/Interfaces/SideEffects.h" + +using namespace mlir; + +//===----------------------------------------------------------------------===// +// SideEffect Interfaces +//===----------------------------------------------------------------------===// + +/// Include the definitions of the side effect interfaces. +#include "mlir/Interfaces/SideEffectInterfaces.cpp.inc" + +//===----------------------------------------------------------------------===// +// MemoryEffects +//===----------------------------------------------------------------------===// + +bool MemoryEffects::Effect::classof(const SideEffects::Effect *effect) { + return isa(effect) || isa(effect) || isa(effect) || + isa(effect); +} diff --git a/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp b/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp --- a/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp +++ b/mlir/lib/Transforms/LoopInvariantCodeMotion.cpp @@ -14,6 +14,7 @@ #include "mlir/IR/Builders.h" #include "mlir/IR/Function.h" +#include "mlir/Interfaces/SideEffects.h" #include "mlir/Pass/Pass.h" #include "mlir/Transforms/LoopLikeInterface.h" #include "llvm/ADT/SmallPtrSet.h" diff --git a/mlir/test/lib/TestDialect/TestDialect.h b/mlir/test/lib/TestDialect/TestDialect.h --- a/mlir/test/lib/TestDialect/TestDialect.h +++ b/mlir/test/lib/TestDialect/TestDialect.h @@ -23,6 +23,7 @@ #include "mlir/Interfaces/CallInterfaces.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/InferTypeOpInterface.h" +#include "mlir/Interfaces/SideEffects.h" #include "TestOpEnums.h.inc" diff --git a/mlir/test/lib/TestDialect/TestOps.td b/mlir/test/lib/TestDialect/TestOps.td --- a/mlir/test/lib/TestDialect/TestOps.td +++ b/mlir/test/lib/TestDialect/TestOps.td @@ -11,7 +11,7 @@ include "mlir/IR/OpBase.td" include "mlir/IR/OpAsmInterface.td" -include "mlir/IR/SideEffects.td" +include "mlir/Interfaces/SideEffects.td" include "mlir/Interfaces/CallInterfaces.td" include "mlir/Interfaces/ControlFlowInterfaces.td" include "mlir/Interfaces/InferTypeOpInterface.td" diff --git a/mlir/test/mlir-tblgen/op-side-effects.td b/mlir/test/mlir-tblgen/op-side-effects.td --- a/mlir/test/mlir-tblgen/op-side-effects.td +++ b/mlir/test/mlir-tblgen/op-side-effects.td @@ -1,6 +1,6 @@ // RUN: mlir-tblgen -gen-op-defs -I %S/../../include %s | FileCheck %s -include "mlir/IR/SideEffects.td" +include "mlir/Interfaces/SideEffects.td" def TEST_Dialect : Dialect { let name = "test";