[llvm] 4f962b0 - [ORC][examples] Add an OrcV2 example for IR optimization via IRTransformLayer.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 19 19:42:52 PDT 2020


Author: Lang Hames
Date: 2020-09-19T18:59:52-07:00
New Revision: 4f962b0d89b9733c8f051c1039b458c9632f6f88

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

LOG: [ORC][examples] Add an OrcV2 example for IR optimization via IRTransformLayer.

Shows how to write a custom IR transform to apply a legacy::PassManager
pipeline.

Added: 
    llvm/examples/OrcV2Examples/LLJITWithOptimizingIRTransform/CMakeLists.txt
    llvm/examples/OrcV2Examples/LLJITWithOptimizingIRTransform/LLJITWithOptimizingIRTransform.cpp

Modified: 
    llvm/examples/OrcV2Examples/CMakeLists.txt
    llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h

Removed: 
    


################################################################################
diff  --git a/llvm/examples/OrcV2Examples/CMakeLists.txt b/llvm/examples/OrcV2Examples/CMakeLists.txt
index fb7fd41b970a..1d87a84fee97 100644
--- a/llvm/examples/OrcV2Examples/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/CMakeLists.txt
@@ -5,6 +5,7 @@ add_subdirectory(LLJITWithInitializers)
 add_subdirectory(LLJITWithLazyReexports)
 add_subdirectory(LLJITWithObjectCache)
 add_subdirectory(LLJITWithObjectLinkingLayerPlugin)
+add_subdirectory(LLJITWithOptimizingIRTransform)
 add_subdirectory(LLJITWithTargetProcessControl)
 add_subdirectory(LLJITWithThinLTOSummaries)
 add_subdirectory(OrcV2CBindingsAddObjectFile)

diff  --git a/llvm/examples/OrcV2Examples/LLJITWithOptimizingIRTransform/CMakeLists.txt b/llvm/examples/OrcV2Examples/LLJITWithOptimizingIRTransform/CMakeLists.txt
new file mode 100644
index 000000000000..63be55cfa379
--- /dev/null
+++ b/llvm/examples/OrcV2Examples/LLJITWithOptimizingIRTransform/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_LINK_COMPONENTS
+  Core
+  ExecutionEngine
+  IRReader
+  OrcJIT
+  Support
+  nativecodegen
+  )
+
+add_llvm_example(LLJITWithOptimizingIRTransform
+  LLJITWithOptimizingIRTransform.cpp
+  )

diff  --git a/llvm/examples/OrcV2Examples/LLJITWithOptimizingIRTransform/LLJITWithOptimizingIRTransform.cpp b/llvm/examples/OrcV2Examples/LLJITWithOptimizingIRTransform/LLJITWithOptimizingIRTransform.cpp
new file mode 100644
index 000000000000..7ebf3e8e9a07
--- /dev/null
+++ b/llvm/examples/OrcV2Examples/LLJITWithOptimizingIRTransform/LLJITWithOptimizingIRTransform.cpp
@@ -0,0 +1,122 @@
+//===-- LLJITWithOptimizingIRTransform.cpp -- LLJIT with IR optimization --===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// In this example we will use an IR transform to optimize a module as it
+// passes through LLJIT's IRTransformLayer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Scalar.h"
+
+#include "../ExampleModules.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+ExitOnError ExitOnErr;
+
+// Example IR module.
+//
+// This IR contains a recursive definition of the factorial function:
+//
+// fac(n) | n == 0    = 1
+//        | otherwise = n * fac(n - 1)
+//
+// It also contains an entry function which calls the factorial function with
+// an input value of 5.
+//
+// We expect the IR optimization transform that we build below to transform
+// this into a non-recursive factorial function and an entry function that
+// returns a constant value of 5!, or 120.
+
+const llvm::StringRef MainMod =
+    R"(
+
+  define i32 @fac(i32 %n) {
+  entry:
+    %tobool = icmp eq i32 %n, 0
+    br i1 %tobool, label %return, label %if.then
+
+  if.then:                                          ; preds = %entry
+    %arg = add nsw i32 %n, -1
+    %call_result = call i32 @fac(i32 %arg)
+    %result = mul nsw i32 %n, %call_result
+    br label %return
+
+  return:                                           ; preds = %entry, %if.then
+    %final_result = phi i32 [ %result, %if.then ], [ 1, %entry ]
+    ret i32 %final_result
+  }
+
+  define i32 @entry() {
+  entry:
+    %result = call i32 @fac(i32 5)
+    ret i32 %result
+  }
+
+)";
+
+// A function object that creates a simple pass pipeline to apply to each
+// module as it passes through the IRTransformLayer.
+class MyOptimizationTransform {
+public:
+  MyOptimizationTransform() : PM(std::make_unique<legacy::PassManager>()) {
+    PM->add(createTailCallEliminationPass());
+    PM->add(createFunctionInliningPass());
+    PM->add(createIndVarSimplifyPass());
+    PM->add(createCFGSimplificationPass());
+  }
+
+  Expected<ThreadSafeModule> operator()(ThreadSafeModule TSM,
+                                        MaterializationResponsibility &R) {
+    TSM.withModuleDo([this](Module &M) {
+      dbgs() << "--- BEFORE OPTIMIZATION ---\n" << M << "\n";
+      PM->run(M);
+      dbgs() << "--- AFTER OPTIMIZATION ---\n" << M << "\n";
+    });
+    return std::move(TSM);
+  }
+
+private:
+  std::unique_ptr<legacy::PassManager> PM;
+};
+
+int main(int argc, char *argv[]) {
+  // Initialize LLVM.
+  InitLLVM X(argc, argv);
+
+  InitializeNativeTarget();
+  InitializeNativeTargetAsmPrinter();
+
+  ExitOnErr.setBanner(std::string(argv[0]) + ": ");
+
+  // (1) Create LLJIT instance.
+  auto J = ExitOnErr(LLJITBuilder().create());
+
+  // (2) Install transform to optimize modules when they're materialized.
+  J->getIRTransformLayer().setTransform(MyOptimizationTransform());
+
+  // (3) Add modules.
+  ExitOnErr(J->addIRModule(ExitOnErr(parseExampleModule(MainMod, "MainMod"))));
+
+  // (4) Look up the JIT'd function and call it.
+  auto EntrySym = ExitOnErr(J->lookup("entry"));
+  auto *Entry = (int (*)())EntrySym.getAddress();
+
+  int Result = Entry();
+  outs() << "--- Result ---\n"
+         << "entry() = " << Result << "\n";
+
+  return 0;
+}

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
index ee4ee3437fa6..475d3f259aef 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
 #define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
 
+#include "llvm/ADT/FunctionExtras.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/ExecutionEngine/Orc/Layer.h"
 #include <memory>
@@ -27,7 +28,7 @@ namespace orc {
 /// before operating on the module.
 class IRTransformLayer : public IRLayer {
 public:
-  using TransformFunction = std::function<Expected<ThreadSafeModule>(
+  using TransformFunction = unique_function<Expected<ThreadSafeModule>(
       ThreadSafeModule, MaterializationResponsibility &R)>;
 
   IRTransformLayer(ExecutionSession &ES, IRLayer &BaseLayer,


        


More information about the llvm-commits mailing list