first workable Mem2Reg

This commit is contained in:
ridethepig 2023-05-22 11:15:19 +08:00
parent 5e6107a02e
commit 8a9c32e820
10 changed files with 76 additions and 65 deletions

2
.vscode/launch.json vendored
View File

@ -9,7 +9,7 @@
"request": "launch", "request": "launch",
"name": "Debug", "name": "Debug",
"program": "${workspaceFolder}/build/sysy", "program": "${workspaceFolder}/build/sysy",
"args": ["../sysytests/functional_2022/21_if_test2.sy", "-S", "-o", "build/21_my.ll", "-emit-llvm"], "args": ["../sysytests/functional_2022/21_if_test2.sy", "-S", "-o", "build/21_my.ll", "-O1", "-emit-llvm"],
"cwd": "${workspaceFolder}" "cwd": "${workspaceFolder}"
} }
] ]

View File

@ -1,10 +1,10 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
#include <cassert>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include <cassert>
namespace antlrSysY { namespace antlrSysY {

View File

@ -9,8 +9,8 @@
#include <shared_mutex> #include <shared_mutex>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <vector>
#include <unordered_set> #include <unordered_set>
#include <vector>
namespace antlrSysY { namespace antlrSysY {

View File

@ -81,7 +81,12 @@ std::shared_ptr<InstGEP> build_InstGEP(
BasicBlockPtr_t parent_bb BasicBlockPtr_t parent_bb
); );
InstPhiPtr_t build_InstPhi(TypePtr_t type, const decltype(Function::bb_list) &incoming_vals, BasicBlockPtr_t parent_bb); InstPhiPtr_t build_InstPhi(
TypePtr_t type,
const decltype(Function::bb_list) &incoming_vals,
BasicBlockPtr_t parent_bb,
const std::string &name
);
#pragma endregion #pragma endregion

View File

@ -228,7 +228,7 @@ scheme_ref = {
scheme_my = { scheme_my = {
"name": "my", "name": "my",
"sy_ir": f"build/sysy -S {{sy}} -o {{ir}} -emit-llvm", "sy_ir": f"build/sysy -S {{sy}} -o {{ir}} -emit-llvm -O1",
"ir_asm": "llc --march=x86 --relocation-model=pic {ir} -o {asm}", "ir_asm": "llc --march=x86 --relocation-model=pic {ir} -o {asm}",
"asm_obj": "as --32 {asm} -o {obj}", "asm_obj": "as --32 {asm} -o {obj}",
"obj_bin": f"clang -m32 -Ofast -fPIE {{obj}} {LIB_PATH} -o {{bin}}", "obj_bin": f"clang -m32 -Ofast -fPIE {{obj}} {LIB_PATH} -o {{bin}}",

View File

@ -62,11 +62,11 @@ int main(int argc, const char **argv) {
#pragma region Logger #pragma region Logger
el::Configurations defaultConf; el::Configurations defaultConf;
defaultConf.setToDefault(); defaultConf.setToDefault();
defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%level %loc %msg"); defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%levshort %loc %msg");
defaultConf.set(el::Level::Warning, el::ConfigurationType::Format, "%level %loc %msg"); defaultConf.set(el::Level::Warning, el::ConfigurationType::Format, "%levshort %loc %msg");
defaultConf.set(el::Level::Error, el::ConfigurationType::Format, "%level %loc %msg"); defaultConf.set(el::Level::Error, el::ConfigurationType::Format, "%levshort %loc %msg");
defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%level %loc %msg"); defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%levshort %loc %msg");
defaultConf.set(el::Level::Verbose, el::ConfigurationType::Format, "%level %loc %msg"); defaultConf.set(el::Level::Verbose, el::ConfigurationType::Format, "%levshort%vlevel %loc %msg");
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput); el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
el::Loggers::reconfigureLogger("default", defaultConf); el::Loggers::reconfigureLogger("default", defaultConf);
#pragma endregion #pragma endregion

View File

@ -83,8 +83,7 @@ static void _build_cfg(const FunctionPtr_t func) {
else else
++itr; ++itr;
} }
if (VLOG_IS_ON(6)) print_cfg(func->bb_list.front(), true);
print_cfg(func->bb_list.front(), true);
} }
void PassBuildCFG::run(const Module &module) { void PassBuildCFG::run(const Module &module) {

View File

@ -69,6 +69,7 @@ static void analyze_alloca(InstAllocaPtr_t ai, AllocaInfo &info) {
info.only_in_1_block = false; info.only_in_1_block = false;
} }
} }
if (VLOG_IS_ON(6)) {
std::cout << "Alloca " << ai->name; std::cout << "Alloca " << ai->name;
std::cout << " Def: ["; std::cout << " Def: [";
for (auto blk : info.def_blocks) { for (auto blk : info.def_blocks) {
@ -76,12 +77,13 @@ static void analyze_alloca(InstAllocaPtr_t ai, AllocaInfo &info) {
} }
std::cout << "]\n"; std::cout << "]\n";
std::cout << " Use: ["; std::cout << " Use: [";
for (auto blk : info.def_blocks) { for (auto blk : info.use_blocks) {
std::cout << blk->name << ", "; std::cout << blk->name << ", ";
} }
std::cout << "]\n"; std::cout << "]\n";
std::cout.flush(); std::cout.flush();
} }
}
// static bool rewrite_single_store(InstAllocaPtr_t ai, AllocaInfo& alloca_info) { // static bool rewrite_single_store(InstAllocaPtr_t ai, AllocaInfo& alloca_info) {
@ -149,8 +151,10 @@ static void print_dom_info(BasicBlockPtr_t bb) {
} }
std::cout << "]\n"; std::cout << "]\n";
std::cout << " idomer: "; std::cout << " idomer: ";
if (bb->IDOM) std::cout << bb->IDOM->name; if (bb->IDOM)
else std::cout << "null"; std::cout << bb->IDOM->name;
else
std::cout << "null";
std::cout << "\n"; std::cout << "\n";
std::cout << " dom: ["; std::cout << " dom: [";
for (auto dom : bb->DOM_set) { for (auto dom : bb->DOM_set) {
@ -185,7 +189,7 @@ static void _mem_2_reg(FunctionPtr_t func) {
VLOG(4) << " Gen Dominance Tree & Frontier"; VLOG(4) << " Gen Dominance Tree & Frontier";
gen_dominance(func); gen_dominance(func);
gen_dominance_frontier(func); gen_dominance_frontier(func);
print_dom_tree(func->bb_list.front()); if (VLOG_IS_ON(6)) print_dom_tree(func->bb_list.front());
// actually, all variable alloca is placed at block head, so we collect them first // actually, all variable alloca is placed at block head, so we collect them first
std::vector<InstAllocaPtr_t> alloca_list; std::vector<InstAllocaPtr_t> alloca_list;
std::unordered_map<InstAllocaPtr_t, int> alloca_to_id; std::unordered_map<InstAllocaPtr_t, int> alloca_to_id;
@ -197,12 +201,12 @@ static void _mem_2_reg(FunctionPtr_t func) {
for (auto bb : func->bb_list) { for (auto bb : func->bb_list) {
for (auto inst : bb->inst_list) { for (auto inst : bb->inst_list) {
if (Value::is<InstAlloca>(inst)) { if (Value::is<InstAlloca>(inst)) {
assert(inst->parent_bb == bb); // assert(inst->parent_bb == bb);
// 貌似没问题parent_bb是插入alloca的时候的那个block而alloca实际上是被插入在entry_block的
assert(bb == func->bb_list.front() && "Alloca should be at front of a func"); assert(bb == func->bb_list.front() && "Alloca should be at front of a func");
auto ai = Value::as<InstAlloca>(inst); auto ai = Value::as<InstAlloca>(inst);
// assert(is_alloca_promotable(ai) && "Invalid alloca"); // assert(is_alloca_promotable(ai) && "Invalid alloca");
if (!Type::isType<IntegerType>(PointerType::pointedType(ai->type))) if (!Type::isType<IntegerType>(PointerType::pointedType(ai->type))) continue;
continue;
alloca_list.push_back(ai); alloca_list.push_back(ai);
} }
} }
@ -248,13 +252,14 @@ static void _mem_2_reg(FunctionPtr_t func) {
auto bb = worklist.front(); auto bb = worklist.front();
worklist.pop(); worklist.pop();
for (auto frontier : bb->DF_set) { for (auto frontier : bb->DF_set) {
// LOG(DEBUG) << "visiting " << bb->name <<" : " << frontier->name;
auto frontier_index = bb_to_id.at(frontier); auto frontier_index = bb_to_id.at(frontier);
if (!visited[frontier_index]) { if (!visited[frontier_index]) {
visited[frontier_index] = true; visited[frontier_index] = true;
if (livein_blocks.count(frontier)) { // if (livein_blocks.count(frontier)) {
auto inst_phi = build_InstPhi(TypeHelper::TYPE_I32, bb->predecessors, bb); auto inst_phi = build_InstPhi(TypeHelper::TYPE_I32, frontier->predecessors, frontier, ai->name);
phi_to_allocaid.insert({inst_phi, i}); phi_to_allocaid.insert({inst_phi, i});
} // }
if (!def_blocks.count(frontier)) { if (!def_blocks.count(frontier)) {
worklist.push(frontier); worklist.push(frontier);
} }
@ -266,8 +271,7 @@ static void _mem_2_reg(FunctionPtr_t func) {
// renaming // renaming
VLOG(4) << " variable renaming"; VLOG(4) << " variable renaming";
std::vector<ValuePtr_t> _init_values; std::vector<ValuePtr_t> _init_values;
for (int i = 0; i < alloca_list.size(); ++ i) for (int i = 0; i < alloca_list.size(); ++i) _init_values.push_back(ConstantInt::make_shared(0));
_init_values.push_back(ConstantInt::make_shared(0));
std::vector<RenameInfo> rename_list = {{func->bb_list.front(), nullptr, _init_values}}; std::vector<RenameInfo> rename_list = {{func->bb_list.front(), nullptr, _init_values}};
std::vector<bool> visited(bb_to_id.size(), 0); std::vector<bool> visited(bb_to_id.size(), 0);
while (!rename_list.empty()) { while (!rename_list.empty()) {
@ -292,8 +296,8 @@ static void _mem_2_reg(FunctionPtr_t func) {
// process instruction // process instruction
for (auto itr = rename_info.bb->inst_list.begin(); itr != rename_info.bb->inst_list.end();) { for (auto itr = rename_info.bb->inst_list.begin(); itr != rename_info.bb->inst_list.end();) {
auto inst = *itr++; auto inst = *itr++;
if (Value::is<InstAlloca>(inst)) { // we skip non-integer alloca, they are not in our alloca_list
assert(alloca_to_id.count(Value::as<InstAlloca>(inst))); if (Value::is<InstAlloca>(inst) && alloca_to_id.count(Value::as<InstAlloca>(inst))) {
rename_info.bb->inst_list.remove(inst); rename_info.bb->inst_list.remove(inst);
} }
else if (Value::is<InstLoad>(inst)) { else if (Value::is<InstLoad>(inst)) {

View File

@ -143,9 +143,11 @@ std::shared_ptr<InstGEP> build_InstGEP(
InstPhiPtr_t build_InstPhi( InstPhiPtr_t build_InstPhi(
TypePtr_t type, TypePtr_t type,
const decltype(Function::bb_list) &incoming_vals, const decltype(Function::bb_list) &incoming_vals,
BasicBlockPtr_t parent_bb BasicBlockPtr_t parent_bb,
const std::string &name
) { ) {
auto inst = std::make_shared<InstPhi>(type, incoming_vals, parent_bb); auto inst = std::make_shared<InstPhi>(type, incoming_vals, parent_bb);
inst->name = name;
parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst);
return inst; return inst;
} }

View File

@ -286,7 +286,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
} }
else if (Value::is<FParam>(inst->operand_list[i])) { else if (Value::is<FParam>(inst->operand_list[i])) {
auto op0 = Value::as<FParam>(inst->operand_list[i]); auto op0 = Value::as<FParam>(inst->operand_list[i]);
ostr << op0->to_IR_string() << ", "; ostr << op0->to_IR_string();
} }
else { else {
LOG(ERROR) << "Unexpected type of op_i: " << inst->operand_list[i]->to_string(); LOG(ERROR) << "Unexpected type of op_i: " << inst->operand_list[i]->to_string();
@ -467,6 +467,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
ostr << ", "; ostr << ", ";
} }
} }
ostr << " ; alloca: " << inst->name;
break; break;
} }
// These should not be generated in frontend stage // These should not be generated in frontend stage