[Mlir-commits] [mlir] e4fb75a - [mlir][ods] Add Deprecate helper

Jacques Pienaar llvmlistbot at llvm.org
Tue Mar 22 11:08:42 PDT 2022


Author: Jacques Pienaar
Date: 2022-03-22T11:08:36-07:00
New Revision: e4fb75a354740bf45dab0ebd43f37ab2fdeae3bf

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

LOG: [mlir][ods] Add Deprecate helper

Add method to tag classes/defs as deprecated. Previously deprecations
were only verbally communicated and folks didn't have an active warning
while building about impending removal. Add mechanism to tag defs as
deprecated to allow warning users.

This doesn't change any policy, it just moves deprecation warnings from
comments to something more user visible.

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

Added: 
    mlir/test/mlir-tblgen/deprecation.td

Modified: 
    mlir/docs/OpDefinitions.md
    mlir/include/mlir/IR/OpBase.td
    mlir/tools/mlir-tblgen/mlir-tblgen.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/docs/OpDefinitions.md b/mlir/docs/OpDefinitions.md
index eab13fd9893d8..ebdc2a93c35ec 100644
--- a/mlir/docs/OpDefinitions.md
+++ b/mlir/docs/OpDefinitions.md
@@ -1526,6 +1526,19 @@ mlir-tblgen --gen-op-interface-doc -I /path/to/mlir/include /path/to/input/td/fi
 
 ## Appendix
 
+### Reporting deprecation
+
+Classes/defs can be marked as deprecated by using the `Deprecate` helper class,
+e.g.,
+
+```td
+def OpTraitA : NativeOpTrait<"OpTraitA">, Deprecated<"use `bar` instead">;
+```
+
+would result in marking `OpTraitA` as deprecated and mlir-tblgen can emit a
+warning (default) or error (depending on `-on-deprecated` flag) to make
+deprecated state known.
+
 ### Requirements and existing mechanisms analysis
 
 The op description should be as declarative as possible to allow a wide range of

diff  --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td
index 844489aa5591b..a5b3ca2f9c89a 100644
--- a/mlir/include/mlir/IR/OpBase.td
+++ b/mlir/include/mlir/IR/OpBase.td
@@ -38,6 +38,12 @@ class StrFunc<string r> {
   string result = r;
 }
 
+// Helper for marking deprecated classes or defs. To mark a def as deprecated,
+// mix in the `Deprecate` class with a reason.
+class Deprecated<string reason> {
+  string odsDeprecated = reason;
+}
+
 //===----------------------------------------------------------------------===//
 // Predicate definitions
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/test/mlir-tblgen/deprecation.td b/mlir/test/mlir-tblgen/deprecation.td
new file mode 100644
index 0000000000000..b6e6d6548f7a5
--- /dev/null
+++ b/mlir/test/mlir-tblgen/deprecation.td
@@ -0,0 +1,15 @@
+// RUN: not mlir-tblgen -on-deprecated=error -gen-op-decls -I %S/../../include -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s
+
+include "mlir/IR/OpBase.td"
+
+def Test_Dialect : Dialect {
+  let name = "test_dialect";
+}
+
+#ifdef ERROR1
+def OpTraitA : NativeOpTrait<"OpTraitA">, Deprecated<"use `bar` instead">;
+
+// ERROR1: warning: Using deprecated def `OpTraitA`
+// ERROR1: use `bar` instead
+def OpTraitWithoutDependentTrait : Op<Test_Dialect, "default_value", [OpTraitA]> {}
+#endif

diff  --git a/mlir/tools/mlir-tblgen/mlir-tblgen.cpp b/mlir/tools/mlir-tblgen/mlir-tblgen.cpp
index 6a2bbcd0baa45..cbc20c4a1af77 100644
--- a/mlir/tools/mlir-tblgen/mlir-tblgen.cpp
+++ b/mlir/tools/mlir-tblgen/mlir-tblgen.cpp
@@ -26,6 +26,15 @@
 using namespace llvm;
 using namespace mlir;
 
