[Mlir-commits] [mlir] ef728ea - [mlir][Interfaces] Generate a struct containing function pointers instead of a class with vtables

River Riddle llvmlistbot at llvm.org
Tue Oct 27 16:21:28 PDT 2020


Author: River Riddle
Date: 2020-10-27T16:16:51-07:00
New Revision: ef728eaf6e8de17b9f5bac89c972a94e37e4f09e

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

LOG: [mlir][Interfaces] Generate a struct containing function pointers instead of a class with vtables

When compiling for code size, the use of a vtable causes a destructor(and constructor in certain cases) to be generated for the class. Interface models don't need a complex constructor or a destructor, so this can lead to many megabytes of code size increase(even in opt). This revision switches to a simpler struct of function pointers approach that accomplishes the same API requirements as before. This change requires no updates to user code, or any other code aside from the generator, as the user facing API is still exactly the same.

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

Added: 
    

Modified: 
    mlir/tools/mlir-tblgen/OpInterfacesGen.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
index 54826f4618c4..1b0cb273638f 100644
--- a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
@@ -189,17 +189,19 @@ bool InterfaceGenerator::emitInterfaceDefs() {
 //===----------------------------------------------------------------------===//
 
 void InterfaceGenerator::emitConceptDecl(Interface &interface) {
-  os << "  class Concept {\n"
-     << "  public:\n"
-     << "    virtual ~Concept() = default;\n";
+  os << "  struct Concept {\n";
 
   // Insert each of the pure virtual concept methods.
   for (auto &method : interface.getMethods()) {
-    os << "    virtual ";
+    os << "    ";
     emitCPPType(method.getReturnType(), os);
-    emitMethodNameAndArgs(method, os, valueType,
-                          /*addThisArg=*/!method.isStatic(), /*addConst=*/true);
-    os << " = 0;\n";
+    os << "(*" << method.getName() << ")(";
+    if (!method.isStatic())
+      emitCPPType(valueType, os) << (method.arg_empty() ? "" : ", ");
+    llvm::interleaveComma(
+        method.getArguments(), os,
+        [&](const InterfaceMethod::Argument &arg) { os << arg.type; });
+    os << ");\n";
   }
   os << "  };\n";
 }
@@ -207,13 +209,19 @@ void InterfaceGenerator::emitConceptDecl(Interface &interface) {
 void InterfaceGenerator::emitModelDecl(Interface &interface) {
   os << "  template<typename " << valueTemplate << ">\n";
   os << "  class Model : public Concept {\n  public:\n";
+  os << "    Model() : Concept{";
+  llvm::interleaveComma(
+      interface.getMethods(), os,
+      [&](const InterfaceMethod &method) { os << method.getName(); });
+  os << "} {}\n\n";
 
   // Insert each of the virtual method overrides.
   for (auto &method : interface.getMethods()) {
-    emitCPPType(method.getReturnType(), os << "    ");
+    emitCPPType(method.getReturnType(), os << "    static ");
     emitMethodNameAndArgs(method, os, valueType,
-                          /*addThisArg=*/!method.isStatic(), /*addConst=*/true);
-    os << " final {\n      ";
+                          /*addThisArg=*/!method.isStatic(),
+                          /*addConst=*/false);
+    os << " {\n      ";
 
     // Check for a provided body to the function.
     if (Optional<StringRef> body = method.getBody()) {


        


More information about the Mlir-commits mailing list