diff --git a/mlir/include/mlir/Support/DebugCounter.h b/mlir/include/mlir/Debug/Counter.h rename from mlir/include/mlir/Support/DebugCounter.h rename to mlir/include/mlir/Debug/Counter.h --- a/mlir/include/mlir/Support/DebugCounter.h +++ b/mlir/include/mlir/Debug/Counter.h @@ -6,31 +6,32 @@ // //===----------------------------------------------------------------------===// -#ifndef MLIR_SUPPORT_DEBUGCOUNTER_H -#define MLIR_SUPPORT_DEBUGCOUNTER_H +#ifndef MLIR_TRACING_DEBUGCOUNTER_H +#define MLIR_TRACING_DEBUGCOUNTER_H -#include "mlir/Support/DebugAction.h" +#include "mlir/IR/Action.h" #include "llvm/ADT/StringMap.h" #include namespace mlir { +namespace tracing { -/// This class implements a debug action handler that attaches a counter value +/// This class implements an action handler that attaches a counter value /// to debug actions and enables/disables execution of these action based on the /// value of the counter. The counter controls the execution of the action with /// a "skip" and "count" value. The "skip" value is used to skip a certain -/// number of initial executions of a debug action. The "count" value is used to -/// prevent a debug action from executing after it has executed for a set number +/// number of initial executions of an action. The "count" value is used to +/// prevent an action from executing after it has executed for a set number /// of times (not including any executions that have been skipped). For example, -/// a counter for a debug action with `skip=47` and `count=2`, would skip the +/// a counter for an action with `skip=47` and `count=2`, would skip the /// first 47 executions, then execute twice, and finally prevent any further /// executions. -class DebugCounter : public DebugActionManager::GenericHandler { +class DebugCounter : public ActionManager::GenericHandler { public: DebugCounter(); ~DebugCounter() override; - /// Add a counter for the given debug action tag. `countToSkip` is the number + /// Add a counter for the given action tag. `countToSkip` is the number /// of counter executions to skip before enabling execution of the action. /// `countToStopAfter` is the number of executions of the counter to allow /// before preventing the action from executing any more. @@ -39,7 +40,7 @@ /// Register a counter with the specified name. FailureOr execute(llvm::function_ref transform, - const DebugActionBase &action) final; + const Action &action) final; /// Print the counters that have been registered with this instance to the /// provided output stream. @@ -69,6 +70,7 @@ llvm::StringMap counters; }; +} // namespace tracing } // namespace mlir -#endif +#endif // MLIR_TRACING_DEBUGCOUNTER_H diff --git a/mlir/include/mlir/Support/DebugAction.h b/mlir/include/mlir/IR/Action.h rename from mlir/include/mlir/Support/DebugAction.h rename to mlir/include/mlir/IR/Action.h --- a/mlir/include/mlir/Support/DebugAction.h +++ b/mlir/include/mlir/IR/Action.h @@ -1,4 +1,4 @@ -//===- DebugAction.h - Debug Action Support ---------------------*- C++ -*-===// +//===- Action.h - Action Support ---------------------*- C++ -*-=============// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,14 +6,14 @@ // //===----------------------------------------------------------------------===// // -// This file contains definitions for the debug action framework. This framework +// This file contains definitions for the action framework. This framework // allows for external entities to control certain actions taken by the compiler // by registering handler functions. // //===----------------------------------------------------------------------===// -#ifndef MLIR_SUPPORT_DEBUGACTION_H -#define MLIR_SUPPORT_DEBUGACTION_H +#ifndef MLIR_IR_ACTION_H +#define MLIR_IR_ACTION_H #include "mlir/Support/LogicalResult.h" #include "mlir/Support/TypeID.h" @@ -26,53 +26,58 @@ #include namespace mlir { +namespace tracing { -/// This class represents the base class of a debug action. -class DebugActionBase { +/// An action is a specific action that is to be taken by the compiler, +/// that can be toggled and controlled by an external user. There are no +/// constraints on the granularity of an action, it could be as simple as +/// "perform this fold" and as complex as "run this pass pipeline". Via template +/// parameters `ParameterTs`, a user may provide the set of argument types that +/// are provided when handling a query on this action. +/// +/// This class represents the base class of the ActionImpl class (see below). +/// This holds the template-invariant elements of the Action class. +class Action { public: - virtual ~DebugActionBase() = default; + virtual ~Action() = default; /// Return the unique action id of this action, use for casting /// functionality. TypeID getActionID() const { return actionID; } - StringRef getTag() const { return tag; } - - StringRef getDescription() const { return desc; } + /// Return a string "tag" which intends to uniquely identify this type of + /// action. For example "pass-application" or "pattern-rewrite". + virtual StringRef getTag() const = 0; virtual void print(raw_ostream &os) const { - os << "Action \"" << tag << "\" : " << desc << "\n"; + os << "Action \"" << getTag() << "\""; } protected: - DebugActionBase(TypeID actionID, StringRef tag, StringRef desc) - : actionID(actionID), tag(tag), desc(desc) {} + Action(TypeID actionID) : actionID(actionID) {} - /// The type of the derived action class. This allows for detecting the - /// specific handler of a given action type. + /// The type of the derived action class, used for `isa`/`dyn_cast`. TypeID actionID; - StringRef tag; - StringRef desc; }; //===----------------------------------------------------------------------===// -// DebugActionManager +// ActionManager //===----------------------------------------------------------------------===// -/// This class represents manages debug actions, and orchestrates the +/// This class represents manages actions, and orchestrates the /// communication between action queries and action handlers. An action handler /// is either an action specific handler, i.e. a derived class of /// `MyActionType::Handler`, or a generic handler, i.e. a derived class of -/// `DebugActionManager::GenericHandler`. For more details on action specific -/// handlers, see the definition of `DebugAction::Handler` below. For more -/// details on generic handlers, see `DebugActionManager::GenericHandler` below. -class DebugActionManager { +/// `ActionManager::GenericHandler`. For more details on action specific +/// handlers, see the definition of `Action::Handler` below. For more +/// details on generic handlers, see `ActionManager::GenericHandler` below. +class ActionManager { public: //===--------------------------------------------------------------------===// // Handlers //===--------------------------------------------------------------------===// - /// This class represents the base class of a debug action handler. + /// This class represents the base class of an action handler. class HandlerBase { public: virtual ~HandlerBase() = default; @@ -104,12 +109,12 @@ /// return failure if the handler could not process the action, or whether /// the `transform` was executed or not. virtual FailureOr execute(function_ref transform, - const DebugActionBase &action) { + const Action &action) { return failure(); } /// Provide classof to allow casting between handler types. - static bool classof(const DebugActionManager::HandlerBase *handler) { + static bool classof(const ActionManager::HandlerBase *handler) { return handler->getHandlerID() == TypeID::get(); } }; @@ -193,39 +198,26 @@ SmallVector> actionHandlers; }; -//===----------------------------------------------------------------------===// -// DebugAction -//===----------------------------------------------------------------------===// - -/// A debug action is a specific action that is to be taken by the compiler, -/// that can be toggled and controlled by an external user. There are no -/// constraints on the granularity of an action, it could be as simple as -/// "perform this fold" and as complex as "run this pass pipeline". Via template -/// parameters `ParameterTs`, a user may provide the set of argument types that -/// are provided when handling a query on this action. Derived classes are -/// expected to provide the following: -/// * static llvm::StringRef getTag() +/// CRTP Implementation of an action. This class provides a base class for +/// implementing specific actions. +/// Derived classes are expected to provide the following: +/// * static constexpr StringLiteral tag = "..."; /// - This method returns a unique string identifier, similar to a command /// line flag or DEBUG_TYPE. -/// * static llvm::StringRef getDescription() -/// - This method returns a short description of what the action represents. -/// -/// This class provides a handler class that can be derived from to handle -/// instances of this action. The parameters to its query methods map 1-1 to the -/// types on the action type. template -class DebugAction : public DebugActionBase { +class ActionImpl : public Action { public: - DebugAction() - : DebugActionBase(TypeID::get(), Derived::getTag(), - Derived::getDescription()) {} + ActionImpl() : Action(TypeID::get()) {} /// Provide classof to allow casting between action types. - static bool classof(const DebugActionBase *action) { + static bool classof(const Action *action) { return action->getActionID() == TypeID::get(); } - class Handler : public DebugActionManager::HandlerBase { + /// Forward tag access to the derived class. + StringRef getTag() const final { return Derived::tag; } + + class Handler : public ActionManager::HandlerBase { public: Handler() : HandlerBase(TypeID::get()) {} @@ -239,7 +231,7 @@ } /// Provide classof to allow casting between handler types. - static bool classof(const DebugActionManager::HandlerBase *handler) { + static bool classof(const ActionManager::HandlerBase *handler) { return handler->getHandlerID() == TypeID::get(); } }; @@ -254,9 +246,10 @@ } /// Allow access to `canHandleWith`. - friend class DebugActionManager; + friend class ActionManager; }; +} // namespace tracing } // namespace mlir -#endif // MLIR_SUPPORT_DEBUGACTION_H +#endif // MLIR_IR_ACTION_H diff --git a/mlir/include/mlir/IR/MLIRContext.h b/mlir/include/mlir/IR/MLIRContext.h --- a/mlir/include/mlir/IR/MLIRContext.h +++ b/mlir/include/mlir/IR/MLIRContext.h @@ -20,7 +20,9 @@ } // namespace llvm namespace mlir { -class DebugActionManager; +namespace tracing { +class ActionManager; +} class DiagnosticEngine; class Dialect; class DialectRegistry; @@ -30,6 +32,7 @@ class MLIRContextImpl; class RegisteredOperationName; class StorageUniquer; +class IRUnit; /// MLIRContext is the top-level object for a collection of MLIR operations. It /// holds immortal uniqued objects like types, and the tables used to unique @@ -215,7 +218,7 @@ StorageUniquer &getAttributeUniquer(); /// Returns the manager of debug actions within the context. - DebugActionManager &getDebugActionManager(); + tracing::ActionManager &getActionManager(); /// These APIs are tracking whether the context will be used in a /// multithreading environment: this has no effect other than enabling diff --git a/mlir/lib/CMakeLists.txt b/mlir/lib/CMakeLists.txt --- a/mlir/lib/CMakeLists.txt +++ b/mlir/lib/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory(AsmParser) add_subdirectory(Bytecode) add_subdirectory(Conversion) +add_subdirectory(Debug) add_subdirectory(Dialect) add_subdirectory(IR) add_subdirectory(Interfaces) diff --git a/mlir/lib/Debug/CMakeLists.txt b/mlir/lib/Debug/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/mlir/lib/Debug/CMakeLists.txt @@ -0,0 +1,11 @@ +add_mlir_library(MLIRDebug + DebugCounter.cpp + + ADDITIONAL_HEADER_DIRS + ${MLIR_MAIN_INCLUDE_DIR}/mlir/Debug + + LINK_LIBS PUBLIC + ${LLVM_PTHREAD_LIB} + MLIRIR + MLIRSupport +) diff --git a/mlir/lib/Support/DebugCounter.cpp b/mlir/lib/Debug/DebugCounter.cpp rename from mlir/lib/Support/DebugCounter.cpp rename to mlir/lib/Debug/DebugCounter.cpp --- a/mlir/lib/Support/DebugCounter.cpp +++ b/mlir/lib/Debug/DebugCounter.cpp @@ -6,13 +6,14 @@ // //===----------------------------------------------------------------------===// -#include "mlir/Support/DebugCounter.h" +#include "mlir/Debug/Counter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" using namespace mlir; +using namespace mlir::tracing; //===----------------------------------------------------------------------===// // DebugCounter CommandLine Options @@ -63,7 +64,7 @@ // Register a counter with the specified name. FailureOr DebugCounter::execute(llvm::function_ref transform, - const DebugActionBase &action) { + const Action &action) { auto counterIt = counters.find(action.getTag()); if (counterIt == counters.end()) return true; diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp --- a/mlir/lib/IR/MLIRContext.cpp +++ b/mlir/lib/IR/MLIRContext.cpp @@ -12,6 +12,7 @@ #include "AttributeDetail.h" #include "IntegerSetDetail.h" #include "TypeDetail.h" +#include "mlir/IR/Action.h" #include "mlir/IR/AffineExpr.h" #include "mlir/IR/AffineMap.h" #include "mlir/IR/Attributes.h" @@ -23,7 +24,6 @@ #include "mlir/IR/Location.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/Types.h" -#include "mlir/Support/DebugAction.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallString.h" @@ -124,7 +124,7 @@ //===--------------------------------------------------------------------===// /// An action manager for use within the context. - DebugActionManager debugActionManager; + tracing::ActionManager actionManager; //===--------------------------------------------------------------------===// // Diagnostics @@ -348,8 +348,8 @@ // Debugging //===----------------------------------------------------------------------===// -DebugActionManager &MLIRContext::getDebugActionManager() { - return getImpl().debugActionManager; +tracing::ActionManager &MLIRContext::getActionManager() { + return getImpl().actionManager; } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Support/CMakeLists.txt b/mlir/lib/Support/CMakeLists.txt --- a/mlir/lib/Support/CMakeLists.txt +++ b/mlir/lib/Support/CMakeLists.txt @@ -1,5 +1,4 @@ set(LLVM_OPTIONAL_SOURCES - DebugCounter.cpp FileUtilities.cpp IndentedOstream.cpp InterfaceSupport.cpp @@ -10,7 +9,6 @@ ) add_mlir_library(MLIRSupport - DebugCounter.cpp FileUtilities.cpp IndentedOstream.cpp InterfaceSupport.cpp diff --git a/mlir/lib/Tools/mlir-opt/CMakeLists.txt b/mlir/lib/Tools/mlir-opt/CMakeLists.txt --- a/mlir/lib/Tools/mlir-opt/CMakeLists.txt +++ b/mlir/lib/Tools/mlir-opt/CMakeLists.txt @@ -6,6 +6,7 @@ LINK_LIBS PUBLIC MLIRBytecodeWriter + MLIRDebug MLIRPass MLIRParser MLIRSupport diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp --- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp +++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp @@ -13,6 +13,7 @@ #include "mlir/Tools/mlir-opt/MlirOptMain.h" #include "mlir/Bytecode/BytecodeWriter.h" +#include "mlir/Debug/Counter.h" #include "mlir/IR/AsmState.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/BuiltinOps.h" @@ -23,7 +24,6 @@ #include "mlir/Parser/Parser.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" -#include "mlir/Support/DebugCounter.h" #include "mlir/Support/FileUtilities.h" #include "mlir/Support/Timing.h" #include "mlir/Support/ToolUtilities.h" @@ -212,7 +212,7 @@ context.allowUnregisteredDialects(config.shouldAllowUnregisteredDialects()); if (config.shouldVerifyDiagnostics()) context.printOpOnDiagnostic(false); - context.getDebugActionManager().registerActionHandler(); + context.getActionManager().registerActionHandler(); // If we are in verify diagnostics mode then we have a lot of work to do, // otherwise just perform the actions without worrying about it. @@ -324,7 +324,7 @@ registerMLIRContextCLOptions(); registerPassManagerCLOptions(); registerDefaultTimingManagerCLOptions(); - DebugCounter::registerCLOptions(); + tracing::DebugCounter::registerCLOptions(); // Build the list of dialects as a header for the --help message. std::string helpHeader = (toolName + "\nAvailable Dialects: ").str(); diff --git a/mlir/unittests/CMakeLists.txt b/mlir/unittests/CMakeLists.txt --- a/mlir/unittests/CMakeLists.txt +++ b/mlir/unittests/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(Analysis) add_subdirectory(Conversion) +add_subdirectory(Debug) add_subdirectory(Dialect) add_subdirectory(Interfaces) add_subdirectory(IR) diff --git a/mlir/unittests/Debug/CMakeLists.txt b/mlir/unittests/Debug/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/mlir/unittests/Debug/CMakeLists.txt @@ -0,0 +1,6 @@ +add_mlir_unittest(MLIRDebugTests + DebugCounterTest.cpp +) + +target_link_libraries(MLIRDebugTests + PRIVATE MLIRDebug) diff --git a/mlir/unittests/Support/DebugCounterTest.cpp b/mlir/unittests/Debug/DebugCounterTest.cpp rename from mlir/unittests/Support/DebugCounterTest.cpp rename to mlir/unittests/Debug/DebugCounterTest.cpp --- a/mlir/unittests/Support/DebugCounterTest.cpp +++ b/mlir/unittests/Debug/DebugCounterTest.cpp @@ -6,26 +6,26 @@ // //===----------------------------------------------------------------------===// -#include "mlir/Support/DebugCounter.h" +#include "mlir/Debug/Counter.h" #include "mlir/Support/TypeID.h" #include "gmock/gmock.h" using namespace mlir; +using namespace mlir::tracing; namespace { -struct CounterAction : public DebugAction { +struct CounterAction : public ActionImpl { MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CounterAction) - static StringRef getTag() { return "counter-action"; } - static StringRef getDescription() { return "Test action for debug counters"; } + static constexpr StringLiteral tag = "counter-action"; }; TEST(DebugCounterTest, CounterTest) { std::unique_ptr counter = std::make_unique(); - counter->addCounter(CounterAction::getTag(), /*countToSkip=*/1, + counter->addCounter(CounterAction::tag, /*countToSkip=*/1, /*countToStopAfter=*/3); - DebugActionManager manager; + ActionManager manager; manager.registerActionHandler(std::move(counter)); auto noOp = []() { return; }; diff --git a/mlir/unittests/Support/DebugActionTest.cpp b/mlir/unittests/IR/ActionTest.cpp rename from mlir/unittests/Support/DebugActionTest.cpp rename to mlir/unittests/IR/ActionTest.cpp --- a/mlir/unittests/Support/DebugActionTest.cpp +++ b/mlir/unittests/IR/ActionTest.cpp @@ -1,4 +1,4 @@ -//===- DebugActionTest.cpp - Debug Action Tests ---------------------------===// +//===- ActionTest.cpp - Debug Action Tests ---------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,50 +6,45 @@ // //===----------------------------------------------------------------------===// -#include "mlir/Support/DebugAction.h" +#include "mlir/IR/Action.h" #include "mlir/Support/TypeID.h" #include "gmock/gmock.h" using namespace mlir; +using namespace mlir::tracing; namespace { -struct SimpleAction : DebugAction { +struct SimpleAction : ActionImpl { MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(SimpleAction) - static StringRef getTag() { return "simple-action"; } - static StringRef getDescription() { return "simple-action-description"; } + static constexpr StringLiteral tag = "simple-action"; }; -struct OtherSimpleAction : DebugAction { +struct OtherSimpleAction : ActionImpl { MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(OtherSimpleAction) - static StringRef getTag() { return "other-simple-action"; } - static StringRef getDescription() { - return "other-simple-action-description"; - } + static constexpr StringLiteral tag = "other-simple-action"; }; -struct ParametricAction : DebugAction { +struct ParametricAction : ActionImpl { MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(ParametricAction) ParametricAction(bool executeParam) : executeParam(executeParam) {} bool executeParam; - static StringRef getTag() { return "param-action"; } - static StringRef getDescription() { return "param-action-description"; } + static constexpr StringLiteral tag = "param-action"; }; -TEST(DebugActionTest, GenericHandler) { - DebugActionManager manager; +TEST(ActionTest, GenericHandler) { + ActionManager manager; // A generic handler that always executes the simple action, but not the // parametric action. - struct GenericHandler : DebugActionManager::GenericHandler { + struct GenericHandler : ActionManager::GenericHandler { FailureOr execute(llvm::function_ref transform, - const DebugActionBase &action) final { - StringRef desc = action.getDescription(); + const Action &action) final { + StringRef tag = action.getTag(); if (isa(action)) { - EXPECT_EQ(desc, SimpleAction::getDescription()); + EXPECT_EQ(tag, SimpleAction::tag); transform(); return true; } EXPECT_TRUE(isa(action)); - EXPECT_EQ(desc, ParametricAction::getDescription()); return false; } }; @@ -60,8 +55,8 @@ EXPECT_FALSE(manager.execute(noOp, true)); } -TEST(DebugActionTest, ActionSpecificHandler) { - DebugActionManager manager; +TEST(ActionTest, ActionSpecificHandler) { + ActionManager manager; // Handler that simply uses the input as the decider. struct ActionSpecificHandler : ParametricAction::Handler { @@ -86,8 +81,8 @@ EXPECT_EQ(count, 2); } -TEST(DebugActionTest, DebugCounterHandler) { - DebugActionManager manager; +TEST(ActionTest, DebugCounterHandler) { + ActionManager manager; // Handler that uses the number of action executions as the decider. struct DebugCounterHandler : SimpleAction::Handler { @@ -111,8 +106,8 @@ EXPECT_FALSE(manager.execute(noOp)); } -TEST(DebugActionTest, NonOverlappingActionSpecificHandlers) { - DebugActionManager manager; +TEST(ActionTest, NonOverlappingActionSpecificHandlers) { + ActionManager manager; // One handler returns true and another returns false struct SimpleActionHandler : SimpleAction::Handler { diff --git a/mlir/unittests/IR/CMakeLists.txt b/mlir/unittests/IR/CMakeLists.txt --- a/mlir/unittests/IR/CMakeLists.txt +++ b/mlir/unittests/IR/CMakeLists.txt @@ -1,4 +1,5 @@ add_mlir_unittest(MLIRIRTests + ActionTest.cpp AdaptorTest.cpp AttributeTest.cpp DialectTest.cpp diff --git a/mlir/unittests/Support/CMakeLists.txt b/mlir/unittests/Support/CMakeLists.txt --- a/mlir/unittests/Support/CMakeLists.txt +++ b/mlir/unittests/Support/CMakeLists.txt @@ -1,6 +1,4 @@ add_mlir_unittest(MLIRSupportTests - DebugActionTest.cpp - DebugCounterTest.cpp IndentedOstreamTest.cpp MathExtrasTest.cpp StorageUniquerTest.cpp