write phi elimination
This commit is contained in:
@ -89,17 +89,9 @@ class BRAction : public JMPActionItem {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
class UNConditionJMPAction : public JMPActionItem {
|
class UNConditionJMPAction : public JMPActionItem {
|
||||||
friend class IRBuilder;
|
public:
|
||||||
friend class FunctionDefItem;
|
|
||||||
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
|
||||||
friend void NaiveBackend::GenerateASM(std::shared_ptr<ActionItem> act, std::vector<std::string> &code_lines,
|
|
||||||
NaiveBackend::FuncLayout &layout,
|
|
||||||
const std::unordered_map<std::string, IRClassInfo> &low_level_class_info,
|
|
||||||
bool process_phi);
|
|
||||||
friend class CFGType BuildCFGForFunction(const std::shared_ptr<class FunctionDefItem> &func);
|
|
||||||
std::string label_full;
|
std::string label_full;
|
||||||
|
|
||||||
public:
|
|
||||||
UNConditionJMPAction() = default;
|
UNConditionJMPAction() = default;
|
||||||
void RecursivePrint(std::ostream &os) const { os << "br label %" << label_full << "\n"; }
|
void RecursivePrint(std::ostream &os) const { os << "br label %" << label_full << "\n"; }
|
||||||
};
|
};
|
||||||
@ -492,10 +484,7 @@ class ConstStrItem : public LLVMIRItemBase {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
class ModuleItem : public LLVMIRItemBase {
|
class ModuleItem : public LLVMIRItemBase {
|
||||||
friend class IRBuilder;
|
public:
|
||||||
friend std::shared_ptr<ModuleItem> BuildIR(std::shared_ptr<Program_ASTNode> src);
|
|
||||||
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
|
||||||
friend std::shared_ptr<ModuleItem> Mem2Reg(std::shared_ptr<ModuleItem> src);
|
|
||||||
std::vector<std::shared_ptr<ConstStrItem>> const_strs;
|
std::vector<std::shared_ptr<ConstStrItem>> const_strs;
|
||||||
std::vector<std::shared_ptr<FunctionDeclareItem>> function_declares;
|
std::vector<std::shared_ptr<FunctionDeclareItem>> function_declares;
|
||||||
std::vector<std::shared_ptr<TypeDefItem>> type_defs;
|
std::vector<std::shared_ptr<TypeDefItem>> type_defs;
|
||||||
@ -503,7 +492,6 @@ class ModuleItem : public LLVMIRItemBase {
|
|||||||
std::vector<std::shared_ptr<FunctionDefItem>> function_defs;
|
std::vector<std::shared_ptr<FunctionDefItem>> function_defs;
|
||||||
std::unordered_map<std::string, IRClassInfo> low_level_class_info;
|
std::unordered_map<std::string, IRClassInfo> low_level_class_info;
|
||||||
|
|
||||||
public:
|
|
||||||
ModuleItem() = default;
|
ModuleItem() = default;
|
||||||
void RecursivePrint(std::ostream &os) const {
|
void RecursivePrint(std::ostream &os) const {
|
||||||
for (auto &item : const_strs) {
|
for (auto &item : const_strs) {
|
||||||
|
@ -8,8 +8,10 @@
|
|||||||
using CFGNodeCollection = std::list<class CFGNodeType *>;
|
using CFGNodeCollection = std::list<class CFGNodeType *>;
|
||||||
class CFGNodeType {
|
class CFGNodeType {
|
||||||
public:
|
public:
|
||||||
|
// successors, predecessors, corresponding_block is provided by BuildCFGForFunction
|
||||||
std::vector<CFGNodeType *> successors, predecessors;
|
std::vector<CFGNodeType *> successors, predecessors;
|
||||||
BlockItem *corresponding_block;
|
BlockItem *corresponding_block;
|
||||||
|
// the following fields are provided by user
|
||||||
CFGNodeCollection dom;
|
CFGNodeCollection dom;
|
||||||
bool visited;
|
bool visited;
|
||||||
CFGNodeType *idom;
|
CFGNodeType *idom;
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
#include "mem2reg.h"
|
|
||||||
#include "cfg.h"
|
#include "cfg.h"
|
||||||
|
#include "mem2reg.h"
|
||||||
|
#include "regalloc.h"
|
18
include/opt/phieliminate.h
Normal file
18
include/opt/phieliminate.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "IR/IR_basic.h"
|
||||||
|
#include "cfg.h"
|
||||||
|
|
||||||
|
namespace opt {
|
||||||
|
class MoveInstruct : public ActionItem {
|
||||||
|
public:
|
||||||
|
std::string src_full;
|
||||||
|
std::string dest_full;
|
||||||
|
MoveInstruct() = default;
|
||||||
|
void RecursivePrint(std::ostream &os) const {
|
||||||
|
throw std::runtime_error("Move instruction is not an actual LLVM IR instruction");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace opt
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<ModuleItem> PhiEliminate(std::shared_ptr<ModuleItem> src);
|
2
include/opt/regalloc.h
Normal file
2
include/opt/regalloc.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "phieliminate.h"
|
@ -46,7 +46,8 @@ int main(int argc, char **argv) {
|
|||||||
GenerateNaiveASM(fout, IR);
|
GenerateNaiveASM(fout, IR);
|
||||||
} else {
|
} else {
|
||||||
auto IR_with_out_allocas = Mem2Reg(IR);
|
auto IR_with_out_allocas = Mem2Reg(IR);
|
||||||
IR_with_out_allocas->RecursivePrint(fout);
|
// IR_with_out_allocas->RecursivePrint(fout);
|
||||||
|
auto IR_with_out_phis = PhiEliminate(IR_with_out_allocas);
|
||||||
}
|
}
|
||||||
} catch (const SemanticError &err) {
|
} catch (const SemanticError &err) {
|
||||||
std::cout << err.what() << std::endl;
|
std::cout << err.what() << std::endl;
|
||||||
|
72
src/opt/phieliminate.cpp
Normal file
72
src/opt/phieliminate.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#include "phieliminate.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "IR/IR_basic.h"
|
||||||
|
|
||||||
|
using namespace opt;
|
||||||
|
|
||||||
|
void ConductPhiEliminateForFunction([[maybe_unused]] std::shared_ptr<FunctionDefItem> func, CFGType &cfg) {
|
||||||
|
size_t new_block_cnt = 0;
|
||||||
|
for (auto cur_node : cfg.nodes) {
|
||||||
|
auto cur_block = cur_node->corresponding_block;
|
||||||
|
if (cur_block->actions.size() > 0) {
|
||||||
|
if (auto phi_act = std::dynamic_pointer_cast<PhiItem>(cur_block->actions[0])) {
|
||||||
|
// simple phi action caused by and, or and ternary operator, no need to insert extra blocks, just remove it and
|
||||||
|
// add phi values to the corresponding blocks
|
||||||
|
cur_block->actions.erase(cur_block->actions.begin());
|
||||||
|
for (auto [src_val, src_label] : phi_act->values) {
|
||||||
|
auto src_block = cfg.label_to_block[src_label];
|
||||||
|
auto new_move = std::make_shared<MoveInstruct>();
|
||||||
|
new_move->src_full = src_val;
|
||||||
|
new_move->dest_full = phi_act->result_full;
|
||||||
|
src_block->actions.push_back(new_move);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto [_, phi_act] : cur_block->phi_map) {
|
||||||
|
for (auto [src_val, src_label] : phi_act->values) {
|
||||||
|
auto src_block = cfg.label_to_block[src_label];
|
||||||
|
auto src_node = cfg.block_to_node[src_block];
|
||||||
|
if (src_node->successors.size() > 1 && cur_node->predecessors.size() > 1) {
|
||||||
|
// it is a critical edge, need to insert a new block
|
||||||
|
auto new_block = std::make_shared<BlockItem>();
|
||||||
|
new_block->label_full = cur_block->label_full + ".phieliminate." + std::to_string(new_block_cnt++);
|
||||||
|
new_block->exit_action = std::make_shared<UNConditionJMPAction>();
|
||||||
|
std::dynamic_pointer_cast<UNConditionJMPAction>(new_block->exit_action)->label_full = cur_block->label_full;
|
||||||
|
auto src_block_exit_action = std::dynamic_pointer_cast<BRAction>(src_block->exit_action);
|
||||||
|
if (!src_block_exit_action) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"something strange happened: src block of a critical edge does not have a BRAction");
|
||||||
|
}
|
||||||
|
if (src_block_exit_action->true_label_full == cur_block->label_full) {
|
||||||
|
src_block_exit_action->true_label_full = new_block->label_full;
|
||||||
|
} else if (src_block_exit_action->false_label_full == cur_block->label_full) {
|
||||||
|
src_block_exit_action->false_label_full = new_block->label_full;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"something strange happened: src block of a critical edge cannot find the corresponding label");
|
||||||
|
}
|
||||||
|
auto new_move = std::make_shared<MoveInstruct>();
|
||||||
|
new_move->src_full = src_val;
|
||||||
|
new_move->dest_full = phi_act->result_full;
|
||||||
|
new_block->actions.push_back(new_move);
|
||||||
|
} else {
|
||||||
|
auto new_move = std::make_shared<MoveInstruct>();
|
||||||
|
new_move->src_full = src_val;
|
||||||
|
new_move->dest_full = phi_act->result_full;
|
||||||
|
cur_block->actions.push_back(new_move);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur_block->phi_map.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ModuleItem> PhiEliminate(std::shared_ptr<ModuleItem> src) {
|
||||||
|
auto res = src;
|
||||||
|
for (auto &func : res->function_defs) {
|
||||||
|
// func = std::make_shared<FunctionDefItem>(*func);
|
||||||
|
auto cfg = BuildCFGForFunction(func);
|
||||||
|
ConductPhiEliminateForFunction(func, cfg);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
1
src/opt/regalloc.cpp
Normal file
1
src/opt/regalloc.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "regalloc.h"
|
Reference in New Issue
Block a user