about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorMartin Nowack <m.nowack@imperial.ac.uk>2023-10-12 11:16:18 +0100
committerCristian Cadar <c.cadar@imperial.ac.uk>2024-02-08 13:17:19 +0000
commit2a75a6d6fdb665d92bafee75cb9c08ca3cc05ea1 (patch)
treeea95b2da9ff1b93bd1c2230b5065325f46d08fcc
parent2b75ab2af15527c9051f1d236427232bb2295d93 (diff)
downloadklee-2a75a6d6fdb665d92bafee75cb9c08ca3cc05ea1.tar.gz
Refactor invocation of old pass manager into legacy function
-rw-r--r--lib/Module/CMakeLists.txt14
-rw-r--r--lib/Module/Instrument.cpp19
-rw-r--r--lib/Module/InstrumentLegacy.cpp125
-rw-r--r--lib/Module/KModule.cpp139
-rw-r--r--lib/Module/ModuleHelper.h37
-rw-r--r--lib/Module/Optimize.cpp249
-rw-r--r--lib/Module/OptimizeLegacy.cpp249
7 files changed, 475 insertions, 357 deletions
diff --git a/lib/Module/CMakeLists.txt b/lib/Module/CMakeLists.txt
index e1f548e8..71e1d40c 100644
--- a/lib/Module/CMakeLists.txt
+++ b/lib/Module/CMakeLists.txt
@@ -16,12 +16,24 @@ set(KLEE_MODULE_COMPONENT_SRCS
   KModule.cpp
   LowerSwitch.cpp
   ModuleUtil.cpp
-  Optimize.cpp
   OptNone.cpp
   PhiCleaner.cpp
   RaiseAsm.cpp
 )
 
+if ("${LLVM_VERSION_MAJOR}" LESS 17)
+  LIST(APPEND KLEE_MODULE_COMPONENT_SRCS
+          InstrumentLegacy.cpp
+          OptimizeLegacy.cpp
+  )
+else ()
+  LIST(APPEND KLEE_MODULE_COMPONENT_SRCS
+          Instrument.cpp
+          Optimize.cpp
+  )
+endif ()
+
+
 add_library(kleeModule
   ${KLEE_MODULE_COMPONENT_SRCS}
 )
diff --git a/lib/Module/Instrument.cpp b/lib/Module/Instrument.cpp
new file mode 100644
index 00000000..bbb5df7c
--- /dev/null
+++ b/lib/Module/Instrument.cpp
@@ -0,0 +1,19 @@
+//===-- Instrument.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ModuleHelper.h"
+
+using namespace klee;
+
+void klee::checkModule(bool DontVerfify, llvm::Module *module) { assert(0); }
+
+void klee::instrument(bool CheckDivZero, bool CheckOvershift,
+                      llvm::Module *module) {
+  assert(0);
+}
\ No newline at end of file
diff --git a/lib/Module/InstrumentLegacy.cpp b/lib/Module/InstrumentLegacy.cpp
new file mode 100644
index 00000000..daae8043
--- /dev/null
+++ b/lib/Module/InstrumentLegacy.cpp
@@ -0,0 +1,125 @@
+//===-- InstrumentLegacy.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ModuleHelper.h"
+
+#include "Passes.h"
+#include "klee/Support/CompilerWarning.h"
+#include "klee/Support/ErrorHandling.h"
+
+DISABLE_WARNING_PUSH
+DISABLE_WARNING_DEPRECATED_DECLARATIONS
+#include "llvm/Bitcode/BitcodeWriter.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/ValueSymbolTable.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Scalar/Scalarizer.h"
+#include "llvm/Transforms/Utils.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+DISABLE_WARNING_POP
+
+using namespace llvm;
+using namespace klee;
+
+void klee::instrument(bool CheckDivZero, bool CheckOvershift,
+                      llvm::Module *module) {
+  // Inject checks prior to optimization... we also perform the
+  // invariant transformations that we will end up doing later so that
+  // optimize is seeing what is as close as possible to the final
+  // module.
+  legacy::PassManager pm;
+  pm.add(new RaiseAsmPass());
+
+  // This pass will scalarize as much code as possible so that the Executor
+  // does not need to handle operands of vector type for most instructions
+  // other than InsertElementInst and ExtractElementInst.
+  //
+  // NOTE: Must come before division/overshift checks because those passes
+  // don't know how to handle vector instructions.
+  pm.add(createScalarizerPass());
+
+  // This pass will replace atomic instructions with non-atomic operations
+  pm.add(createLowerAtomicPass());
+  if (CheckDivZero)
+    pm.add(new DivCheckPass());
+  if (CheckOvershift)
+    pm.add(new OvershiftCheckPass());
+
+  llvm::DataLayout targetData(module);
+  pm.add(new IntrinsicCleanerPass(targetData));
+  pm.run(*module);
+}
+
+void klee::checkModule(bool DontVerify, llvm::Module *module) {
+  InstructionOperandTypeCheckPass *operandTypeCheckPass =
+      new InstructionOperandTypeCheckPass();
+
+  legacy::PassManager pm;
+  if (!DontVerify)
+    pm.add(createVerifierPass());
+  pm.add(operandTypeCheckPass);
+  pm.run(*module);
+
+  // Enforce the operand type invariants that the Executor expects.  This
+  // implicitly depends on the "Scalarizer" pass to be run in order to succeed
+  // in the presence of vector instructions.
+  if (!operandTypeCheckPass->checkPassed()) {
+    klee_error("Unexpected instruction operand types detected");
+  }
+}
+
+void klee::optimiseAndPrepare(bool OptimiseKLEECall, bool Optimize,
+                              SwitchImplType SwitchType, std::string EntryPoint,
+                              llvm::ArrayRef<const char *> preservedFunctions,
+                              llvm::Module *module) {
+  // Preserve all functions containing klee-related function calls from being
+  // optimised around
+  if (!OptimiseKLEECall) {
+    legacy::PassManager pm;
+    pm.add(new OptNonePass());
+    pm.run(*module);
+  }
+
+  if (Optimize)
+    optimizeModule(module, preservedFunctions);
+
+  // Needs to happen after linking (since ctors/dtors can be modified)
+  // and optimization (since global optimization can rewrite lists).
+  injectStaticConstructorsAndDestructors(module, EntryPoint);
+
+  // Finally, run the passes that maintain invariants we expect during
+  // interpretation. We run the intrinsic cleaner just in case we
+  // linked in something with intrinsics but any external calls are
+  // going to be unresolved. We really need to handle the intrinsics
+  // directly I think?
+  legacy::PassManager pm3;
+  pm3.add(createCFGSimplificationPass());
+  switch (SwitchType) {
+  case SwitchImplType::eSwitchTypeInternal:
+    break;
+  case SwitchImplType::eSwitchTypeSimple:
+    pm3.add(new LowerSwitchPass());
+    break;
+  case SwitchImplType::eSwitchTypeLLVM:
+    pm3.add(createLowerSwitchPass());
+    break;
+  }
+
+  llvm::DataLayout targetData(module);
+  pm3.add(new IntrinsicCleanerPass(targetData));
+  pm3.add(createScalarizerPass());
+  pm3.add(new PhiCleanerPass());
+  pm3.add(new FunctionAliasPass());
+  pm3.run(*module);
+}
\ No newline at end of file
diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp
index eed922f8..cb8b4539 100644
--- a/lib/Module/KModule.cpp
+++ b/lib/Module/KModule.cpp
@@ -9,40 +9,27 @@
 
 #define DEBUG_TYPE "KModule"
 
