From f3af5d27bf51c3617b7a79d066cb5749643edbcb Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 16 Jun 2024 01:01:49 -0400 Subject: [PATCH] xo-jit: move IR improvement pipeline to dedicated class --- include/xo/jit/IrPipeline.hpp | 75 +++++++++++++++++++++++++++++++++++ include/xo/jit/Jit.hpp | 18 +-------- src/jit/CMakeLists.txt | 1 + src/jit/IrPipeline.cpp | 45 +++++++++++++++++++++ src/jit/Jit.cpp | 27 ++----------- 5 files changed, 126 insertions(+), 40 deletions(-) create mode 100644 include/xo/jit/IrPipeline.hpp create mode 100644 src/jit/IrPipeline.cpp diff --git a/include/xo/jit/IrPipeline.hpp b/include/xo/jit/IrPipeline.hpp new file mode 100644 index 00000000..8719fbe2 --- /dev/null +++ b/include/xo/jit/IrPipeline.hpp @@ -0,0 +1,75 @@ +/** @file IrPipeline.hpp + * + * Author: Roland Conybeare + **/ + +#pragma once + +#include "xo/refcnt/Refcounted.hpp" + +/* stuff from kaleidoscope.cpp */ +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/StandardInstrumentations.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "llvm/Transforms/Scalar/Reassociate.h" +#include "llvm/Transforms/Scalar/SimplifyCFG.h" + +//#include + +namespace xo { + namespace jit { + /** @class IrPipeline + * @brief represent an LLVM IR pipeline + * + * Represents analysis/transformation short of generating + * machine-code. For now pipeline stages are hardwired; + * adapted from the LLVM Kaleidoscope example project. + * + * Conversely, pipeline *starts* with code already that has + * already been expressed in LLVM IR + **/ + class IrPipeline : public ref::Refcount { + public: + explicit IrPipeline(llvm::LLVMContext & llvm_cx); + + void run_pipeline(llvm::Function & fn); + + private: + // ----- transforms (also adapted from kaleidescope.cpp) ------ + + /** manages all the passes+analaysis (?) **/ + std::unique_ptr llvm_fpmgr_; + /** loop analysis (?) **/ + std::unique_ptr llvm_lamgr_; + /** function-level analysis (?) **/ + std::unique_ptr llvm_famgr_; + /** cgscc (?) analysis **/ + std::unique_ptr llvm_cgamgr_; + /** module analsyis (?) **/ + std::unique_ptr llvm_mamgr_; + /** pass instrumentation **/ + std::unique_ptr llvm_pic_; + /** standard instrumentation **/ + std::unique_ptr llvm_si_; + }; /*IrPipeline*/ + } /*namespace jit*/ +} /*namespace xo*/ + + +/** end IrPipeline.hpp **/ diff --git a/include/xo/jit/Jit.hpp b/include/xo/jit/Jit.hpp index 14b368d3..f5eb65a4 100644 --- a/include/xo/jit/Jit.hpp +++ b/include/xo/jit/Jit.hpp @@ -8,6 +8,7 @@ //#include #include "xo/refcnt/Refcounted.hpp" +#include "IrPipeline.hpp" #include "xo/expression/Expression.hpp" #include "xo/expression/ConstantInterface.hpp" #include "xo/expression/PrimitiveInterface.hpp" @@ -150,6 +151,7 @@ namespace xo { * kal_jit_.addModule() * Note that this makes the module itself unavailable to us **/ + xo::ref::rp ir_pipeline_; /** owns + manages core "global" llvm data, * including type- and constant- unique-ing tables. @@ -176,22 +178,6 @@ namespace xo { **/ std::map nested_env_; - // ----- transforms (also adapted from kaleidescope.cpp) ------ - - /** manages all the passes+analaysis (?) **/ - std::unique_ptr llvm_fpmgr_; - /** loop analysis (?) **/ - std::unique_ptr llvm_lamgr_; - /** function-level analysis (?) **/ - std::unique_ptr llvm_famgr_; - /** cgscc (?) analysis **/ - std::unique_ptr llvm_cgamgr_; - /** module analsyis (?) **/ - std::unique_ptr llvm_mamgr_; - /** pass instrumentation **/ - std::unique_ptr llvm_pic_; - /** standard instrumentation **/ - std::unique_ptr llvm_si_; }; /*Jit*/ inline std::ostream & diff --git a/src/jit/CMakeLists.txt b/src/jit/CMakeLists.txt index abd3c903..bbf5aa99 100644 --- a/src/jit/CMakeLists.txt +++ b/src/jit/CMakeLists.txt @@ -2,6 +2,7 @@ set(SELF_LIB xo_jit) set(SELF_SRCS + IrPipeline.cpp Jit.cpp ) diff --git a/src/jit/IrPipeline.cpp b/src/jit/IrPipeline.cpp new file mode 100644 index 00000000..200d3a52 --- /dev/null +++ b/src/jit/IrPipeline.cpp @@ -0,0 +1,45 @@ +/* @file IrPipeline.cpp */ + +#include "IrPipeline.hpp" + +namespace xo { + namespace jit { + IrPipeline::IrPipeline(llvm::LLVMContext & llvm_cx) + { + using std::make_unique; + + this->llvm_fpmgr_ = make_unique(); + this->llvm_lamgr_ = std::make_unique(); + this->llvm_famgr_ = std::make_unique(); + this->llvm_cgamgr_ = std::make_unique(); + this->llvm_mamgr_ = std::make_unique(); + this->llvm_pic_ = std::make_unique(); + this->llvm_si_ = std::make_unique(llvm_cx, + /*DebugLogging*/ true); + + this->llvm_si_->registerCallbacks(*llvm_pic_, llvm_mamgr_.get()); + + /** transform passes **/ + this->llvm_fpmgr_->addPass(llvm::InstCombinePass()); + this->llvm_fpmgr_->addPass(llvm::ReassociatePass()); + this->llvm_fpmgr_->addPass(llvm::GVNPass()); + this->llvm_fpmgr_->addPass(llvm::SimplifyCFGPass()); + + /** tracking for analysis passes that share info? **/ + llvm::PassBuilder llvm_pass_builder; + llvm_pass_builder.registerModuleAnalyses(*llvm_mamgr_); + llvm_pass_builder.registerFunctionAnalyses(*llvm_famgr_); + llvm_pass_builder.crossRegisterProxies(*llvm_lamgr_, *llvm_famgr_, *llvm_cgamgr_, *llvm_mamgr_); + } /*ctor*/ + + void + IrPipeline::run_pipeline(llvm::Function & fn) + { + llvm_fpmgr_->run(fn, *llvm_famgr_); + } /*run_pipeline*/ + } /*namespace jit*/ +} /*namespace xo*/ + + + +/* end IrPipeline.cpp */ diff --git a/src/jit/Jit.cpp b/src/jit/Jit.cpp index 1f660348..67752b7b 100644 --- a/src/jit/Jit.cpp +++ b/src/jit/Jit.cpp @@ -148,28 +148,7 @@ namespace xo { throw std::runtime_error("Jit::ctor: expected non-empty llvm module"); } - this->llvm_fpmgr_ = std::make_unique(); - this->llvm_lamgr_ = std::make_unique(); - this->llvm_famgr_ = std::make_unique(); - this->llvm_cgamgr_ = std::make_unique(); - this->llvm_mamgr_ = std::make_unique(); - this->llvm_pic_ = std::make_unique(); - this->llvm_si_ = std::make_unique(*llvm_cx_, - /*DebugLogging*/ true); - - this->llvm_si_->registerCallbacks(*llvm_pic_, llvm_mamgr_.get()); - - /** transform passes **/ - this->llvm_fpmgr_->addPass(llvm::InstCombinePass()); - this->llvm_fpmgr_->addPass(llvm::ReassociatePass()); - this->llvm_fpmgr_->addPass(llvm::GVNPass()); - this->llvm_fpmgr_->addPass(llvm::SimplifyCFGPass()); - - /** tracking for analysis passes that share info? **/ - llvm::PassBuilder llvm_pass_builder; - llvm_pass_builder.registerModuleAnalyses(*llvm_mamgr_); - llvm_pass_builder.registerFunctionAnalyses(*llvm_famgr_); - llvm_pass_builder.crossRegisterProxies(*llvm_lamgr_, *llvm_famgr_, *llvm_cgamgr_, *llvm_mamgr_); + ir_pipeline_ = new IrPipeline(*llvm_cx_); } /*recreate_llvm_ir_pipeline*/ const std::string & @@ -420,8 +399,8 @@ namespace xo { /* validate! always validate! */ llvm::verifyFunction(*fn); - /* optimize! does this generate code? */ - llvm_fpmgr_->run(*fn, *llvm_famgr_); + /* optimize! improves IR */ + ir_pipeline_->run_pipeline(*fn); // llvm_fpmgr_->run(*fn, *llvm_famgr_); return fn; }