diff --git a/source/runtime/backend/arm64/jit/jit_context.cpp b/source/runtime/backend/arm64/jit/jit_context.cpp index 5a44c8f..93db36b 100644 --- a/source/runtime/backend/arm64/jit/jit_context.cpp +++ b/source/runtime/backend/arm64/jit/jit_context.cpp @@ -20,6 +20,16 @@ VRegister JitContext::V(const ir::Value& value) { return VRegister::GetVRegFromCode(reg.id); } +Register JitContext::GetTmpX(const ir::Value& value) { + auto reg = reg_alloc.GetTmpGPR(); + return XRegister::GetXRegFromCode(reg.id); +} + +VRegister JitContext::GetTmpV(const ir::Value& value) { + auto reg = reg_alloc.GetTmpFPR(); + return VRegister::GetVRegFromCode(reg.id); +} + void JitContext::Forward(ir::Location location) { } diff --git a/source/runtime/backend/arm64/jit/jit_context.h b/source/runtime/backend/arm64/jit/jit_context.h index 99f358d..ec2fd2a 100644 --- a/source/runtime/backend/arm64/jit/jit_context.h +++ b/source/runtime/backend/arm64/jit/jit_context.h @@ -24,6 +24,9 @@ class JitContext : DeleteCopyAndMove { Register X(const ir::Value &value); VRegister V(const ir::Value &value); + Register GetTmpX(const ir::Value &value); + VRegister GetTmpV(const ir::Value &value); + void Forward(ir::Location location); void Forward(const Register &location); void Finish(); diff --git a/source/runtime/backend/reg_alloc.cpp b/source/runtime/backend/reg_alloc.cpp index 43a4a52..3de5bb3 100644 --- a/source/runtime/backend/reg_alloc.cpp +++ b/source/runtime/backend/reg_alloc.cpp @@ -44,6 +44,7 @@ const GPRSMask& RegAlloc::GetGprs() const { return gprs; } const FPRSMask& RegAlloc::GetFprs() const { return fprs; } ir::HostGPR RegAlloc::GetTmpGPR() { + return ir::HostGPR{1}; } diff --git a/source/runtime/backend/riscv64/jit/jit_context.cpp b/source/runtime/backend/riscv64/jit/jit_context.cpp new file mode 100644 index 0000000..4143bf2 --- /dev/null +++ b/source/runtime/backend/riscv64/jit/jit_context.cpp @@ -0,0 +1,5 @@ +// +// Created by 甘尧 on 2023/12/13. +// + +#include "jit_context.h" diff --git a/source/runtime/backend/riscv64/jit/jit_context.h b/source/runtime/backend/riscv64/jit/jit_context.h new file mode 100644 index 0000000..384ac7c --- /dev/null +++ b/source/runtime/backend/riscv64/jit/jit_context.h @@ -0,0 +1,8 @@ +// +// Created by 甘尧 on 2023/12/13. +// + +#ifndef SWIFTVM_JIT_CONTEXT_H +#define SWIFTVM_JIT_CONTEXT_H + +#endif // SWIFTVM_JIT_CONTEXT_H diff --git a/source/runtime/common/mem_arena.h b/source/runtime/common/mem_arena.h index 4ceb829..7c4242e 100644 --- a/source/runtime/common/mem_arena.h +++ b/source/runtime/common/mem_arena.h @@ -10,7 +10,7 @@ namespace swift::runtime { class MemArena { public: - explicit MemArena(size_t chunk_size = 4096) : new_chunk_size{chunk_size} { + explicit MemArena(size_t chunk_size = 4_KB) : new_chunk_size{chunk_size} { node = &chunks.emplace_back(new_chunk_size); } diff --git a/source/runtime/common/types.h b/source/runtime/common/types.h index 4cc8249..5156832 100644 --- a/source/runtime/common/types.h +++ b/source/runtime/common/types.h @@ -6,6 +6,7 @@ #include #include +#include #include "base/types.h" #include #include @@ -44,6 +45,9 @@ using Vector = typename std::vector; template using List = typename std::list; +template +using Set = typename std::set; + template using StackVector = typename boost::container::small_vector; diff --git a/source/runtime/externals/riscv-asm/riscv64/CMakeLists.txt b/source/runtime/externals/riscv-asm/riscv64/CMakeLists.txt index 685364d..a3d031b 100644 --- a/source/runtime/externals/riscv-asm/riscv64/CMakeLists.txt +++ b/source/runtime/externals/riscv-asm/riscv64/CMakeLists.txt @@ -1,3 +1,6 @@ add_library(riscv64_asm STATIC assembler_riscv64.cc assembler_riscv64.h) -target_include_directories(riscv64_asm PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file +target_include_directories(riscv64_asm PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +add_executable(riscv64_test main.cpp) +target_link_libraries(riscv64_test PRIVATE riscv64_asm) \ No newline at end of file diff --git a/source/runtime/externals/riscv-asm/riscv64/assembler_riscv64.h b/source/runtime/externals/riscv-asm/riscv64/assembler_riscv64.h index a50cac1..826eda2 100644 --- a/source/runtime/externals/riscv-asm/riscv64/assembler_riscv64.h +++ b/source/runtime/externals/riscv-asm/riscv64/assembler_riscv64.h @@ -921,7 +921,7 @@ class Assembler { virtual void Bind(Label* label) = 0; virtual void Jump(Label* label) = 0; - virtual ~Assembler() {} + virtual ~Assembler() = default; /** * @brief Buffer of DWARF's Call Frame Information opcodes. @@ -1014,8 +1014,7 @@ class JumpTable { class Riscv64Assembler final : public Assembler { public: - explicit Riscv64Assembler(ArenaAllocator* allocator) - : Assembler(allocator) + explicit Riscv64Assembler(ArenaAllocator* allocator): Assembler(allocator) , branches_{} , finalized_(false) , overwriting_(false) @@ -1030,14 +1029,15 @@ class Riscv64Assembler final : public Assembler { , available_scratch_fp_registers_(1u << FTMP) { } - virtual ~Riscv64Assembler() { + ~Riscv64Assembler() override { for (auto& branch : branches_) { CHECK(branch.IsResolved()); } } + + size_t CodeSize() const override { return Assembler::CodeSize(); } - DebugFrameOpCodeWriterForAssembler& cfi() { return Assembler::cfi(); } // According to "The RISC-V Instruction Set Manual" diff --git a/source/runtime/externals/riscv-asm/riscv64/main.cpp b/source/runtime/externals/riscv-asm/riscv64/main.cpp new file mode 100644 index 0000000..5b0d0ef --- /dev/null +++ b/source/runtime/externals/riscv-asm/riscv64/main.cpp @@ -0,0 +1,19 @@ +// +// Created by 甘尧 on 2023/12/8. +// + +#include "assembler_riscv64.h" + +int main (int argc, char * argv[]) { + using namespace swift; + riscv64::Riscv64Label label{}; + riscv64::ArenaAllocator allocator{}; + riscv64::Riscv64Assembler assembler{&allocator}; + assembler.Add(riscv64::A1, riscv64::A1, riscv64::A1); + assembler.Bind(&label); + assembler.Add(riscv64::A1, riscv64::A1, riscv64::A1); + assembler.Add(riscv64::A1, riscv64::A1, riscv64::A1); + assembler.Bne(riscv64::A1, riscv64::A2, &label); + assembler.FinalizeCode(); + return 0; +} diff --git a/source/runtime/ir/hir_builder.cpp b/source/runtime/ir/hir_builder.cpp index d85a603..c8a647a 100644 --- a/source/runtime/ir/hir_builder.cpp +++ b/source/runtime/ir/hir_builder.cpp @@ -10,6 +10,19 @@ namespace swift::runtime::ir { Edge::Edge(HIRBlock* src, HIRBlock* dest) : src_block(src), dest_block(dest) {} +HIRLoop* HIRLoop::Create(HIRFunction* function, HIRBlock* header, size_t length) { + return function->pools.mem_arena.Create(function, header, length); +} + +HIRLoop::HIRLoop(HIRFunction* function, HIRBlock* header, size_t length) { + loop = function->pools.CreateBlockVector(length); + std::memcpy(loop.data(), (void*)header, sizeof(HIRBlock*) * length); +} + +HIRBlock* HIRLoop::GetHeader() const { return loop[0]; } + +HIRBlockVector HIRLoop::GetLoopVector() const { return loop; } + HIRBlock::HIRBlock(Block* block, HIRValueMap& values, HIRPools& pools) : block(block), value_map(values), pools(pools) {} @@ -141,6 +154,8 @@ HIRBlockList& HIRFunction::GetHIRBlockList() { return block_list; } HIRBlockList& HIRFunction::GetHIRBlocksRPO() { return blocks_rpo; } +HIRLoopList& HIRFunction::GetHIRLoop() { return loops; } + HIRValueMap& HIRFunction::GetHIRValues() { return values; } HIRValue* HIRFunction::GetHIRValue(const Value& value) { @@ -171,6 +186,8 @@ void HIRFunction::AddEdge(HIRBlock* src, HIRBlock* dest, bool conditional) { void HIRFunction::RemoveEdge(Edge* edge) {} +void HIRFunction::AddLoop(HIRLoop* loop) { loops.push_back(*loop); } + void HIRFunction::MergeAdjacentBlocks(HIRBlock* left, HIRBlock* right) {} bool HIRFunction::SplitBlock(HIRBlock* new_block, HIRBlock* old_block) { return false; } @@ -361,4 +378,14 @@ Location HIRBuilder::GetNextLocation(const terminal::Terminal& term) { }); } +void DfsHIRBlock(HIRBlock* start, HIRBlock* end, HIRBlockSet& visited) { + if (start == end || visited.count(start)) { + return; + } + visited.insert(start); + for (auto pred : start->GetPredecessors()) { + DfsHIRBlock(pred, end, visited); + } +} + } // namespace swift::runtime::ir diff --git a/source/runtime/ir/hir_builder.h b/source/runtime/ir/hir_builder.h index b93ce2d..4b70bea 100644 --- a/source/runtime/ir/hir_builder.h +++ b/source/runtime/ir/hir_builder.h @@ -8,8 +8,8 @@ #include "runtime/common/mem_arena.h" #include "runtime/common/object_pool.h" #include "runtime/ir/function.h" -#include "runtime/ir/module.h" #include "runtime/ir/host_reg.h" +#include "runtime/ir/module.h" namespace swift::runtime::ir { @@ -19,6 +19,9 @@ class HIRBuilder; struct HIRPools; struct HIRValue; +using HIRBlockVector = std::span; +using HIRBlockSet = Set; + class DataContext { public: virtual u16 MaxBlockCount() = 0; @@ -45,18 +48,18 @@ struct Edge { struct Dominance { IntrusiveListNode node; - HIRBlock *block; + HIRBlock* block; - explicit Dominance(HIRBlock* block) : block(block), node() {}; + explicit Dominance(HIRBlock* block) : block(block), node(){}; }; using DomFrontier = IntrusiveList<&Dominance::node>; struct BackEdge { - HIRBlock *target; + HIRBlock* target; IntrusiveListNode list_node{}; - explicit BackEdge(HIRBlock *block) : target(block) {} + explicit BackEdge(HIRBlock* block) : target(block) {} }; using BackEdgeList = IntrusiveList<&BackEdge::list_node>; @@ -88,13 +91,9 @@ struct HIRUse { explicit HIRUse(Inst* inst, u8 arg_idx); - [[nodiscard]] bool IsFuncCall() const { - return arg_idx == USE_FUNC_CALL; - } + [[nodiscard]] bool IsFuncCall() const { return arg_idx == USE_FUNC_CALL; } - [[nodiscard]] bool IsPhi() const { - return arg_idx == USE_PHI; - } + [[nodiscard]] bool IsPhi() const { return arg_idx == USE_PHI; } }; #pragma pack(pop) @@ -109,7 +108,7 @@ struct HIRValue final { IntrusiveMapNode map_node{}; - HIRValue() : value(), block(nullptr) {}; + HIRValue() : value(), block(nullptr){}; HIRValue(const Value& value) : value(value), block(nullptr){}; explicit HIRValue(const Value& value, HIRBlock* block); @@ -135,13 +134,25 @@ struct HIRLocal { HIRValue* current_value{}; }; +class HIRLoop final { +public: + static HIRLoop* Create(HIRFunction* function, HIRBlock* header, size_t length); + + explicit HIRLoop(HIRFunction* function, HIRBlock* header, size_t length); + [[nodiscard]] HIRBlock* GetHeader() const; + [[nodiscard]] HIRBlockVector GetLoopVector() const; + + IntrusiveListNode node{}; + +private: + HIRBlockVector loop; +}; #pragma pack(pop) +using HIRLoopList = IntrusiveList<&HIRLoop::node>; using HIRValueMap = IntrusiveMap<&HIRValue::map_node>; -using HIRBlockVector = std::span; - -class HIRBlock : public DataContext { +class HIRBlock final : public DataContext { friend class HIRFunction; friend class HIRValue; @@ -154,7 +165,7 @@ class HIRBlock : public DataContext { return inst; } - template HIRValue *AppendInst(OpCode op, const Args&... args) { + template HIRValue* AppendInst(OpCode op, const Args&... args) { auto inst = new Inst(op); inst->SetArgs(args...); return AppendInst(inst); @@ -162,13 +173,14 @@ class HIRBlock : public DataContext { #define INST(name, ret, ...) \ template ret name(const Args&... args) { \ - return ret{AppendInst(OpCode::name, args...)}; \ + auto hir_value = AppendInst(OpCode::name, args...); \ + return ret{hir_value ? hir_value->value.Def() : nullptr}; \ } #include "ir.inc" #undef INST - HIRValue *AppendInst(Inst* inst); - HIRValue *InsertFront(Inst* inst); + HIRValue* AppendInst(Inst* inst); + HIRValue* InsertFront(Inst* inst); HIRValueMap& GetHIRValues(); [[nodiscard]] u16 GetOrderId() const; @@ -188,8 +200,8 @@ class HIRBlock : public DataContext { auto& GetDomFrontier() { return dom_frontier; } - void PushDominance(HIRBlock *block); - void SetDominator(HIRBlock *block_) { dominator = block_; }; + void PushDominance(HIRBlock* block); + void SetDominator(HIRBlock* block_) { dominator = block_; }; auto GetDominator() { return dominator; }; Block* GetBlock(); @@ -204,7 +216,7 @@ class HIRBlock : public DataContext { private: u16 order_id{}; Block* block; - HIRFunction *function{}; + HIRFunction* function{}; HIRPools& pools; HIRValueMap& value_map; IntrusiveList<&Edge::outgoing_edges> outgoing_edges{}; @@ -243,20 +255,22 @@ class HIRFunction final : public DataContext { #undef INST HIRBlock* AppendBlock(Location start, Location end = {}); - HIRBlock *CreateOrGetBlock(Location location); - void SetCurBlock(HIRBlock *block); - HIRValue *AppendValue(HIRBlock *block, Inst* inst); + HIRBlock* CreateOrGetBlock(Location location); + void SetCurBlock(HIRBlock* block); + HIRValue* AppendValue(HIRBlock* block, Inst* inst); void DestroyHIRValue(HIRValue* value); - HIRBlock *GetEntryBlock(); - HIRBlock *GetCurrentBlock(); + HIRBlock* GetEntryBlock(); + HIRBlock* GetCurrentBlock(); HIRBlockVector& GetHIRBlocks(); HIRBlockList& GetHIRBlockList(); HIRBlockList& GetHIRBlocksRPO(); + HIRLoopList& GetHIRLoop(); HIRValueMap& GetHIRValues(); HIRValue* GetHIRValue(const Value& value); HIRPools& GetMemPool(); void AddEdge(HIRBlock* src, HIRBlock* dest, bool conditional = false); void RemoveEdge(Edge* edge); + void AddLoop(HIRLoop* loop); void MergeAdjacentBlocks(HIRBlock* left, HIRBlock* right); bool SplitBlock(HIRBlock* new_block, HIRBlock* old_block); void IdByRPO(); @@ -273,6 +287,7 @@ class HIRFunction final : public DataContext { private: friend class HIRBuilder; friend class HIRBlock; + friend class HIRLoop; struct { u32 current_slot{0}; @@ -296,6 +311,7 @@ class HIRFunction final : public DataContext { HIRValueMap values{}; HIRBlock* current_block{}; HIRBlock* entry_block{}; + HIRLoopList loops{}; }; using HIRFunctionList = IntrusiveList<&HIRFunction::list_node>; @@ -337,7 +353,7 @@ class HIRBuilder { explicit HIRBuilder(u32 func_cap = 1); - HIRFunction *AppendFunction(Location start, Location end = {}); + HIRFunction* AppendFunction(Location start, Location end = {}); HIRFunctionList& GetHIRFunctions(); @@ -350,7 +366,7 @@ class HIRBuilder { void SetLocation(Location location); - void SetCurBlock(HIRBlock *block); + void SetCurBlock(HIRBlock* block); void SetCurBlock(Location location); @@ -371,4 +387,6 @@ class HIRBuilder { HIRFunction* current_function{}; }; +void DfsHIRBlock(HIRBlock* start, HIRBlock* end, HIRBlockSet& visited); + } // namespace swift::runtime::ir \ No newline at end of file diff --git a/source/runtime/ir/opts/cfg_analysis_pass.cpp b/source/runtime/ir/opts/cfg_analysis_pass.cpp index 96068d7..85a39d5 100644 --- a/source/runtime/ir/opts/cfg_analysis_pass.cpp +++ b/source/runtime/ir/opts/cfg_analysis_pass.cpp @@ -94,8 +94,11 @@ void CFGAnalysisPass::Run(HIRFunction* hir_function) { // Build back edges FindBackEdges(hir_function, visited); - // Build Reverse Post Order + // Build Reverse Post Order & Build Dom Tree ComputeDominanceInformation(hir_function); + + // Collect looper + ComputeLoopInformation(hir_function); } bool CFGAnalysisPass::UpdateDominatorOfSuccessor(HIRBlock* block, HIRBlock* successor) { @@ -202,8 +205,8 @@ void CFGAnalysisPass::ComputeDominanceInformation(HIRFunction* hir_function) { entry_block->SetDominator(entry_block); // Dominance Frontier - for (auto &block : reverse_post_order) { - auto &predecessors = block.GetPredecessors(); + for (auto& block : reverse_post_order) { + auto& predecessors = block.GetPredecessors(); if (predecessors.size() > 1) { auto dom = block.GetDominator(); for (auto predecessor : predecessors) { @@ -217,4 +220,27 @@ void CFGAnalysisPass::ComputeDominanceInformation(HIRFunction* hir_function) { } } +void CFGAnalysisPass::ComputeLoopInformation(HIRFunction* hir_function) { + for (auto& block : hir_function->GetHIRBlocksRPO()) { + auto& back_edges = block.GetBackEdges(); + if (!back_edges.empty()) { + auto dominator = block.GetDominator(); + for (auto& back_edge : back_edges) { + auto header = back_edge.target; + if (header != dominator) { + StackVector loop{}; + loop.push_back(&block); + HIRBlockSet visited{}; + DfsHIRBlock(&block, header, visited); + for (HIRBlock* loop_block : visited) { + loop.push_back(loop_block); + } + auto hir_loop = HIRLoop::Create(hir_function, *loop.begin(), loop.size()); + hir_function->AddLoop(hir_loop); + } + } + } + } +} + } // namespace swift::runtime::ir diff --git a/source/runtime/ir/opts/cfg_analysis_pass.h b/source/runtime/ir/opts/cfg_analysis_pass.h index fe56d94..fb28e22 100644 --- a/source/runtime/ir/opts/cfg_analysis_pass.h +++ b/source/runtime/ir/opts/cfg_analysis_pass.h @@ -19,6 +19,7 @@ class CFGAnalysisPass { static void FindDominateEdges(HIRFunction *hir_function); static void FindBackEdges(HIRFunction *hir_function, BitVector &visited); static void ComputeDominanceInformation(HIRFunction *hir_function); + static void ComputeLoopInformation(HIRFunction *hir_function); }; } // namespace swift::runtime::ir \ No newline at end of file diff --git a/source/tests/main_case.cpp b/source/tests/main_case.cpp index e39644f..c089ce1 100644 --- a/source/tests/main_case.cpp +++ b/source/tests/main_case.cpp @@ -124,6 +124,32 @@ TEST_CASE("Test runtime ir cfg") { } +TEST_CASE("Test runtime ir loop") { + using namespace swift::runtime::backend; + using namespace swift::runtime::ir; + Inst::InitializeSlabHeap(0x100000); + Block::InitializeSlabHeap(0x10000); + Function::InitializeSlabHeap(0x2000); + HIRBuilder hir_builder{1}; + auto function = hir_builder.AppendFunction(Location{0}, Location{0x10}); + Local local1{ + .id = 0, + .type = ValueType::U32, + }; + auto value = function->LoadLocal(local1); + auto [else_, then_] = hir_builder.If(terminal::If{value, terminal::LinkBlock{1}, terminal::LinkBlock{2}}); + else_->StoreLocal(local1, else_->LoadImm(Imm(UINT32_MAX))); + then_->StoreLocal(local1, else_->LoadImm(Imm(UINT32_MAX))); + hir_builder.SetCurBlock(else_); + hir_builder.LinkBlock(terminal::LinkBlock{0}); + hir_builder.SetCurBlock(then_); + hir_builder.Return(); + + CFGAnalysisPass::Run(&hir_builder); + LocalEliminationPass::Run(&hir_builder); + ReIdInstrPass::Run(&hir_builder); +} + TEST_CASE("Test riscv64 asm") { using namespace swift; riscv64::Riscv64Label label{};