#pragma once #include "ir/IR.h" #include #include #include #include #include namespace ir { class DominatorTree { public: explicit DominatorTree(Function& function); void Recalculate(); Function& GetFunction() const { return *function_; } bool IsReachable(BasicBlock* block) const; bool Dominates(BasicBlock* dom, BasicBlock* node) const; bool Dominates(Instruction* dom, Instruction* user) const; BasicBlock* GetIDom(BasicBlock* block) const; const std::vector& GetChildren(BasicBlock* block) const; const std::vector& GetReversePostOrder() const { return reverse_post_order_; } private: Function* function_ = nullptr; std::vector reverse_post_order_; std::unordered_map block_index_; std::vector> dominates_; std::unordered_map immediate_dominator_; std::unordered_map> dom_children_; }; struct Loop { BasicBlock* header = nullptr; std::unordered_set blocks; std::vector block_list; std::vector latches; std::vector exiting_blocks; std::vector exit_blocks; BasicBlock* preheader = nullptr; Loop* parent = nullptr; std::vector subloops; bool Contains(BasicBlock* block) const; bool Contains(const Loop* other) const; bool IsInnermost() const; }; class LoopInfo { public: LoopInfo(Function& function, const DominatorTree& dom_tree); void Recalculate(); const std::vector>& GetLoops() const { return loops_; } std::vector GetTopLevelLoops() const; std::vector GetLoopsInPostOrder() const; Loop* GetLoopFor(BasicBlock* block) const; private: Function* function_ = nullptr; const DominatorTree* dom_tree_ = nullptr; std::vector> loops_; std::vector top_level_loops_; std::unordered_map block_to_loop_; }; } // namespace ir