+#include "klee/Module/KModule.h"
+
+#include "ModuleHelper.h"
 #include "Passes.h"
 
 #include "klee/Config/Version.h"
 #include "klee/Core/Interpreter.h"
-#include "klee/Support/OptionCategories.h"
 #include "klee/Module/Cell.h"
 #include "klee/Module/InstructionInfoTable.h"
 #include "klee/Module/KInstruction.h"
-#include "klee/Module/KModule.h"
 #include "klee/Support/Debug.h"
 #include "klee/Support/ErrorHandling.h"
 #include "klee/Support/ModuleUtil.h"
+#include "klee/Support/OptionCategories.h"
 
 #include "klee/Support/CompilerWarning.h"
+
 DISABLE_WARNING_PUSH
 DISABLE_WARNING_DEPRECATED_DECLARATIONS
 #include "llvm/Bitcode/BitcodeWriter.h"
-#include "llvm/IR/DataLayout.h"
 #include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
-#include "llvm/IR/ValueSymbolTable.h"
-#include "llvm/IR/Verifier.h"
-#include "llvm/Linker/Linker.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/raw_os_ostream.h"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Transforms/Scalar/Scalarizer.h"
-#include "llvm/Transforms/Utils/Cloning.h"
-#include "llvm/Transforms/Utils.h"
 DISABLE_WARNING_POP
 
 #include <sstream>
