This is a preparation for adding support for more infrastructure around the concept
of Action and make tracing Action more of a first class concept.
The doc will be updated later in a subsequent revision after the changes are
completed.
Action belongs to IR because of circular dependency: Actions are dispatched through
the MLIRContext but Action will learn to encapsulate IR construct.
Differential Revision: https://reviews.llvm.org/D144809
//
//===----------------------------------------------------------------------===//
-#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 <string>
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.
/// Register a counter with the specified name.
FailureOr<bool> execute(llvm::function_ref<void()> transform,
- const DebugActionBase &action) final;
+ const Action &action) final;
/// Print the counters that have been registered with this instance to the
/// provided output stream.
llvm::StringMap<Counter> counters;
};
+} // namespace tracing
} // namespace mlir
-#endif
+#endif // MLIR_TRACING_DEBUGCOUNTER_H
-//===- 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.
//
//===----------------------------------------------------------------------===//
//
-// 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"
#include <type_traits>
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;
/// return failure if the handler could not process the action, or whether
/// the `transform` was executed or not.
virtual FailureOr<bool> execute(function_ref<void()> 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<GenericHandler>();
}
};
SmallVector<std::unique_ptr<HandlerBase>> 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 <typename Derived, typename... ParameterTs>
-class DebugAction : public DebugActionBase {
+class ActionImpl : public Action {
public:
- DebugAction()
- : DebugActionBase(TypeID::get<Derived>(), Derived::getTag(),
- Derived::getDescription()) {}
+ ActionImpl() : Action(TypeID::get<Derived>()) {}
/// 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<Derived>();
}
- 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<Derived>()) {}
}
/// 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<Derived>();
}
};
}
/// Allow access to `canHandleWith`.
- friend class DebugActionManager;
+ friend class ActionManager;
};
+} // namespace tracing
} // namespace mlir
-#endif // MLIR_SUPPORT_DEBUGACTION_H
+#endif // MLIR_IR_ACTION_H
} // namespace llvm
namespace mlir {
-class DebugActionManager;
+namespace tracing {
+class ActionManager;
+}
class DiagnosticEngine;
class Dialect;
class DialectRegistry;
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
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
add_subdirectory(AsmParser)
add_subdirectory(Bytecode)
add_subdirectory(Conversion)
+add_subdirectory(Debug)
add_subdirectory(Dialect)
add_subdirectory(IR)
add_subdirectory(Interfaces)
--- /dev/null
+add_mlir_library(MLIRDebug
+ DebugCounter.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${MLIR_MAIN_INCLUDE_DIR}/mlir/Debug
+
+ LINK_LIBS PUBLIC
+ ${LLVM_PTHREAD_LIB}
+ MLIRIR
+ MLIRSupport
+)
//
//===----------------------------------------------------------------------===//
-#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
// Register a counter with the specified name.
FailureOr<bool> DebugCounter::execute(llvm::function_ref<void()> transform,
- const DebugActionBase &action) {
+ const Action &action) {
auto counterIt = counters.find(action.getTag());
if (counterIt == counters.end())
return true;
#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"
#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"
//===--------------------------------------------------------------------===//
/// An action manager for use within the context.
- DebugActionManager debugActionManager;
+ tracing::ActionManager actionManager;
//===--------------------------------------------------------------------===//
// Diagnostics
// Debugging
//===----------------------------------------------------------------------===//
-DebugActionManager &MLIRContext::getDebugActionManager() {
- return getImpl().debugActionManager;
+tracing::ActionManager &MLIRContext::getActionManager() {
+ return getImpl().actionManager;
}
//===----------------------------------------------------------------------===//
set(LLVM_OPTIONAL_SOURCES
- DebugCounter.cpp
FileUtilities.cpp
IndentedOstream.cpp
InterfaceSupport.cpp
)
add_mlir_library(MLIRSupport
- DebugCounter.cpp
FileUtilities.cpp
IndentedOstream.cpp
InterfaceSupport.cpp
LINK_LIBS PUBLIC
MLIRBytecodeWriter
+ MLIRDebug
MLIRPass
MLIRParser
MLIRSupport
#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"
#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"
context.allowUnregisteredDialects(config.shouldAllowUnregisteredDialects());
if (config.shouldVerifyDiagnostics())
context.printOpOnDiagnostic(false);
- context.getDebugActionManager().registerActionHandler<DebugCounter>();
+ context.getActionManager().registerActionHandler<tracing::DebugCounter>();
// 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.
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();
add_subdirectory(Analysis)
add_subdirectory(Conversion)
+add_subdirectory(Debug)
add_subdirectory(Dialect)
add_subdirectory(Interfaces)
add_subdirectory(IR)
--- /dev/null
+add_mlir_unittest(MLIRDebugTests
+ DebugCounterTest.cpp
+)
+
+target_link_libraries(MLIRDebugTests
+ PRIVATE MLIRDebug)
//
//===----------------------------------------------------------------------===//
-#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<CounterAction> {
+struct CounterAction : public ActionImpl<CounterAction> {
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<DebugCounter> counter = std::make_unique<DebugCounter>();
- 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; };
-//===- 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.
//
//===----------------------------------------------------------------------===//
-#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<SimpleAction> {
+struct SimpleAction : ActionImpl<SimpleAction> {
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<OtherSimpleAction> {
+struct OtherSimpleAction : ActionImpl<OtherSimpleAction> {
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<ParametricAction, bool> {
+struct ParametricAction : ActionImpl<ParametricAction, bool> {
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<bool> execute(llvm::function_ref<void()> transform,
- const DebugActionBase &action) final {
- StringRef desc = action.getDescription();
+ const Action &action) final {
+ StringRef tag = action.getTag();
if (isa<SimpleAction>(action)) {
- EXPECT_EQ(desc, SimpleAction::getDescription());
+ EXPECT_EQ(tag, SimpleAction::tag);
transform();
return true;
}
EXPECT_TRUE(isa<ParametricAction>(action));
- EXPECT_EQ(desc, ParametricAction::getDescription());
return false;
}
};
EXPECT_FALSE(manager.execute<ParametricAction>(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 {
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 {
EXPECT_FALSE(manager.execute<SimpleAction>(noOp));
}
-TEST(DebugActionTest, NonOverlappingActionSpecificHandlers) {
- DebugActionManager manager;
+TEST(ActionTest, NonOverlappingActionSpecificHandlers) {
+ ActionManager manager;
// One handler returns true and another returns false
struct SimpleActionHandler : SimpleAction::Handler {
add_mlir_unittest(MLIRIRTests
+ ActionTest.cpp
AdaptorTest.cpp
AttributeTest.cpp
DialectTest.cpp
add_mlir_unittest(MLIRSupportTests
- DebugActionTest.cpp
- DebugCounterTest.cpp
IndentedOstreamTest.cpp
MathExtrasTest.cpp
StorageUniquerTest.cpp