+enum DeprecatedAction { None, Warn, Error };
+llvm::cl::opt<DeprecatedAction> actionOnDeprecated(
+    "on-deprecated", llvm::cl::init(Warn),
+    llvm::cl::desc("Action to perform on deprecated def"),
+    llvm::cl::values(clEnumValN(DeprecatedAction::None, "none", "No action"),
+                     clEnumValN(DeprecatedAction::Warn, "warn", "Warn on use"),
+                     clEnumValN(DeprecatedAction::Error, "error",
+                                "Error on use")));
+
 static llvm::ManagedStatic<std::vector<GenInfo>> generatorRegistry;
 
 mlir::GenRegistration::GenRegistration(StringRef arg, StringRef description,
@@ -62,9 +71,80 @@ GenRegistration printRecords("print-records", "Print all records to stdout",
 // Generator to invoke.
 const mlir::GenInfo *generator;
 
+// Returns if there is a use of `init` in `record`.
+bool findUse(Record &record, Init *init,
+             llvm::DenseMap<Record *, bool> &known) {
+  auto it = known.find(&record);
+  if (it != known.end())
+    return it->second;
+
+  auto memoize = [&](bool val) {
+    known[&record] = val;
+    return val;
+  };
+
+  for (const RecordVal &val : record.getValues()) {
+    Init *valInit = val.getValue();
+    if (valInit == init)
+      return true;
+    if (auto *di = dyn_cast<DefInit>(valInit)) {
+      if (findUse(*di->getDef(), init, known))
+        return memoize(true);
+    } else if (auto *di = dyn_cast<DagInit>(valInit)) {
+      for (Init *arg : di->getArgs())
+        if (auto *di = dyn_cast<DefInit>(arg))
+          if (findUse(*di->getDef(), init, known))
+            return memoize(true);
+    } else if (ListInit *li = dyn_cast<ListInit>(valInit)) {
+      for (Init *jt : li->getValues())
+        if (jt == init)
+          return memoize(true);
+    }
+  }
+  return memoize(false);
+}
+
+void warnOfDeprecatedUses(RecordKeeper &records) {
+  // This performs a direct check for any def marked as deprecated and then
+  // finds all uses of deprecated def. Deprecated defs are not expected to be
+  // either numerous or long lived.
+  bool deprecatedDefsFounds = false;
+  for (auto &it : records.getDefs()) {
+    const RecordVal *r = it.second->getValue("odsDeprecated");
+    if (!r || !r->getValue())
+      continue;
+
+    llvm::DenseMap<Record *, bool> hasUse;
+    if (auto *si = dyn_cast<StringInit>(r->getValue())) {
+      for (auto &jt : records.getDefs()) {
+        // Skip anonymous defs.
+        if (jt.second->isAnonymous())
+          continue;
+        // Skip all outside main file to avoid flagging redundantly.
+        unsigned buf =
+            SrcMgr.FindBufferContainingLoc(jt.second->getLoc().front());
+        if (buf != SrcMgr.getMainFileID())
+          continue;
+
+        if (findUse(*jt.second, it.second->getDefInit(), hasUse)) {
+          PrintWarning(jt.second->getLoc(),
+                       "Using deprecated def `" + it.first + "`");
+          PrintNote(si->getAsUnquotedString());
+          deprecatedDefsFounds = true;
+        }
+      }
+    }
+  }
+  if (deprecatedDefsFounds && actionOnDeprecated == DeprecatedAction::Error)
+    PrintFatalNote("Error'ing out due to deprecated defs");
+}
+
 // TableGenMain requires a function pointer so this function is passed in which
 // simply wraps the call to the generator.
 static bool mlirTableGenMain(raw_ostream &os, RecordKeeper &records) {
+  if (actionOnDeprecated != DeprecatedAction::None)
+    warnOfDeprecatedUses(records);
+
   if (!generator) {
     os << records;
     return false;


        


More information about the Mlir-commits mailing list