@@ -57,12 +44,6 @@ cl::OptionCategory
 }
 
 namespace {
-  enum SwitchImplType {
-    eSwitchTypeSimple,
-    eSwitchTypeLLVM,
-    eSwitchTypeInternal
-  };
-
   cl::opt<bool>
   OutputSource("output-source",
                cl::desc("Write the assembly for the final transformed source (default=true)"),
@@ -75,16 +56,6 @@ namespace {
                cl::init(false),
 	       cl::cat(ModuleCat));
 
-  cl::opt<SwitchImplType>
-  SwitchType("switch-type", cl::desc("Select the implementation of switch (default=internal)"),
-             cl::values(clEnumValN(eSwitchTypeSimple, "simple", 
-                                   "lower to ordered branches"),
-                        clEnumValN(eSwitchTypeLLVM, "llvm", 
-                                   "lower using LLVM"),
-                        clEnumValN(eSwitchTypeInternal, "internal", 
-                                   "execute switch internally")),
-             cl::init(eSwitchTypeInternal),
-	     cl::cat(ModuleCat));
   
   cl::opt<bool>
   DebugPrintEscapingFunctions("debug-print-escaping-functions", 
@@ -102,14 +73,21 @@ namespace {
                              cl::desc("Allow optimization of functions that "
                                       "contain KLEE calls (default=true)"),
                              cl::init(true), cl::cat(ModuleCat));
-}
+cl::opt<SwitchImplType> SwitchType(
+    "switch-type",
+    cl::desc("Select the implementation of switch (default=internal)"),
+    cl::values(clEnumValN(SwitchImplType::eSwitchTypeSimple, "simple",
+                          "lower to ordered branches"),
+               clEnumValN(SwitchImplType::eSwitchTypeLLVM, "llvm",
+                          "lower using LLVM"),
+               clEnumValN(SwitchImplType::eSwitchTypeInternal, "internal",
+                          "execute switch internally")),
+    cl::init(SwitchImplType::eSwitchTypeInternal), cl::cat(ModuleCat));
+
+} // namespace
 
 /***/
 
-namespace llvm {
-extern void Optimize(Module *, llvm::ArrayRef<const char *> preservedFunctions);
-}
-
 // what a hack
 static Function *getStubFunctionForCtorList(Module *m,
                                             GlobalVariable *gv, 
@@ -156,9 +134,8 @@ static Function *getStubFunctionForCtorList(Module *m,
   return fn;
 }
 
-static void
-injectStaticConstructorsAndDestructors(Module *m,
-                                       llvm::StringRef entryFunction) {
+void klee::injectStaticConstructorsAndDestructors(
+    Module *m, llvm::StringRef entryFunction) {
   GlobalVariable *ctors = m->getNamedGlobal("llvm.global_ctors");
   GlobalVariable *dtors = m->getNamedGlobal("llvm.global_dtors");
 
@@ -216,44 +193,12 @@ bool KModule::link(std::vector<std::unique_ptr<llvm::Module>> &modules,
 }
 
 void KModule::instrument(const Interpreter::ModuleOptions &opts) {
-  // Inject checks prior to optimization... we also perform the
-  // invariant transformations that we will end up doing later so that
-  // optimize is seeing what is as close as possible to the final
-  // module.
-  legacy::PassManager pm;
-  pm.add(new RaiseAsmPass());
-
-  // This pass will scalarize as much code as possible so that the Executor
-  // does not need to handle operands of vector type for most instructions
-  // other than InsertElementInst and ExtractElementInst.
-  //
-  // NOTE: Must come before division/overshift checks because those passes
-  // don't know how to handle vector instructions.
-  pm.add(createScalarizerPass());
-
-  // This pass will replace atomic instructions with non-atomic operations
-  pm.add(createLowerAtomicPass());
-  if (opts.CheckDivZero) pm.add(new DivCheckPass());
-  if (opts.CheckOvershift) pm.add(new OvershiftCheckPass());
-
-  pm.add(new IntrinsicCleanerPass(*targetData));
-  pm.run(*module);
+  klee::instrument(opts.CheckDivZero, opts.CheckOvershift, module.get());
 }
 
 void KModule::optimiseAndPrepare(
     const Interpreter::ModuleOptions &opts,
     llvm::ArrayRef<const char *> preservedFunctions) {
-  // Preserve all functions containing klee-related function calls from being
-  // optimised around
-  if (!OptimiseKLEECall) {
-    legacy::PassManager pm;
-    pm.add(new OptNonePass());
-    pm.run(*module);
-  }
-
-  if (opts.Optimize)
-    Optimize(module.get(), preservedFunctions);
-
   // Add internal functions which are not used to check if instructions
   // have been already visited
   if (opts.CheckDivZero)
@@ -261,28 +206,8 @@ void KModule::optimiseAndPrepare(
   if (opts.CheckOvershift)
     addInternalFunction("klee_overshift_check");
 
-  // Needs to happen after linking (since ctors/dtors can be modified)
-  // and optimization (since global optimization can rewrite lists).
-  injectStaticConstructorsAndDestructors(module.get(), opts.EntryPoint);
-
-  // Finally, run the passes that maintain invariants we expect during
-  // interpretation. We run the intrinsic cleaner just in case we
-  // linked in something with intrinsics but any external calls are
-  // going to be unresolved. We really need to handle the intrinsics
-  // directly I think?
-  legacy::PassManager pm3;
-  pm3.add(createCFGSimplificationPass());
-  switch(SwitchType) {
-  case eSwitchTypeInternal: break;
-  case eSwitchTypeSimple: pm3.add(new LowerSwitchPass()); break;
-  case eSwitchTypeLLVM:  pm3.add(createLowerSwitchPass()); break;
-  default: klee_error("invalid --switch-type");
-  }
-  pm3.add(new IntrinsicCleanerPass(*targetData));
-  pm3.add(createScalarizerPass());
-  pm3.add(new PhiCleanerPass());
-  pm3.add(new FunctionAliasPass());
-  pm3.run(*module);
+  klee::optimiseAndPrepare(OptimiseKLEECall, opts.Optimize, SwitchType,
+                           opts.EntryPoint, preservedFunctions, module.get());
 }
 
 void KModule::manifest(InterpreterHandler *ih, bool forceSourceOutput) {
@@ -294,7 +219,7 @@ void KModule::manifest(InterpreterHandler *ih, bool forceSourceOutput) {
 
   if (OutputModule) {
     std::unique_ptr<llvm::raw_fd_ostream> f(ih->openOutputFile("final.bc"));
-    WriteBitcodeToFile(*module, *f);
+    llvm::WriteBitcodeToFile(*module, *f);
   }
 
   /* Build shadow structures */
@@ -343,23 +268,7 @@ void KModule::manifest(InterpreterHandler *ih, bool forceSourceOutput) {
   }
 }
 
-void KModule::checkModule() {
-  InstructionOperandTypeCheckPass *operandTypeCheckPass =
-      new InstructionOperandTypeCheckPass();
-
-  legacy::PassManager pm;
-  if (!DontVerify)
-    pm.add(createVerifierPass());
-  pm.add(operandTypeCheckPass);
-  pm.run(*module);
-
-  // Enforce the operand type invariants that the Executor expects.  This
-  // implicitly depends on the "Scalarizer" pass to be run in order to succeed
-  // in the presence of vector instructions.
-  if (!operandTypeCheckPass->checkPassed()) {
-    klee_error("Unexpected instruction operand types detected");
-  }
-}
+void KModule::checkModule() { klee::checkModule(DontVerify, module.get()); }
 
 KConstant* KModule::getKConstant(const Constant *c) {
   auto it = constantMap.find(c);
diff --git a/lib/Module/ModuleHelper.h b/lib/Module/ModuleHelper.h
new file mode 100644
index 00000000..1b279edd
--- /dev/null
+++ b/lib/Module/ModuleHelper.h
@@ -0,0 +1,37 @@
+//===-- ModuleHelper.h ------------------------------------------*- C++ -*-===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef KLEE_MODULEHELPER_H
+#define KLEE_MODULEHELPER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/Module.h"
+
+namespace klee {
+enum class SwitchImplType {
+  eSwitchTypeSimple,
+  eSwitchTypeLLVM,
+  eSwitchTypeInternal
+};
+
+void optimiseAndPrepare(bool OptimiseKLEECall, bool Optimize,
+                        SwitchImplType SwitchType, std::string EntryPoint,
+                        llvm::ArrayRef<const char *> preservedFunctions,
+                        llvm::Module *module);
+void checkModule(bool DontVerfify, llvm::Module *module);
+void instrument(bool CheckDivZero, bool CheckOvershift, llvm::Module *module);
+
+void injectStaticConstructorsAndDestructors(llvm::Module *m,
+                                            llvm::StringRef entryFunction);
+
+void optimizeModule(llvm::Module *M,
+                    llvm::ArrayRef<const char *> preservedFunctions);
+} // namespace klee
+
+#endif // KLEE_MODULEHELPER_H
diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp
index 35b9805a..9475512b 100644
--- a/lib/Module/Optimize.cpp
+++ b/lib/Module/Optimize.cpp
@@ -15,247 +15,14 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "klee/Config/Version.h"
-#include "klee/Support/OptionCategories.h"
+#include "ModuleHelper.h"
 
-#include "klee/Support/CompilerWarning.h"
-DISABLE_WARNING_PUSH
-DISABLE_WARNING_DEPRECATED_DECLARATIONS
-#include "llvm/Analysis/GlobalsModRef.h"
-#include "llvm/Analysis/Passes.h"
-#include "llvm/Analysis/LoopPass.h"
 #include "llvm/IR/Module.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/IR/Verifier.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/PluginLoader.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Transforms/InstCombine/InstCombine.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/IPO/FunctionAttrs.h"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Transforms/Scalar/GVN.h"
-#include "llvm/Transforms/Utils.h"
-DISABLE_WARNING_POP
 
-using namespace llvm;
-
-static cl::opt<bool>
-    DisableInline("disable-inlining",
-                  cl::desc("Do not run the inliner pass (default=false)"),
-                  cl::init(false), cl::cat(klee::ModuleCat));
-
-static cl::opt<bool> DisableInternalize(
-    "disable-internalize",
-    cl::desc("Do not mark all symbols as internal (default=false)"),
-    cl::init(false), cl::cat(klee::ModuleCat));
-
-static cl::opt<bool> VerifyEach(
-    "verify-each",
-    cl::desc("Verify intermediate results of all optimization passes (default=false)"),
-    cl::init(false),
-    cl::cat(klee::ModuleCat));
-
-static cl::alias ExportDynamic("export-dynamic",
-                               cl::aliasopt(DisableInternalize),
-                               cl::desc("Alias for -disable-internalize"));
-
-static cl::opt<bool>
-    Strip("strip-all", cl::desc("Strip all symbol information from executable"),
-          cl::init(false), cl::cat(klee::ModuleCat));
-
-static cl::alias A0("s", cl::desc("Alias for --strip-all"),
-                    cl::aliasopt(Strip));
-
-static cl::opt<bool>
-    StripDebug("strip-debug",
-               cl::desc("Strip debugger symbol info from executable"),
-               cl::init(false), cl::cat(klee::ModuleCat));
-
-static cl::alias A1("S", cl::desc("Alias for --strip-debug"),
-                    cl::aliasopt(StripDebug));
-
-// A utility function that adds a pass to the pass manager but will also add
-// a verifier pass after if we're supposed to verify.
-static inline void addPass(legacy::PassManager &PM, Pass *P) {
-  // Add the pass to the pass manager...
-  PM.add(P);
-
-  // If we are verifying all of the intermediate steps, add the verifier...
-  if (VerifyEach)
-    PM.add(createVerifierPass());
-}
-
-namespace llvm {
-
-
-static void AddStandardCompilePasses(legacy::PassManager &PM) {
-  PM.add(createVerifierPass());                  // Verify that input is correct
-
-  // If the -strip-debug command line option was specified, do it.
-  if (StripDebug)
-    addPass(PM, createStripSymbolsPass(true));
-
-  addPass(PM, createCFGSimplificationPass());    // Clean up disgusting code
-  addPass(PM, createPromoteMemoryToRegisterPass());// Kill useless allocas
-  addPass(PM, createGlobalOptimizerPass());      // Optimize out global vars
-  addPass(PM, createGlobalDCEPass());            // Remove unused fns and globs
-#if LLVM_VERSION_CODE >= LLVM_VERSION(11, 0)
-  addPass(PM, createSCCPPass());                 // Constant prop with SCCP
-#else
-  addPass(PM, createIPConstantPropagationPass());// IP Constant Propagation
-#endif
-  addPass(PM, createDeadArgEliminationPass());   // Dead argument elimination
-  addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE
-  addPass(PM, createCFGSimplificationPass());    // Clean up after IPCP & DAE
-
-  addPass(PM, createPruneEHPass());              // Remove dead EH info
-  addPass(PM, createPostOrderFunctionAttrsLegacyPass());
-  addPass(PM, createReversePostOrderFunctionAttrsPass()); // Deduce function attrs
-
-  if (!DisableInline)
-    addPass(PM, createFunctionInliningPass());   // Inline small functions
-  addPass(PM, createArgumentPromotionPass());    // Scalarize uninlined fn args
-
-  addPass(PM, createInstructionCombiningPass()); // Cleanup for scalarrepl.
-  addPass(PM, createJumpThreadingPass());        // Thread jumps.
-  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
-  addPass(PM, createSROAPass());                 // Break up aggregate allocas
-  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
-
-  addPass(PM, createTailCallEliminationPass());  // Eliminate tail calls
-  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
-  addPass(PM, createReassociatePass());          // Reassociate expressions
-  addPass(PM, createLoopRotatePass());
-  addPass(PM, createLICMPass());                 // Hoist loop invariants
-  addPass(PM, createLoopUnswitchPass());         // Unswitch loops.
-  // FIXME : Removing instcombine causes nestedloop regression.
-  addPass(PM, createInstructionCombiningPass());
-  addPass(PM, createIndVarSimplifyPass());       // Canonicalize indvars
-  addPass(PM, createLoopDeletionPass());         // Delete dead loops
-  addPass(PM, createLoopUnrollPass());           // Unroll small loops
-  addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
-  addPass(PM, createGVNPass());                  // Remove redundancies
-  addPass(PM, createMemCpyOptPass());            // Remove memcpy / form memset
-  addPass(PM, createSCCPPass());                 // Constant prop with SCCP
-
-  // Run instcombine after redundancy elimination to exploit opportunities
-  // opened up by them.
-  addPass(PM, createInstructionCombiningPass());
-
-  addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores
-  addPass(PM, createAggressiveDCEPass());        // Delete dead instructions
-  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
-  addPass(PM, createStripDeadPrototypesPass());  // Get rid of dead prototypes
-  addPass(PM, createConstantMergePass());        // Merge dup global constants
-}
-
-/// Optimize - Perform link time optimizations. This will run the scalar
-/// optimizations, any loaded plugin-optimization modules, and then the
-/// inter-procedural optimizations if applicable.
-void Optimize(Module *M, llvm::ArrayRef<const char *> preservedFunctions) {
-
-  // Instantiate the pass manager to organize the passes.
-  legacy::PassManager Passes;
-
-  // If we're verifying, start off with a verification pass.
-  if (VerifyEach)
-    Passes.add(createVerifierPass());
-
-  // DWD - Run the opt standard pass list as well.
-  AddStandardCompilePasses(Passes);
-
-  // Now that composite has been compiled, scan through the module, looking
-  // for a main function.  If main is defined, mark all other functions
-  // internal.
-  if (!DisableInternalize) {
-    auto PreserveFunctions = [=](const GlobalValue &GV) {
-      StringRef GVName = GV.getName();
-
-      for (const char *fun : preservedFunctions)
-        if (GVName.equals(fun))
-          return true;
-
-      return false;
-    };
-    ModulePass *pass = createInternalizePass(PreserveFunctions);
-    addPass(Passes, pass);
-  }
-
-  // Propagate constants at call sites into the functions they call.  This
-  // opens opportunities for globalopt (and inlining) by substituting function
-  // pointers passed as arguments to direct uses of functions.
-  addPass(Passes, createIPSCCPPass());
-
-  // Now that we internalized some globals, see if we can hack on them!
-  addPass(Passes, createGlobalOptimizerPass());
-
-  // Linking modules together can lead to duplicated global constants, only
-  // keep one copy of each constant...
-  addPass(Passes, createConstantMergePass());
-
-  // Remove unused arguments from functions...
-  addPass(Passes, createDeadArgEliminationPass());
-
-  // Reduce the code after globalopt and ipsccp.  Both can open up significant
-  // simplification opportunities, and both can propagate functions through
-  // function pointers.  When this happens, we often have to resolve varargs
-  // calls, etc, so let instcombine do this.
-  addPass(Passes, createInstructionCombiningPass());
-
-  if (!DisableInline)
-    addPass(Passes, createFunctionInliningPass()); // Inline small functions
-
-  addPass(Passes, createPruneEHPass());         // Remove dead EH info
-  addPass(Passes, createGlobalOptimizerPass()); // Optimize globals again.
-  addPass(Passes, createGlobalDCEPass());       // Remove dead functions
-
-  // If we didn't decide to inline a function, check to see if we can
-  // transform it to pass arguments by value instead of by reference.
-  addPass(Passes, createArgumentPromotionPass());
-
-  // The IPO passes may leave cruft around.  Clean up after them.
-  addPass(Passes, createInstructionCombiningPass());
-  addPass(Passes, createJumpThreadingPass()); // Thread jumps.
-  addPass(Passes, createSROAPass()); // Break up allocas
-
-  // Run a few AA driven optimizations here and now, to cleanup the code.
-  addPass(Passes, createPostOrderFunctionAttrsLegacyPass());
-  addPass(Passes, createReversePostOrderFunctionAttrsPass()); // Add nocapture
-  addPass(Passes, createGlobalsAAWrapperPass()); // IP alias analysis
-
-  addPass(Passes, createLICMPass());                 // Hoist loop invariants
-  addPass(Passes, createGVNPass());                  // Remove redundancies
-  addPass(Passes, createMemCpyOptPass());            // Remove dead memcpy's
-  addPass(Passes, createDeadStoreEliminationPass()); // Nuke dead stores
-
-  // Cleanup and simplify the code after the scalar optimizations.
-  addPass(Passes, createInstructionCombiningPass());
-
-  addPass(Passes, createJumpThreadingPass());           // Thread jumps.
-  addPass(Passes, createPromoteMemoryToRegisterPass()); // Cleanup jumpthread.
-
-  // Delete basic blocks, which optimization passes may have killed...
-  addPass(Passes, createCFGSimplificationPass());
-
-  // Now that we have optimized the program, discard unreachable functions...
-  addPass(Passes, createGlobalDCEPass());
-
-  // If the -s or -S command line options were specified, strip the symbols out
-  // of the resulting program to make it smaller.  -s and -S are GNU ld options
-  // that we are supporting; they alias -strip-all and -strip-debug.
-  if (Strip || StripDebug)
-    addPass(Passes, createStripSymbolsPass(StripDebug && !Strip));
-
-  // The user's passes may leave cruft around; clean up after them.
-  addPass(Passes, createInstructionCombiningPass());
-  addPass(Passes, createCFGSimplificationPass());
-  addPass(Passes, createAggressiveDCEPass());
-  addPass(Passes, createGlobalDCEPass());
-
-  // Run our queue of passes all at once now, efficiently.
-  Passes.run(*M);
-}
-}
+using namespace klee;
+void klee::optimiseAndPrepare(bool OptimiseKLEECall, bool Optimize,
+                              SwitchImplType SwitchType, std::string EntryPoint,
+                              llvm::ArrayRef<const char *> preservedFunctions,
+                              llvm::Module *module) {
+  assert(0);
+}
\ No newline at end of file
diff --git a/lib/Module/OptimizeLegacy.cpp b/lib/Module/OptimizeLegacy.cpp
new file mode 100644
index 00000000..53488924
--- /dev/null
+++ b/lib/Module/OptimizeLegacy.cpp
@@ -0,0 +1,249 @@
+// FIXME: This file is a bastard child of opt.cpp and llvm-ld's
+// Optimize.cpp. This stuff should live in common code.
+
+//===- Optimize.cpp - Optimize a complete program -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements all optimization of the linked module for llvm-ld.
+//
+//===----------------------------------------------------------------------===//
+
+#include "klee/Config/Version.h"
+#include "klee/Support/OptionCategories.h"
+
+#include "klee/Support/CompilerWarning.h"
+
+#include "ModuleHelper.h"
+
+DISABLE_WARNING_PUSH
+DISABLE_WARNING_DEPRECATED_DECLARATIONS
+#include "llvm/Analysis/GlobalsModRef.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/FunctionAttrs.h"
+#include "llvm/Transforms/InstCombine/InstCombine.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Scalar/GVN.h"
+#include "llvm/Transforms/Utils.h"
+DISABLE_WARNING_POP
+
+using namespace llvm;
+using namespace klee;
+
+namespace {
+static cl::opt<bool>
+    DisableInline("disable-inlining",
+                  cl::desc("Do not run the inliner pass (default=false)"),
+                  cl::init(false), cl::cat(klee::ModuleCat));
+
+static cl::opt<bool> DisableInternalize(
+    "disable-internalize",
+    cl::desc("Do not mark all symbols as internal (default=false)"),
+    cl::init(false), cl::cat(klee::ModuleCat));
+
+static cl::opt<bool> VerifyEach("verify-each",
+                                cl::desc("Verify intermediate results of all "
+                                         "optimization passes (default=false)"),
+                                cl::init(false), cl::cat(klee::ModuleCat));
+
+static cl::opt<bool>
+    Strip("strip-all", cl::desc("Strip all symbol information from executable"),
+          cl::init(false), cl::cat(klee::ModuleCat));
+
+static cl::opt<bool>
+    StripDebug("strip-debug",
+               cl::desc("Strip debugger symbol info from executable"),
+               cl::init(false), cl::cat(klee::ModuleCat));
+
+// A utility function that adds a pass to the pass manager but will also add
+// a verifier pass after if we're supposed to verify.
+static inline void addPass(legacy::PassManager &PM, Pass *P) {
+  // Add the pass to the pass manager...
+  PM.add(P);
+
+  // If we are verifying all of the intermediate steps, add the verifier...
+  if (VerifyEach)
+    PM.add(createVerifierPass());
+}
+} // namespace
+
+static void AddStandardCompilePasses(legacy::PassManager &PM) {
+  PM.add(createVerifierPass()); // Verify that input is correct
+
+  // If the -strip-debug command line option was specified, do it.
+  if (StripDebug)
+    addPass(PM, createStripSymbolsPass(true));
+
+  addPass(PM, createCFGSimplificationPass());       // Clean up disgusting code
+  addPass(PM, createPromoteMemoryToRegisterPass()); // Kill useless allocas
+  addPass(PM, createGlobalOptimizerPass());         // Optimize out global vars
+  addPass(PM, createGlobalDCEPass()); // Remove unused fns and globs
+#if LLVM_VERSION_CODE >= LLVM_VERSION(11, 0)
+  addPass(PM, createSCCPPass()); // Constant prop with SCCP
+#else
+  addPass(PM, createIPConstantPropagationPass()); // IP Constant Propagation
+#endif
+  addPass(PM, createDeadArgEliminationPass());   // Dead argument elimination
+  addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE
+  addPass(PM, createCFGSimplificationPass());    // Clean up after IPCP & DAE
+
+  addPass(PM, createPruneEHPass()); // Remove dead EH info
+  addPass(PM, createPostOrderFunctionAttrsLegacyPass());
+  addPass(PM,
+          createReversePostOrderFunctionAttrsPass()); // Deduce function attrs
+
+  if (!DisableInline)
+    addPass(PM, createFunctionInliningPass()); // Inline small functions
+  addPass(PM, createArgumentPromotionPass());  // Scalarize uninlined fn args
+
+  addPass(PM, createInstructionCombiningPass()); // Cleanup for scalarrepl.
+  addPass(PM, createJumpThreadingPass());        // Thread jumps.
+  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
+  addPass(PM, createSROAPass());                 // Break up aggregate allocas
+  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
+
+  addPass(PM, createTailCallEliminationPass()); // Eliminate tail calls
+  addPass(PM, createCFGSimplificationPass());   // Merge & remove BBs
+  addPass(PM, createReassociatePass());         // Reassociate expressions
+  addPass(PM, createLoopRotatePass());
+  addPass(PM, createLICMPass());         // Hoist loop invariants
+  addPass(PM, createLoopUnswitchPass()); // Unswitch loops.
+  // FIXME : Removing instcombine causes nestedloop regression.
+  addPass(PM, createInstructionCombiningPass());
+  addPass(PM, createIndVarSimplifyPass());       // Canonicalize indvars
+  addPass(PM, createLoopDeletionPass());         // Delete dead loops
+  addPass(PM, createLoopUnrollPass());           // Unroll small loops
+  addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
+  addPass(PM, createGVNPass());                  // Remove redundancies
+  addPass(PM, createMemCpyOptPass());            // Remove memcpy / form memset
+  addPass(PM, createSCCPPass());                 // Constant prop with SCCP
+
+  // Run instcombine after redundancy elimination to exploit opportunities
+  // opened up by them.
+  addPass(PM, createInstructionCombiningPass());
+
+  addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores
+  addPass(PM, createAggressiveDCEPass());        // Delete dead instructions
+  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
+  addPass(PM, createStripDeadPrototypesPass());  // Get rid of dead prototypes
+  addPass(PM, createConstantMergePass());        // Merge dup global constants
+}
+
+/// Optimize - Perform link time optimizations. This will run the scalar
+/// optimizations, any loaded plugin-optimization modules, and then the
+/// inter-procedural optimizations if applicable.
+void klee::optimizeModule(llvm::Module *M,
+                          llvm::ArrayRef<const char *> preservedFunctions) {
+
+  // Instantiate the pass manager to organize the passes.
+  legacy::PassManager Passes;
+
+  // If we're verifying, start off with a verification pass.
+  if (VerifyEach)
+    Passes.add(createVerifierPass());
+
+  // DWD - Run the opt standard pass list as well.
+  AddStandardCompilePasses(Passes);
+
+  // Now that composite has been compiled, scan through the module, looking
+  // for a main function.  If main is defined, mark all other functions
+  // internal.
+  if (!DisableInternalize) {
+    auto PreserveFunctions = [=](const llvm::GlobalValue &GV) {
+      StringRef GVName = GV.getName();
+
+      for (const char *fun : preservedFunctions)
+        if (GVName.equals(fun))
+          return true;
+
+      return false;
+    };
+    ModulePass *pass = createInternalizePass(PreserveFunctions);
+    addPass(Passes, pass);
+  }
+
+  // Propagate constants at call sites into the functions they call.  This
+  // opens opportunities for globalopt (and inlining) by substituting function
+  // pointers passed as arguments to direct uses of functions.
+  addPass(Passes, createIPSCCPPass());
+
+  // Now that we internalized some globals, see if we can hack on them!
+  addPass(Passes, createGlobalOptimizerPass());
+
+  // Linking modules together can lead to duplicated global constants, only
+  // keep one copy of each constant...
+  addPass(Passes, createConstantMergePass());
+
+  // Remove unused arguments from functions...
+  addPass(Passes, createDeadArgEliminationPass());
+
+  // Reduce the code after globalopt and ipsccp.  Both can open up significant
+  // simplification opportunities, and both can propagate functions through
+  // function pointers.  When this happens, we often have to resolve varargs
+  // calls, etc, so let instcombine do this.
+  addPass(Passes, createInstructionCombiningPass());
+
+  if (!DisableInline)
+    addPass(Passes, createFunctionInliningPass()); // Inline small functions
+
+  addPass(Passes, createPruneEHPass());         // Remove dead EH info
+  addPass(Passes, createGlobalOptimizerPass()); // Optimize globals again.
+  addPass(Passes, createGlobalDCEPass());       // Remove dead functions
+
+  // If we didn't decide to inline a function, check to see if we can
+  // transform it to pass arguments by value instead of by reference.
+  addPass(Passes, createArgumentPromotionPass());
+
+  // The IPO passes may leave cruft around.  Clean up after them.
+  addPass(Passes, createInstructionCombiningPass());
+  addPass(Passes, createJumpThreadingPass()); // Thread jumps.
+  addPass(Passes, createSROAPass());          // Break up allocas
+
+  // Run a few AA driven optimizations here and now, to cleanup the code.
+  addPass(Passes, createPostOrderFunctionAttrsLegacyPass());
+  addPass(Passes, createReversePostOrderFunctionAttrsPass()); // Add nocapture
+  addPass(Passes, createGlobalsAAWrapperPass()); // IP alias analysis
+
+  addPass(Passes, createLICMPass());                 // Hoist loop invariants
+  addPass(Passes, createGVNPass());                  // Remove redundancies
+  addPass(Passes, createMemCpyOptPass());            // Remove dead memcpy's
+  addPass(Passes, createDeadStoreEliminationPass()); // Nuke dead stores
+
+  // Cleanup and simplify the code after the scalar optimizations.
+  addPass(Passes, createInstructionCombiningPass());
+
+  addPass(Passes, createJumpThreadingPass());           // Thread jumps.
+  addPass(Passes, createPromoteMemoryToRegisterPass()); // Cleanup jumpthread.
+
+  // Delete basic blocks, which optimization passes may have killed...
+  addPass(Passes, createCFGSimplificationPass());
+
+  // Now that we have optimized the program, discard unreachable functions...
+  addPass(Passes, createGlobalDCEPass());
+
+  // If the -s or -S command line options were specified, strip the symbols out
+  // of the resulting program to make it smaller.  -s and -S are GNU ld options
+  // that we are supporting; they alias -strip-all and -strip-debug.
+  if (Strip || StripDebug)
+    addPass(Passes, createStripSymbolsPass(StripDebug && !Strip));
+
+  // The user's passes may leave cruft around; clean up after them.
+  addPass(Passes, createInstructionCombiningPass());
+  addPass(Passes, createCFGSimplificationPass());
+  addPass(Passes, createAggressiveDCEPass());
+  addPass(Passes, createGlobalDCEPass());
+
+  // Run our queue of passes all at once now, efficiently.
+  Passes.run(*M);
+}