finish live analysis
This commit is contained in:
@ -365,9 +365,7 @@ class SelectItem : public ActionItem {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
class FunctionDefItem : public LLVMIRItemBase {
|
class FunctionDefItem : public LLVMIRItemBase {
|
||||||
friend class IRBuilder;
|
public:
|
||||||
friend void GenerateNaiveASM(std::ostream &os, std::shared_ptr<ModuleItem> prog);
|
|
||||||
friend class CFGType BuildCFGForFunction(const std::shared_ptr<FunctionDefItem> &func);
|
|
||||||
LLVMType return_type;
|
LLVMType return_type;
|
||||||
std::string func_name_raw;
|
std::string func_name_raw;
|
||||||
std::vector<LLVMType> args;
|
std::vector<LLVMType> args;
|
||||||
@ -375,7 +373,6 @@ class FunctionDefItem : public LLVMIRItemBase {
|
|||||||
std::shared_ptr<BlockItem> init_block;
|
std::shared_ptr<BlockItem> init_block;
|
||||||
std::vector<std::shared_ptr<BlockItem>> basic_blocks;
|
std::vector<std::shared_ptr<BlockItem>> basic_blocks;
|
||||||
|
|
||||||
public:
|
|
||||||
FunctionDefItem() = default;
|
FunctionDefItem() = default;
|
||||||
void RecursivePrint(std::ostream &os) const {
|
void RecursivePrint(std::ostream &os) const {
|
||||||
os << "define ";
|
os << "define ";
|
||||||
|
@ -17,6 +17,11 @@ class CFGNodeType {
|
|||||||
CFGNodeType *idom;
|
CFGNodeType *idom;
|
||||||
std::vector<CFGNodeType *> successors_in_dom_tree;
|
std::vector<CFGNodeType *> successors_in_dom_tree;
|
||||||
CFGNodeCollection dom_frontier;
|
CFGNodeCollection dom_frontier;
|
||||||
|
|
||||||
|
std::vector<size_t> in_active_vars;
|
||||||
|
std::vector<size_t> out_active_vars;
|
||||||
|
std::vector<size_t> use_vars;
|
||||||
|
std::vector<size_t> def_vars;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CFGType {
|
class CFGType {
|
||||||
@ -27,9 +32,100 @@ class CFGType {
|
|||||||
std::unordered_map<std::string, BlockItem *> label_to_block;
|
std::unordered_map<std::string, BlockItem *> label_to_block;
|
||||||
};
|
};
|
||||||
|
|
||||||
CFGNodeCollection GetCFGNodeCollectionsIntersection(const CFGNodeCollection &a, const CFGNodeCollection &b);
|
template <typename Container, typename Compare = std::less<typename Container::value_type>>
|
||||||
CFGNodeCollection GetCFGNodeCollectionsUnion(const CFGNodeCollection &a, const CFGNodeCollection &b);
|
Container GetCollectionsIntersection(const Container &a, const Container &b, Compare comp = Compare()) {
|
||||||
CFGNodeCollection GetCFGNodeCollectionsDifference(const CFGNodeCollection &a, const CFGNodeCollection &b);
|
Container result;
|
||||||
bool CFGNodeCollectionIsSame(const CFGNodeCollection &a, const CFGNodeCollection &b);
|
auto ita = a.begin();
|
||||||
|
auto itb = b.begin();
|
||||||
|
|
||||||
|
while (ita != a.end() && itb != b.end()) {
|
||||||
|
if (comp(*ita, *itb)) {
|
||||||
|
++ita;
|
||||||
|
} else if (comp(*itb, *ita)) {
|
||||||
|
++itb;
|
||||||
|
} else {
|
||||||
|
result.push_back(*ita);
|
||||||
|
++ita;
|
||||||
|
++itb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Container, typename Compare = std::less<typename Container::value_type>>
|
||||||
|
Container GetCollectionsUnion(const Container &a, const Container &b, Compare comp = Compare()) {
|
||||||
|
Container result;
|
||||||
|
auto ita = a.begin();
|
||||||
|
auto itb = b.begin();
|
||||||
|
|
||||||
|
while (ita != a.end() && itb != b.end()) {
|
||||||
|
if (comp(*ita, *itb)) {
|
||||||
|
result.push_back(*ita);
|
||||||
|
++ita;
|
||||||
|
} else if (comp(*itb, *ita)) {
|
||||||
|
result.push_back(*itb);
|
||||||
|
++itb;
|
||||||
|
} else {
|
||||||
|
result.push_back(*ita);
|
||||||
|
++ita;
|
||||||
|
++itb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ita != a.end()) {
|
||||||
|
result.push_back(*ita);
|
||||||
|
++ita;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (itb != b.end()) {
|
||||||
|
result.push_back(*itb);
|
||||||
|
++itb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Container, typename Compare = std::less<typename Container::value_type>>
|
||||||
|
Container GetCollectionsDifference(const Container &a, const Container &b, Compare comp = Compare()) {
|
||||||
|
Container result;
|
||||||
|
auto ita = a.begin();
|
||||||
|
auto itb = b.begin();
|
||||||
|
|
||||||
|
while (ita != a.end() && itb != b.end()) {
|
||||||
|
if (comp(*ita, *itb)) {
|
||||||
|
result.push_back(*ita);
|
||||||
|
++ita;
|
||||||
|
} else if (comp(*itb, *ita)) {
|
||||||
|
++itb;
|
||||||
|
} else {
|
||||||
|
++ita;
|
||||||
|
++itb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ita != a.end()) {
|
||||||
|
result.push_back(*ita);
|
||||||
|
++ita;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Container, typename Compare = std::less<typename Container::value_type>>
|
||||||
|
bool GetCollectionsIsSame(const Container &a, const Container &b, Compare comp = Compare()) {
|
||||||
|
auto ita = a.begin();
|
||||||
|
auto itb = b.begin();
|
||||||
|
|
||||||
|
while (ita != a.end() && itb != b.end()) {
|
||||||
|
if (comp(*ita, *itb) || comp(*itb, *ita)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
++ita;
|
||||||
|
++itb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ita == a.end() && itb == b.end();
|
||||||
|
}
|
||||||
|
|
||||||
CFGType BuildCFGForFunction(const std::shared_ptr<FunctionDefItem> &func);
|
CFGType BuildCFGForFunction(const std::shared_ptr<FunctionDefItem> &func);
|
4
include/opt/liveanalysis.h
Normal file
4
include/opt/liveanalysis.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "cfg.h"
|
||||||
|
|
||||||
|
void LiveAnalysis(CFGType &cfg);
|
@ -8,11 +8,10 @@ class MoveInstruct : public ActionItem {
|
|||||||
std::string src_full;
|
std::string src_full;
|
||||||
std::string dest_full;
|
std::string dest_full;
|
||||||
MoveInstruct() = default;
|
MoveInstruct() = default;
|
||||||
void RecursivePrint(std::ostream &os) const {
|
void RecursivePrint([[maybe_unused]] std::ostream &os) const {
|
||||||
throw std::runtime_error("Move instruction is not an actual LLVM IR instruction");
|
throw std::runtime_error("Move instruction is not an actual LLVM IR instruction");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace opt
|
} // namespace opt
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<ModuleItem> PhiEliminate(std::shared_ptr<ModuleItem> src);
|
std::shared_ptr<ModuleItem> PhiEliminate(std::shared_ptr<ModuleItem> src);
|
@ -1,2 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "liveanalysis.h"
|
||||||
#include "phieliminate.h"
|
#include "phieliminate.h"
|
||||||
|
|
||||||
|
std::shared_ptr<ModuleItem> RegAlloc(std::shared_ptr<ModuleItem> src);
|
@ -3,8 +3,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "IR/IR.h"
|
#include "IR/IR.h"
|
||||||
#include "naivebackend/naivebackend.h"
|
#include "naivebackend/naivebackend.h"
|
||||||
#include "semantic/semantic.h"
|
|
||||||
#include "opt/opt.h"
|
#include "opt/opt.h"
|
||||||
|
#include "semantic/semantic.h"
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
argparse::ArgumentParser program("zmxcc");
|
argparse::ArgumentParser program("zmxcc");
|
||||||
@ -46,8 +46,9 @@ 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);
|
auto IR_with_out_phis = PhiEliminate(IR_with_out_allocas);
|
||||||
|
auto alloced_code = RegAlloc(IR_with_out_phis);
|
||||||
}
|
}
|
||||||
} catch (const SemanticError &err) {
|
} catch (const SemanticError &err) {
|
||||||
std::cout << err.what() << std::endl;
|
std::cout << err.what() << std::endl;
|
||||||
|
@ -1,95 +1,12 @@
|
|||||||
#include "cfg.h"
|
#include "cfg.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
CFGNodeCollection GetCFGNodeCollectionsIntersection(const CFGNodeCollection &a, const CFGNodeCollection &b) {
|
|
||||||
// assume that thety are both sorted
|
|
||||||
CFGNodeCollection res;
|
|
||||||
auto ita = a.begin();
|
|
||||||
auto itb = b.begin();
|
|
||||||
while (ita != a.end() && itb != b.end()) {
|
|
||||||
if (*ita == *itb) {
|
|
||||||
res.push_back(*ita);
|
|
||||||
ita++;
|
|
||||||
itb++;
|
|
||||||
} else if (*ita < *itb) {
|
|
||||||
ita++;
|
|
||||||
} else {
|
|
||||||
itb++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFGNodeCollection GetCFGNodeCollectionsUnion(const CFGNodeCollection &a, const CFGNodeCollection &b) {
|
|
||||||
// assume that thety are both sorted
|
|
||||||
CFGNodeCollection res;
|
|
||||||
auto ita = a.begin();
|
|
||||||
auto itb = b.begin();
|
|
||||||
while (ita != a.end() && itb != b.end()) {
|
|
||||||
if (*ita == *itb) {
|
|
||||||
res.push_back(*ita);
|
|
||||||
ita++;
|
|
||||||
itb++;
|
|
||||||
} else if (*ita < *itb) {
|
|
||||||
res.push_back(*ita);
|
|
||||||
ita++;
|
|
||||||
} else {
|
|
||||||
res.push_back(*itb);
|
|
||||||
itb++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (ita != a.end()) {
|
|
||||||
res.push_back(*ita);
|
|
||||||
ita++;
|
|
||||||
}
|
|
||||||
while (itb != b.end()) {
|
|
||||||
res.push_back(*itb);
|
|
||||||
itb++;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFGNodeCollection GetCFGNodeCollectionsDifference(const CFGNodeCollection &a, const CFGNodeCollection &b) {
|
|
||||||
// assume that thety are both sorted
|
|
||||||
CFGNodeCollection res;
|
|
||||||
auto ita = a.begin();
|
|
||||||
auto itb = b.begin();
|
|
||||||
while (ita != a.end() && itb != b.end()) {
|
|
||||||
if (*ita == *itb) {
|
|
||||||
ita++;
|
|
||||||
itb++;
|
|
||||||
} else if (*ita < *itb) {
|
|
||||||
res.push_back(*ita);
|
|
||||||
ita++;
|
|
||||||
} else {
|
|
||||||
itb++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (ita != a.end()) {
|
|
||||||
res.push_back(*ita);
|
|
||||||
ita++;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CFGNodeCollectionIsSame(const CFGNodeCollection &a, const CFGNodeCollection &b) {
|
|
||||||
auto ita = a.begin();
|
|
||||||
auto itb = b.begin();
|
|
||||||
while (ita != a.end() && itb != b.end()) {
|
|
||||||
if (*ita != *itb) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ita++;
|
|
||||||
itb++;
|
|
||||||
}
|
|
||||||
return ita == a.end() && itb == b.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
CFGType BuildCFGForFunction(const std::shared_ptr<FunctionDefItem> &func) {
|
CFGType BuildCFGForFunction(const std::shared_ptr<FunctionDefItem> &func) {
|
||||||
CFGType res;
|
CFGType res;
|
||||||
auto init_block=func->init_block;
|
auto init_block = func->init_block;
|
||||||
if (!func->init_block) {
|
if (!func->init_block) {
|
||||||
// throw std::runtime_error("Function does not have an init block");
|
// throw std::runtime_error("Function does not have an init block");
|
||||||
if(func->basic_blocks.size()==0) throw std::runtime_error("Function does not have any block");
|
if (func->basic_blocks.size() == 0) throw std::runtime_error("Function does not have any block");
|
||||||
init_block = func->basic_blocks[0];
|
init_block = func->basic_blocks[0];
|
||||||
}
|
}
|
||||||
res.label_to_block[init_block->label_full] = init_block.get();
|
res.label_to_block[init_block->label_full] = init_block.get();
|
||||||
|
217
src/opt/liveanalysis.cpp
Normal file
217
src/opt/liveanalysis.cpp
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
#include "liveanalysis.h"
|
||||||
|
#include <queue>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "IR/IR_basic.h"
|
||||||
|
#include "cfg.h"
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
|
void VarCollect(CFGType &cfg, std::vector<std::string> &id_to_var, std::unordered_map<std::string, size_t> &var_to_id) {
|
||||||
|
for (auto node : cfg.nodes) {
|
||||||
|
auto block = node->corresponding_block;
|
||||||
|
for (auto act : block->actions) {
|
||||||
|
if (auto bin_act = std::dynamic_pointer_cast<BinaryOperationAction>(act)) {
|
||||||
|
id_to_var.push_back(bin_act->result_full);
|
||||||
|
var_to_id[bin_act->result_full] = id_to_var.size() - 1;
|
||||||
|
} else if (auto load_act = std::dynamic_pointer_cast<LoadAction>(act)) {
|
||||||
|
id_to_var.push_back(load_act->result_full);
|
||||||
|
var_to_id[load_act->result_full] = id_to_var.size() - 1;
|
||||||
|
} else if (auto get_act = std::dynamic_pointer_cast<GetElementPtrAction>(act)) {
|
||||||
|
id_to_var.push_back(get_act->result_full);
|
||||||
|
var_to_id[get_act->result_full] = id_to_var.size() - 1;
|
||||||
|
} else if (auto icmp_act = std::dynamic_pointer_cast<ICMPAction>(act)) {
|
||||||
|
id_to_var.push_back(icmp_act->result_full);
|
||||||
|
var_to_id[icmp_act->result_full] = id_to_var.size() - 1;
|
||||||
|
} else if (auto call_act = std::dynamic_pointer_cast<CallItem>(act)) {
|
||||||
|
if (!std::holds_alternative<LLVMVOIDType>(call_act->return_type)) {
|
||||||
|
id_to_var.push_back(call_act->result_full);
|
||||||
|
var_to_id[call_act->result_full] = id_to_var.size() - 1;
|
||||||
|
}
|
||||||
|
} else if (auto select_act = std::dynamic_pointer_cast<SelectItem>(act)) {
|
||||||
|
id_to_var.push_back(select_act->result_full);
|
||||||
|
var_to_id[select_act->result_full] = id_to_var.size() - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UseDefCollect(CFGType &cfg, [[maybe_unused]] std::vector<std::string> &id_to_var,
|
||||||
|
std::unordered_map<std::string, size_t> &var_to_id) {
|
||||||
|
for (auto node : cfg.nodes) {
|
||||||
|
auto block = node->corresponding_block;
|
||||||
|
std::vector<size_t> cur_node_use;
|
||||||
|
std::vector<size_t> cur_node_def;
|
||||||
|
bool use_def_init = false;
|
||||||
|
for (auto act : block->actions) {
|
||||||
|
std::vector<size_t> cur_act_use;
|
||||||
|
std::vector<size_t> cur_act_def;
|
||||||
|
if (auto br_act = std::dynamic_pointer_cast<BRAction>(act)) {
|
||||||
|
if (var_to_id.find(br_act->cond) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[br_act->cond]);
|
||||||
|
}
|
||||||
|
} else if (auto ret_act = std::dynamic_pointer_cast<RETAction>(act)) {
|
||||||
|
if (!std::holds_alternative<LLVMVOIDType>(ret_act->type) && var_to_id.find(ret_act->value) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[ret_act->value]);
|
||||||
|
}
|
||||||
|
} else if (auto bin_act = std::dynamic_pointer_cast<BinaryOperationAction>(act)) {
|
||||||
|
if (var_to_id.find(bin_act->operand1_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[bin_act->operand1_full]);
|
||||||
|
}
|
||||||
|
if (bin_act->operand2_full != bin_act->operand1_full &&
|
||||||
|
var_to_id.find(bin_act->operand2_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[bin_act->operand2_full]);
|
||||||
|
}
|
||||||
|
if (var_to_id.find(bin_act->result_full) != var_to_id.end()) {
|
||||||
|
cur_act_def.push_back(var_to_id[bin_act->result_full]);
|
||||||
|
}
|
||||||
|
} else if (auto load_act = std::dynamic_pointer_cast<LoadAction>(act)) {
|
||||||
|
if (var_to_id.find(load_act->ptr_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[load_act->ptr_full]);
|
||||||
|
}
|
||||||
|
if (var_to_id.find(load_act->result_full) != var_to_id.end()) {
|
||||||
|
cur_act_def.push_back(var_to_id[load_act->result_full]);
|
||||||
|
}
|
||||||
|
} else if (auto store_act = std::dynamic_pointer_cast<StoreAction>(act)) {
|
||||||
|
if (var_to_id.find(store_act->value_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[store_act->value_full]);
|
||||||
|
}
|
||||||
|
if (store_act->ptr_full == store_act->value_full)
|
||||||
|
throw std::runtime_error("store action should not have the same ptr and value");
|
||||||
|
if (var_to_id.find(store_act->ptr_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[store_act->ptr_full]);
|
||||||
|
}
|
||||||
|
} else if (auto get_act = std::dynamic_pointer_cast<GetElementPtrAction>(act)) {
|
||||||
|
std::unordered_set<std::string> used_vars;
|
||||||
|
if (var_to_id.find(get_act->ptr_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[get_act->ptr_full]);
|
||||||
|
used_vars.insert(get_act->ptr_full);
|
||||||
|
}
|
||||||
|
for (auto idx : get_act->indices) {
|
||||||
|
if (used_vars.find(idx) != used_vars.end()) continue;
|
||||||
|
if (var_to_id.find(idx) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[idx]);
|
||||||
|
used_vars.insert(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (var_to_id.find(get_act->result_full) != var_to_id.end()) {
|
||||||
|
cur_act_def.push_back(var_to_id[get_act->result_full]);
|
||||||
|
}
|
||||||
|
} else if (auto icmp_act = std::dynamic_pointer_cast<ICMPAction>(act)) {
|
||||||
|
if (var_to_id.find(icmp_act->operand1_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[icmp_act->operand1_full]);
|
||||||
|
}
|
||||||
|
if (icmp_act->operand2_full != icmp_act->operand1_full &&
|
||||||
|
var_to_id.find(icmp_act->operand2_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[icmp_act->operand2_full]);
|
||||||
|
}
|
||||||
|
if (var_to_id.find(icmp_act->result_full) != var_to_id.end()) {
|
||||||
|
cur_act_def.push_back(var_to_id[icmp_act->result_full]);
|
||||||
|
}
|
||||||
|
} else if (auto call_act = std::dynamic_pointer_cast<CallItem>(act)) {
|
||||||
|
std::unordered_set<std::string> used_vars;
|
||||||
|
for (auto arg : call_act->args_val_full) {
|
||||||
|
if (used_vars.find(arg) != used_vars.end()) continue;
|
||||||
|
if (var_to_id.find(arg) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[arg]);
|
||||||
|
used_vars.insert(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!std::holds_alternative<LLVMVOIDType>(call_act->return_type) &&
|
||||||
|
var_to_id.find(call_act->result_full) != var_to_id.end()) {
|
||||||
|
cur_act_def.push_back(var_to_id[call_act->result_full]);
|
||||||
|
}
|
||||||
|
} else if (auto select_act = std::dynamic_pointer_cast<SelectItem>(act)) {
|
||||||
|
if (var_to_id.find(select_act->cond_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[select_act->cond_full]);
|
||||||
|
}
|
||||||
|
if (select_act->true_val_full != select_act->cond_full &&
|
||||||
|
var_to_id.find(select_act->true_val_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[select_act->true_val_full]);
|
||||||
|
}
|
||||||
|
if (select_act->false_val_full != select_act->cond_full &&
|
||||||
|
select_act->false_val_full != select_act->cond_full &&
|
||||||
|
var_to_id.find(select_act->false_val_full) != var_to_id.end()) {
|
||||||
|
cur_act_use.push_back(var_to_id[select_act->false_val_full]);
|
||||||
|
}
|
||||||
|
if (var_to_id.find(select_act->result_full) != var_to_id.end()) {
|
||||||
|
cur_act_def.push_back(var_to_id[select_act->result_full]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(cur_act_use.begin(), cur_act_use.end());
|
||||||
|
std::sort(cur_act_def.begin(), cur_act_def.end());
|
||||||
|
for (size_t i = 1; i < cur_act_use.size(); i++) {
|
||||||
|
if (cur_act_use[i] == cur_act_use[i - 1]) {
|
||||||
|
throw std::runtime_error("use variable appears twice in one action");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i = 1; i < cur_act_def.size(); i++) {
|
||||||
|
if (cur_act_def[i] == cur_act_def[i - 1]) {
|
||||||
|
throw std::runtime_error("def variable appears twice in one action");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!use_def_init) {
|
||||||
|
use_def_init = true;
|
||||||
|
cur_node_use = cur_act_use;
|
||||||
|
cur_node_def = cur_act_def;
|
||||||
|
} else {
|
||||||
|
auto use_p = std::move(cur_node_use);
|
||||||
|
auto def_p = std::move(cur_node_def);
|
||||||
|
auto use_n = std::move(cur_act_use);
|
||||||
|
auto def_n = std::move(cur_act_def);
|
||||||
|
cur_node_use = GetCollectionsUnion(use_p, GetCollectionsDifference(use_n, def_p));
|
||||||
|
cur_node_def = GetCollectionsUnion(def_p, use_n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node->use_vars = cur_node_use;
|
||||||
|
node->def_vars = cur_node_def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiveAnalysis(CFGType &cfg) {
|
||||||
|
std::vector<std::string> id_to_var;
|
||||||
|
std::unordered_map<std::string, size_t> var_to_id;
|
||||||
|
VarCollect(cfg, id_to_var, var_to_id);
|
||||||
|
UseDefCollect(cfg, id_to_var, var_to_id);
|
||||||
|
std::vector<CFGNodeType *> exists;
|
||||||
|
for (auto node : cfg.nodes) {
|
||||||
|
node->in_active_vars = node->use_vars;
|
||||||
|
if (node->successors.size() == 0) {
|
||||||
|
exists.push_back(node.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool all_data_unchanged;
|
||||||
|
do {
|
||||||
|
all_data_unchanged = true;
|
||||||
|
for (auto node : cfg.nodes) {
|
||||||
|
node->visited = false;
|
||||||
|
}
|
||||||
|
std::queue<CFGNodeType *> Q;
|
||||||
|
for (auto e : exists) {
|
||||||
|
Q.push(e);
|
||||||
|
e->visited = true;
|
||||||
|
}
|
||||||
|
while (Q.size() > 0) {
|
||||||
|
auto cur_node = Q.front();
|
||||||
|
Q.pop();
|
||||||
|
for (auto pred : cur_node->predecessors) {
|
||||||
|
if (!pred->visited) {
|
||||||
|
pred->visited = true;
|
||||||
|
Q.push(pred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::vector<size_t> out_active_vars;
|
||||||
|
for (auto succ : cur_node->successors) {
|
||||||
|
out_active_vars = GetCollectionsUnion(out_active_vars, succ->in_active_vars);
|
||||||
|
}
|
||||||
|
if (!GetCollectionsIsSame(cur_node->out_active_vars, out_active_vars)) {
|
||||||
|
all_data_unchanged = false;
|
||||||
|
cur_node->out_active_vars = std::move(out_active_vars);
|
||||||
|
}
|
||||||
|
std::vector<size_t> in_active_vars = GetCollectionsUnion(
|
||||||
|
cur_node->use_vars, GetCollectionsDifference(cur_node->out_active_vars, cur_node->def_vars));
|
||||||
|
if (!GetCollectionsIsSame(cur_node->in_active_vars, in_active_vars)) {
|
||||||
|
all_data_unchanged = false;
|
||||||
|
cur_node->in_active_vars = std::move(in_active_vars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!all_data_unchanged);
|
||||||
|
}
|
@ -36,11 +36,11 @@ void BuildDomForFunction(const std::shared_ptr<FunctionDefItem> &func, const CFG
|
|||||||
if (cur->predecessors.size() > 0) {
|
if (cur->predecessors.size() > 0) {
|
||||||
CFGNodeCollection tmp = cur->predecessors[0]->dom;
|
CFGNodeCollection tmp = cur->predecessors[0]->dom;
|
||||||
for (size_t i = 1; i < cur->predecessors.size(); i++) {
|
for (size_t i = 1; i < cur->predecessors.size(); i++) {
|
||||||
tmp = GetCFGNodeCollectionsIntersection(tmp, cur->predecessors[i]->dom);
|
tmp = GetCollectionsIntersection(tmp, cur->predecessors[i]->dom);
|
||||||
}
|
}
|
||||||
new_dom = GetCFGNodeCollectionsUnion(new_dom, tmp);
|
new_dom = GetCollectionsUnion(new_dom, tmp);
|
||||||
}
|
}
|
||||||
if (!CFGNodeCollectionIsSame(new_dom, cur->dom)) {
|
if (!GetCollectionsIsSame(new_dom, cur->dom)) {
|
||||||
all_dom_unchanged = false;
|
all_dom_unchanged = false;
|
||||||
cur->dom = new_dom;
|
cur->dom = new_dom;
|
||||||
}
|
}
|
||||||
@ -59,10 +59,10 @@ void BuildDomForFunction(const std::shared_ptr<FunctionDefItem> &func, const CFG
|
|||||||
for (auto node : cfg.nodes) {
|
for (auto node : cfg.nodes) {
|
||||||
CFGNodeCollection is_frontier_of;
|
CFGNodeCollection is_frontier_of;
|
||||||
CFGNodeCollection tmp1 = {node.get()};
|
CFGNodeCollection tmp1 = {node.get()};
|
||||||
tmp1 = GetCFGNodeCollectionsDifference(node->dom, tmp1);
|
tmp1 = GetCollectionsDifference(node->dom, tmp1);
|
||||||
for (auto pred : node->predecessors) {
|
for (auto pred : node->predecessors) {
|
||||||
CFGNodeCollection tmp2 = GetCFGNodeCollectionsDifference(pred->dom, tmp1);
|
CFGNodeCollection tmp2 = GetCollectionsDifference(pred->dom, tmp1);
|
||||||
is_frontier_of = GetCFGNodeCollectionsUnion(is_frontier_of, tmp2);
|
is_frontier_of = GetCollectionsUnion(is_frontier_of, tmp2);
|
||||||
}
|
}
|
||||||
for (auto frontier_node : is_frontier_of) {
|
for (auto frontier_node : is_frontier_of) {
|
||||||
frontier_node->dom_frontier.push_back(node.get());
|
frontier_node->dom_frontier.push_back(node.get());
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
using namespace opt;
|
using namespace opt;
|
||||||
|
|
||||||
void ConductPhiEliminateForFunction([[maybe_unused]] std::shared_ptr<FunctionDefItem> func, CFGType &cfg) {
|
void ConductPhiEliminateForFunction(std::shared_ptr<FunctionDefItem> func, CFGType &cfg) {
|
||||||
size_t new_block_cnt = 0;
|
size_t new_block_cnt = 0;
|
||||||
for (auto cur_node : cfg.nodes) {
|
for (auto cur_node : cfg.nodes) {
|
||||||
auto cur_block = cur_node->corresponding_block;
|
auto cur_block = cur_node->corresponding_block;
|
||||||
@ -22,14 +22,23 @@ void ConductPhiEliminateForFunction([[maybe_unused]] std::shared_ptr<FunctionDef
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::unordered_map<std::string, BlockItem *> src_changed;
|
||||||
for (auto [_, phi_act] : cur_block->phi_map) {
|
for (auto [_, phi_act] : cur_block->phi_map) {
|
||||||
for (auto [src_val, src_label] : phi_act->values) {
|
for (auto [src_val, src_label] : phi_act->values) {
|
||||||
auto src_block = cfg.label_to_block[src_label];
|
auto src_block = cfg.label_to_block[src_label];
|
||||||
auto src_node = cfg.block_to_node[src_block];
|
auto src_node = cfg.block_to_node[src_block];
|
||||||
if (src_node->successors.size() > 1 && cur_node->predecessors.size() > 1) {
|
if (src_changed.find(src_label) != src_changed.end()) {
|
||||||
|
src_block = src_changed[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);
|
||||||
|
} else if (src_node->successors.size() > 1 && cur_node->predecessors.size() > 1) {
|
||||||
// it is a critical edge, need to insert a new block
|
// it is a critical edge, need to insert a new block
|
||||||
auto new_block = std::make_shared<BlockItem>();
|
auto new_block = std::make_shared<BlockItem>();
|
||||||
|
func->basic_blocks.push_back(new_block);
|
||||||
new_block->label_full = cur_block->label_full + ".phieliminate." + std::to_string(new_block_cnt++);
|
new_block->label_full = cur_block->label_full + ".phieliminate." + std::to_string(new_block_cnt++);
|
||||||
|
src_changed[src_label] = new_block.get();
|
||||||
new_block->exit_action = std::make_shared<UNConditionJMPAction>();
|
new_block->exit_action = std::make_shared<UNConditionJMPAction>();
|
||||||
std::dynamic_pointer_cast<UNConditionJMPAction>(new_block->exit_action)->label_full = cur_block->label_full;
|
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);
|
auto src_block_exit_action = std::dynamic_pointer_cast<BRAction>(src_block->exit_action);
|
||||||
@ -43,7 +52,9 @@ void ConductPhiEliminateForFunction([[maybe_unused]] std::shared_ptr<FunctionDef
|
|||||||
src_block_exit_action->false_label_full = new_block->label_full;
|
src_block_exit_action->false_label_full = new_block->label_full;
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"something strange happened: src block of a critical edge cannot find the corresponding label");
|
"something strange happened: src block of a critical edge cannot find the corresponding label, src "
|
||||||
|
"block label=" +
|
||||||
|
src_block->label_full);
|
||||||
}
|
}
|
||||||
auto new_move = std::make_shared<MoveInstruct>();
|
auto new_move = std::make_shared<MoveInstruct>();
|
||||||
new_move->src_full = src_val;
|
new_move->src_full = src_val;
|
||||||
|
@ -1 +1,15 @@
|
|||||||
#include "regalloc.h"
|
#include "regalloc.h"
|
||||||
|
|
||||||
|
void ConductRegAllocForFunction([[maybe_unused]] std::shared_ptr<FunctionDefItem> func, CFGType &cfg) {
|
||||||
|
LiveAnalysis(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ModuleItem> RegAlloc(std::shared_ptr<ModuleItem> src) {
|
||||||
|
auto res = src;
|
||||||
|
for (auto &func : res->function_defs) {
|
||||||
|
// func = std::make_shared<FunctionDefItem>(*func);
|
||||||
|
auto cfg = BuildCFGForFunction(func);
|
||||||
|
ConductRegAllocForFunction(func, cfg);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
Reference in New Issue
Block a user