Commit b4870a73 authored by lxq's avatar lxq

have too many bugs now, use lab3 testcases to debug

parent 0454682c
...@@ -113,7 +113,7 @@ op6: <8, 8> ...@@ -113,7 +113,7 @@ op6: <8, 8>
程序有`$a`系列寄存器8个,`$t`系列9个,拿出`$t0``$t1`做IR生成汇编过程中的临时寄存器(这个方案仅在cminus下成立),所以可以自由分配的寄存器一共15个。 程序有`$a`系列寄存器8个,`$t`系列9个,拿出`$t0``$t1`做IR生成汇编过程中的临时寄存器(这个方案仅在cminus下成立),所以可以自由分配的寄存器一共15个。
首先完成对于局部变量的寄存器分配,即全局变量、传参依旧通过栈进行 首先完成对于局部变量和参数的整形寄存器分配
程序分配寄存器时会对部分指令做特殊处理,具体如下: 程序分配寄存器时会对部分指令做特殊处理,具体如下:
...@@ -135,4 +135,28 @@ op6: <8, 8> ...@@ -135,4 +135,28 @@ op6: <8, 8>
- `call`指令:使用栈传参,caller保存自己用到的寄存器,被保存的寄存器的活跃区间覆盖`call`指令的程序点。 - `call`指令:使用栈传参,caller保存自己用到的寄存器,被保存的寄存器的活跃区间覆盖`call`指令的程序点。
参数传递:固定为前8个参数分配`$a0`\~`$a7`,超过8个使用栈传递。
#### 4. 局部优化
- 基于跳转的bool变量翻译。
- GEP取值的优化:两个0的情况
- 常量取值的优化
-
#### 5. 测试样例
功能正确性由以下几部分测试样例作为证明:
- `/tests/5-bonus/testcases`
- `tests/3-ir-gen/testcases`
而性能主要向gcc看齐,主要测试样例为
- `tests/4-ir-opt/testcases/GVN/performance`
-
...@@ -11,9 +11,13 @@ ...@@ -11,9 +11,13 @@
#include "liverange.hpp" #include "liverange.hpp"
#include "regalloc.hpp" #include "regalloc.hpp"
#include <string>
#define __PRINT_ORI__
#define __RO_PART__ #define __RO_PART__
// #a = 8, #t = 9, reserve $t0, $t1 for temporary // #a = 8, #t = 9, reserve $t0, $t1 for temporary
#define R_USABLE 17 - 2 #define R_USABLE 17 - 2
#define ARG_R 8
#include <map> #include <map>
#include <ostream> #include <ostream>
...@@ -29,7 +33,7 @@ using std::vector; ...@@ -29,7 +33,7 @@ using std::vector;
class CodeGen { class CodeGen {
public: public:
CodeGen(Module *m_) : m(m_), LRA(m_, phi_map), RA(R_USABLE) {} CodeGen(Module *m_) : m(m_), LRA(m_, phi_map), RA(R_USABLE, ARG_R) {}
string print() { string print() {
string result; string result;
...@@ -74,9 +78,8 @@ class CodeGen { ...@@ -74,9 +78,8 @@ class CodeGen {
void stackMemDealloc(); void stackMemDealloc();
// In the case of register allocation, this function will return the // In the case of register allocation, this function will return the
// allocated register for that value, if the value possesses no register, // allocated register for that value, if the value possesses no register,
// choose from from $t0 or $t1 based on id // choose from from $t0 or $t1 based on id, or the input string(not "")
__attribute__((warn_unused_result)) string value2reg(Value *, int i = 0, string = "");
__attribute__((warn_unused_result)) string value2reg(Value *, int i = 0);
// load the content in ptr to specified register. // load the content in ptr to specified register.
void ptrContent2reg(Value *, string); void ptrContent2reg(Value *, string);
void compute_arg_info(Function *); void compute_arg_info(Function *);
...@@ -104,13 +107,16 @@ class CodeGen { ...@@ -104,13 +107,16 @@ class CodeGen {
return false; return false;
} }
auto is_float = lhs->get_type()->is_float_type(); auto is_float = lhs->get_type()->is_float_type();
gencopy(lhs_reg, rhs_reg, is_float);
return true;
}
void gencopy(string lhs_reg, string rhs_reg, bool is_float = false) {
if (rhs_reg != lhs_reg) { if (rhs_reg != lhs_reg) {
if (is_float) if (is_float)
output.push_back("fmov.s " + lhs_reg + ", " + rhs_reg); output.push_back("fmov.s " + lhs_reg + ", " + rhs_reg);
else else
output.push_back("or " + lhs_reg + ", $zero, " + rhs_reg); output.push_back("or " + lhs_reg + ", $zero, " + rhs_reg);
} }
return true;
} }
string label_in_assem(BasicBlock *bb) const { string label_in_assem(BasicBlock *bb) const {
...@@ -186,6 +192,8 @@ class CodeGen { ...@@ -186,6 +192,8 @@ class CodeGen {
name = "$a" + to_string(i - 1); name = "$a" + to_string(i - 1);
else if (9 <= i and i <= R_USABLE) else if (9 <= i and i <= R_USABLE)
name = "$t" + to_string(i - 9 + 2); name = "$t" + to_string(i - 9 + 2);
else
name = "WRONG_REG" + to_string(i);
} }
return name; return name;
} }
......
...@@ -49,7 +49,7 @@ class LiveRangeAnalyzer { ...@@ -49,7 +49,7 @@ class LiveRangeAnalyzer {
// void run(); // void run();
void run(Function *); void run(Function *);
void clear(); void clear();
void print(Function *func, bool printSet = true) const; void print(Function *func, bool printSet = false, bool printInt = false) const;
string print_liveSet(const LiveSet &ls) const { string print_liveSet(const LiveSet &ls) const {
string s = "[ "; string s = "[ ";
for (auto k : ls) for (auto k : ls)
......
#ifndef REGALLOCA_HPP
#define REGALLOCA_HPP
#include "Function.h"
#include "Value.h" #include "Value.h"
#include "liverange.hpp" #include "liverange.hpp"
...@@ -6,16 +9,12 @@ ...@@ -6,16 +9,12 @@
using std::cout; using std::cout;
using std::endl; using std::endl;
using std::to_string;
using namespace LRA; using namespace LRA;
namespace RA { namespace RA {
#define MAXR 32 #define MAXR 32
bool no_reg_alloca(Value *v);
struct ActiveCMP { struct ActiveCMP {
bool operator()(LiveInterval const &lhs, LiveInterval const &rhs) const { bool operator()(LiveInterval const &lhs, LiveInterval const &rhs) const {
if (lhs.first.j != rhs.first.j) if (lhs.first.j != rhs.first.j)
...@@ -27,11 +26,14 @@ struct ActiveCMP { ...@@ -27,11 +26,14 @@ struct ActiveCMP {
class RegAllocator { class RegAllocator {
public: public:
RegAllocator(const uint R_) : R(R_), used{false} { assert(R <= MAXR); } RegAllocator(const uint R_, const uint ARG_R_)
: R(R_), ARG_MAX_R(ARG_R_), used{false} {
assert(R <= MAXR);
}
RegAllocator() = delete; RegAllocator() = delete;
bool no_reg_alloca(Value *v) const;
// input set is sorted by increasing start point // input set is sorted by increasing start point
void LinearScan(const LVITS &liveints); void LinearScan(const LVITS &, Function *);
void reset();
const map<Value *, int> &get() const { return regmap; } const map<Value *, int> &get() const { return regmap; }
void print(string (*regname)(int)) { void print(string (*regname)(int)) {
for (auto [op, reg] : regmap) for (auto [op, reg] : regmap)
...@@ -39,13 +41,19 @@ class RegAllocator { ...@@ -39,13 +41,19 @@ class RegAllocator {
} }
private: private:
Function *cur_func;
const uint R; const uint R;
const uint ARG_MAX_R;
bool used[MAXR + 1]; // index range: 1 ~ R bool used[MAXR + 1]; // index range: 1 ~ R
map<Value *, int> regmap; map<Value *, int> regmap;
// sorted by increasing end point // sorted by increasing end point
set<LiveInterval, ActiveCMP> active; set<LiveInterval, ActiveCMP> active;
void reset(Function * = nullptr);
int ReserveForArg(const LVITS &);
void ExpireOldIntervals(LiveInterval); void ExpireOldIntervals(LiveInterval);
void SpillAtInterval(LiveInterval); void SpillAtInterval(LiveInterval);
}; };
} // namespace RA } // namespace RA
#endif
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <ostream>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <sys/types.h> #include <sys/types.h>
...@@ -19,6 +20,8 @@ ...@@ -19,6 +20,8 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#define CONST_0 ConstantInt::get(0, m)
// $r0 $zero constant 0 // $r0 $zero constant 0
// $r1 $ra return address // $r1 $ra return address
// $r2 $tp thread pointer // $r2 $tp thread pointer
...@@ -31,6 +34,7 @@ ...@@ -31,6 +34,7 @@
// $r23 - $r31 $s0 - $s8 static // $r23 - $r31 $s0 - $s8 static
using std::to_string; using std::to_string;
using std::operator""s;
pair<string, bool> pair<string, bool>
CodeGen::getRegName(Value *v, int i) const { CodeGen::getRegName(Value *v, int i) const {
...@@ -89,7 +93,7 @@ CodeGen::run() { ...@@ -89,7 +93,7 @@ CodeGen::run() {
for (auto &func : m->get_functions()) { for (auto &func : m->get_functions()) {
if (not func.is_declaration()) { if (not func.is_declaration()) {
LRA.run(&func); LRA.run(&func);
RA.LinearScan(LRA.get()); RA.LinearScan(LRA.get(), &func);
std::cout << "register map for function: " << func.get_name() std::cout << "register map for function: " << func.get_name()
<< std::endl; << std::endl;
...@@ -149,8 +153,8 @@ CodeGen::ptrContent2reg(Value *ptr, string reg_name) { ...@@ -149,8 +153,8 @@ CodeGen::ptrContent2reg(Value *ptr, string reg_name) {
string suff = suffix(ele_tp); string suff = suffix(ele_tp);
auto [addr_reg, find] = getRegName(ptr, 1); auto [addr_reg, find] = getRegName(ptr, 1);
if (not find) /* if (not find)
addr_reg = "$t1"; * addr_reg = "$t1"; */
if (dynamic_cast<GlobalVariable *>(ptr)) { if (dynamic_cast<GlobalVariable *>(ptr)) {
output.push_back("la.local " + addr_reg + ", " + ptr->get_name()); output.push_back("la.local " + addr_reg + ", " + ptr->get_name());
...@@ -174,15 +178,17 @@ CodeGen::ptrContent2reg(Value *ptr, string reg_name) { ...@@ -174,15 +178,17 @@ CodeGen::ptrContent2reg(Value *ptr, string reg_name) {
} }
string string
CodeGen::value2reg(Value *v, int i) { CodeGen::value2reg(Value *v, int i, string recommend) {
bool is_float = v->get_type()->is_float_type(); bool is_float = v->get_type()->is_float_type();
string tmp_ireg = "$t" + to_string(i); string tmp_ireg = "$t" + to_string(i);
auto [reg_name, find] = getRegName(v, i); auto [reg_name, find] = getRegName(v, i);
if (find) if (find)
return reg_name; return reg_name;
else if (recommend != "")
reg_name = recommend;
// now is the stack allocation case // now is the stack allocation case
if (dynamic_cast<Constant *>(v)) { if (dynamic_cast<Constant *>(v)) {
if (v == ConstantInt::get(0, m)) if (v == CONST_0)
return "$zero"; return "$zero";
auto constant = static_cast<Constant *>(v); auto constant = static_cast<Constant *>(v);
#ifdef __RO_PART__ #ifdef __RO_PART__
...@@ -239,10 +245,14 @@ CodeGen::value2reg(Value *v, int i) { ...@@ -239,10 +245,14 @@ CodeGen::value2reg(Value *v, int i) {
for (auto iter = args.begin(); id <= args.size(); ++iter, ++id) for (auto iter = args.begin(); id <= args.size(); ++iter, ++id)
if (*iter == v) if (*iter == v)
break; break;
string instr_ir = is_float ? "fld" : "ld"; if (id <= ARG_R)
output.push_back(instr_ir + suffix(v->get_type()) + " " + reg_name + return regname(ARG_R);
", $fp, " + else {
to_string(func_arg_off.at(cur_func).at(id))); string instr_ir = is_float ? "fld" : "ld";
output.push_back(instr_ir + suffix(v->get_type()) + " " + reg_name +
", $fp, " +
to_string(func_arg_off.at(cur_func).at(id)));
}
} else { } else {
string instr_ir = is_float ? "fld" : "ld"; string instr_ir = is_float ? "fld" : "ld";
output.push_back(instr_ir + suffix(v->get_type()) + " " + reg_name + output.push_back(instr_ir + suffix(v->get_type()) + " " + reg_name +
...@@ -258,15 +268,19 @@ CodeGen::compute_arg_info(Function *func) { ...@@ -258,15 +268,19 @@ CodeGen::compute_arg_info(Function *func) {
auto func_tp = func->get_function_type(); auto func_tp = func->get_function_type();
auto &arg_off = func_arg_off[func]; auto &arg_off = func_arg_off[func];
int argN = 0, arg_id = func->get_num_of_args(); int argN = 0, arg_id = func->get_num_of_args();
// only alloca stack memory for argk, k >= 8;
auto rend = func_tp->param_begin();
for (int i = 0; i < ARG_R and rend != func_tp->param_end(); ++i, ++rend)
;
// reserve space // reserve space
for (auto iter = func_tp->param_end(); iter != func_tp->param_begin();) { for (auto iter = func_tp->param_end(); iter != rend;) {
--iter; --iter;
auto tplen = typeLen(*iter); auto tplen = typeLen(*iter);
argN = ALIGN(argN, tplen) + tplen; argN = ALIGN(argN, tplen) + tplen;
arg_off[arg_id--] = argN; arg_off[arg_id--] = argN;
} }
for (arg_id = 1; arg_id <= func->get_num_of_args(); ++arg_id) for (arg_id = ARG_R + 1; arg_id <= func->get_num_of_args(); ++arg_id)
arg_off[arg_id] = argN - arg_off[arg_id]; arg_off.at(arg_id) = argN - arg_off.at(arg_id);
func_arg_N[func] = argN; func_arg_N[func] = argN;
} }
...@@ -349,7 +363,7 @@ CodeGen::bool2branch(Instruction *instr) { ...@@ -349,7 +363,7 @@ CodeGen::bool2branch(Instruction *instr) {
break; break;
case CmpInst::NE: { case CmpInst::NE: {
instr_ir = "bne"; instr_ir = "bne";
if (instr->get_operand(1) == ConstantInt::get(0, m) and if (instr->get_operand(1) == CONST_0 and
dynamic_cast<Instruction *>(instr->get_operand(0)) dynamic_cast<Instruction *>(instr->get_operand(0))
->is_zext()) { ->is_zext()) {
// something like: // something like:
...@@ -440,7 +454,7 @@ CodeGen::IR2assem(CallInst *instr) { ...@@ -440,7 +454,7 @@ CodeGen::IR2assem(CallInst *instr) {
int storeN = 0; int storeN = 0;
vector<std::tuple<Value *, string, int>> store_record; vector<std::tuple<Value *, string, int>> store_record;
for (auto [op, interval] : LRA.get_interval_map()) { for (auto [op, interval] : LRA.get_interval_map()) {
if (RA::no_reg_alloca(op)) if (RA.no_reg_alloca(op) or regmap.at(op) == 1)
continue; continue;
if (interval.i <= cur_i and cur_i <= interval.j) { if (interval.i <= cur_i and cur_i <= interval.j) {
int tplen = typeLen(op->get_type()); int tplen = typeLen(op->get_type());
...@@ -452,8 +466,9 @@ CodeGen::IR2assem(CallInst *instr) { ...@@ -452,8 +466,9 @@ CodeGen::IR2assem(CallInst *instr) {
int totalN = STACK_ALIGN(ALIGN(storeN, 8) + func_argN); int totalN = STACK_ALIGN(ALIGN(storeN, 8) + func_argN);
// cout << "debug: " << STACK_ALIGN(12) << endl; // cout << "debug: " << STACK_ALIGN(12) << endl;
// stack space allocation // stack space allocation
output.push_back("addi.d $sp, $sp, -" + to_string(totalN)); if (totalN)
string instr_ir, suff, reg; output.push_back("addi.d $sp, $sp, -" + to_string(totalN));
string instr_ir, suff, v_reg;
// place the reserved regs // place the reserved regs
for (auto [op, reg, off] : store_record) { for (auto [op, reg, off] : store_record) {
instr_ir = (op->get_type()->is_float_type() ? "fst" : "st"); instr_ir = (op->get_type()->is_float_type() ? "fst" : "st");
...@@ -461,15 +476,18 @@ CodeGen::IR2assem(CallInst *instr) { ...@@ -461,15 +476,18 @@ CodeGen::IR2assem(CallInst *instr) {
output.push_back(instr_ir + suff + " " + reg + ", $sp, " + output.push_back(instr_ir + suff + " " + reg + ", $sp, " +
to_string(totalN - off)); to_string(totalN - off));
} }
// place the arguments // pass arguments
for (int i = 1; i < instr->get_num_operand(); i++) { for (int arg_i = 1; arg_i < instr->get_num_operand(); arg_i++) {
auto arg = instr->get_operand(i); auto arg_value = instr->get_operand(arg_i);
// auto tplen = typeLen(arg->get_type()); v_reg = value2reg(arg_value);
instr_ir = (arg->get_type()->is_float_type() ? "fst" : "st"); if (arg_i <= ARG_R) { // pass by register
suff = suffix(arg->get_type()); gencopy(regname(arg_i), v_reg);
reg = value2reg(arg); } else { // pass by stack
output.push_back(instr_ir + suff + " " + reg + ", $sp, " + instr_ir = (arg_value->get_type()->is_float_type() ? "fst" : "st");
to_string(func_arg_off.at(func).at(i))); suff = suffix(arg_value->get_type());
output.push_back(instr_ir + suff + " " + v_reg + ", $sp, " +
to_string(func_arg_off.at(func).at(arg_i)));
}
} }
output.push_back("bl " + func->get_name()); output.push_back("bl " + func->get_name());
// bug here: maybe // bug here: maybe
...@@ -481,8 +499,8 @@ CodeGen::IR2assem(CallInst *instr) { ...@@ -481,8 +499,8 @@ CodeGen::IR2assem(CallInst *instr) {
output.push_back(instr_ir + suff + " " + reg + ", $sp, " + output.push_back(instr_ir + suff + " " + reg + ", $sp, " +
to_string(totalN - off)); to_string(totalN - off));
} }
output.push_back("addi.d $sp, $sp, " + to_string(totalN)); if (totalN)
// output.push_back("addi.d $fp, $sp, " + to_string(stackN)); output.push_back("addi.d $sp, $sp, " + to_string(totalN));
} }
void void
...@@ -502,34 +520,27 @@ CodeGen::IR2assem(BinaryInst *instr) { ...@@ -502,34 +520,27 @@ CodeGen::IR2assem(BinaryInst *instr) {
void void
CodeGen::IR2assem(GetElementPtrInst *instr) { CodeGen::IR2assem(GetElementPtrInst *instr) {
assert(instr->get_num_operand() <= 3); assert(instr->get_num_operand() <= 3);
auto addr_reg = value2reg(instr->get_operand(0), 0); auto [dest_reg, _] = getRegName(instr);
assert(addr_reg == "$t0");
auto off = instr->get_operand(instr->get_num_operand() == 3 ? 2 : 1);
Type *type = instr->get_operand(0)->get_type(); if (off == CONST_0) {
for (int i = 1; i < instr->get_num_operand(); i++) { auto final_reg = value2reg(instr->get_operand(0), 0, dest_reg);
int size; gencopy(instr, final_reg);
if (type->is_array_type()) { return;
size = type->get_array_element_type()->get_size(); }
type = type->get_array_element_type(); if (instr->get_num_operand() == 3) {
} else if (type->is_pointer_type()) { // %op54 = getelementptr [66 x i32], [66 x i32]* @dp, i32 0, i32 %op41
size = type->get_size(); assert(instr->get_operand(1) == CONST_0);
type = type->get_pointer_element_type(); } else { // %op38 = getelementptr i32, i32* %arg1, i32 %op34
} else
assert(false && "GEP translation error");
if (size != 4) {
// getelementptr [5 x i32], [5 x i32]* @w, i32 0, i32 4
assert(instr->get_operand(i) == ConstantInt::get(0, m) &&
"cminus support only 1 dimension array, so first offset is "
"must 0");
continue;
}
auto off_reg = value2reg(instr->get_operand(i), 1);
// value2reg(ConstantInt::get(size, m), 2);
output.push_back("slli.d " + off_reg + ", " + off_reg + ", 2");
output.push_back("add.d " + addr_reg + ", " + addr_reg + ", " +
off_reg);
} }
gencopy(instr, addr_reg); auto addr_reg = value2reg(instr->get_operand(0), 0);
auto off_reg = value2reg(off, 1);
auto tmp_reg = "$t1"s;
output.push_back("slli.d " + tmp_reg + ", " + off_reg + ", 2");
output.push_back("add.d " + dest_reg + ", " + addr_reg + ", " + tmp_reg);
gencopy(instr, dest_reg);
} }
void void
...@@ -559,7 +570,7 @@ CodeGen::IR2assem(ReturnInst *instr) { ...@@ -559,7 +570,7 @@ CodeGen::IR2assem(ReturnInst *instr) {
if (is_float and reg != "$fa0") if (is_float and reg != "$fa0")
output.push_back("fmov.s $fa0, " + reg); output.push_back("fmov.s $fa0, " + reg);
else if (not is_float and reg != "$a0") else if (not is_float and reg != "$a0")
output.push_back("or $a0, $zero " + reg); output.push_back("or $a0, $zero, " + reg);
} }
output.push_back("b " + cur_func->get_name() + "_end"); output.push_back("b " + cur_func->get_name() + "_end");
...@@ -569,7 +580,9 @@ void ...@@ -569,7 +580,9 @@ void
CodeGen::IR2assem(Instruction &instr, BasicBlock &bb) { CodeGen::IR2assem(Instruction &instr, BasicBlock &bb) {
if (instr.is_br() or instr.is_ret()) if (instr.is_br() or instr.is_ret())
copystmt(&bb); copystmt(&bb);
#ifdef __PRINT_ORI__
output.push_back("# " + instr.print()); output.push_back("# " + instr.print());
#endif
switch (instr.get_instr_type()) { switch (instr.get_instr_type()) {
case Instruction::ret: case Instruction::ret:
IR2assem(static_cast<ReturnInst *>(&instr)); IR2assem(static_cast<ReturnInst *>(&instr));
......
#include "liverange.hpp" #include "liverange.hpp"
#include "Function.h"
using std::cout; using std::cout;
using std::endl; using std::endl;
using namespace LRA; using namespace LRA;
...@@ -58,9 +60,6 @@ void ...@@ -58,9 +60,6 @@ void
LiveRangeAnalyzer::run(Function *func) { LiveRangeAnalyzer::run(Function *func) {
clear(); clear();
make_id(func); make_id(func);
#ifdef __LRA_PRINT__
print(func, false);
#endif
bool cont = true; bool cont = true;
while (cont) { while (cont) {
cont = false; cont = false;
...@@ -128,7 +127,7 @@ LiveRangeAnalyzer::run(Function *func) { ...@@ -128,7 +127,7 @@ LiveRangeAnalyzer::run(Function *func) {
make_interval(func); make_interval(func);
#ifdef __LRA_PRINT__ #ifdef __LRA_PRINT__
print(func); print(func, false, true);
#endif #endif
} }
...@@ -166,12 +165,15 @@ LiveRangeAnalyzer::transferFunction(Instruction *instr) { ...@@ -166,12 +165,15 @@ LiveRangeAnalyzer::transferFunction(Instruction *instr) {
// - function // - function
// - Constant // - Constant
// - instruction // - instruction
// - argument // - argument*
// - BasicBlock // - BasicBlock
auto ins = dynamic_cast<Instruction *>(op); auto ins = dynamic_cast<Instruction *>(op);
auto arg = dynamic_cast<Argument *>(op);
if (ins) { if (ins) {
assert(not ins->is_void() && "instr as op should not be void"); assert(not ins->is_void() && "instr as op should not be void");
use.insert(op); use.insert(op);
} else if (arg) {
use.insert(op);
} }
} }
// in = use + (out - def) // in = use + (out - def)
...@@ -188,7 +190,9 @@ LiveRangeAnalyzer::transferFunction(Instruction *instr) { ...@@ -188,7 +190,9 @@ LiveRangeAnalyzer::transferFunction(Instruction *instr) {
} }
void void
LiveRangeAnalyzer::print(Function *func, bool printSet) const { // for debug LiveRangeAnalyzer::print(Function *func,
bool printSet,
bool printInt) const { // for debug
cout << "Function " << func->get_name() << endl; cout << "Function " << func->get_name() << endl;
for (auto &bb : func->get_basic_blocks()) { for (auto &bb : func->get_basic_blocks()) {
for (auto &instr : bb.get_instructions()) { for (auto &instr : bb.get_instructions()) {
...@@ -225,7 +229,7 @@ LiveRangeAnalyzer::print(Function *func, bool printSet) const { // for debug ...@@ -225,7 +229,7 @@ LiveRangeAnalyzer::print(Function *func, bool printSet) const { // for debug
} }
} }
if (printSet) { if (printInt) {
for (auto [interval, op] : liveIntervals) for (auto [interval, op] : liveIntervals)
cout << op->get_name() << ": " << print_interval(interval) << endl; cout << op->get_name() << ": " << print_interval(interval) << endl;
} }
......
#include "regalloc.hpp" #include "regalloc.hpp"
#include "Function.h"
#include "Instruction.h" #include "Instruction.h"
#include "liverange.hpp" #include "liverange.hpp"
...@@ -9,25 +10,67 @@ using std::for_each; ...@@ -9,25 +10,67 @@ using std::for_each;
using namespace RA; using namespace RA;
int
get_arg_id(Argument *arg) {
auto args = arg->get_parent()->get_args();
int id = 1;
for (auto a : args) {
if (a == arg)
break;
++id;
}
return id;
}
bool bool
RA::no_reg_alloca(Value *v) { RegAllocator::no_reg_alloca(Value *v) const {
auto instr = static_cast<Instruction *>(v); auto instr = dynamic_cast<Instruction *>(v);
return instr->is_alloca() or instr->is_cmp() or instr->is_fcmp() or auto arg = dynamic_cast<Argument *>(v);
instr->is_zext(); if (instr)
return instr->is_alloca() or instr->is_cmp() or instr->is_fcmp() or
instr->is_zext();
if (arg) {
return get_arg_id(arg) > ARG_MAX_R;
} else
assert(false && "only instruction and argument's LiveInterval exits");
} }
void void
RegAllocator::reset() { RegAllocator::reset(Function *func) {
cur_func = func;
regmap.clear(); regmap.clear();
active.clear(); active.clear();
for_each(used, used + R + 1, [](bool &u) { u = false; }); for_each(used, used + R + 1, [](bool &u) { u = false; });
} }
int
RegAllocator::ReserveForArg(const LVITS &Liveints) {
auto args = cur_func->get_args();
auto it_int = Liveints.begin();
auto it_arg = args.begin();
int reg;
for (reg = 1; reg <= args.size() and reg <= ARG_MAX_R; ++reg) {
auto arg = *it_arg;
auto liveint = *it_int;
assert(arg == liveint.second && "arg should be in order in liveints");
used[reg] = true;
regmap[arg] = reg;
active.insert(liveint);
++it_arg, ++it_int;
}
return reg;
}
void void
RegAllocator::LinearScan(const LVITS &liveints) { RegAllocator::LinearScan(const LVITS &liveints, Function *func) {
reset(); reset(func);
ReserveForArg(liveints);
int reg; int reg;
for (auto liveint : liveints) { for (auto liveint : liveints) {
if (dynamic_cast<Argument *>(liveint.second)) {
continue;
}
if (no_reg_alloca(liveint.second)) if (no_reg_alloca(liveint.second))
continue; continue;
ExpireOldIntervals(liveint); ExpireOldIntervals(liveint);
...@@ -54,6 +97,8 @@ RegAllocator::ExpireOldIntervals(LiveInterval liveint) { ...@@ -54,6 +97,8 @@ RegAllocator::ExpireOldIntervals(LiveInterval liveint) {
void void
RegAllocator::SpillAtInterval(LiveInterval liveint) { RegAllocator::SpillAtInterval(LiveInterval liveint) {
auto spill = *active.rbegin(); auto spill = *active.rbegin();
if (dynamic_cast<Argument *>(spill.second))
return;
if (spill.first.j > liveint.first.j) { if (spill.first.j > liveint.first.j) {
// cancel reg allocation for spill // cancel reg allocation for spill
regmap[liveint.second] = regmap.at(spill.second); regmap[liveint.second] = regmap.at(spill.second);
......
int getarg(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j)
{
output(a);
output(b);
output(c);
output(d);
output(e);
output(f);
output(g);
output(h);
output(i);
output(j);
}
int main(void)
{
int arr[100];
arr[0] = input();
arr[1] = input();
arr[2] = input();
arr[3] = input();
arr[4] = input();
arr[5] = input();
arr[6] = input();
arr[7] = input();
arr[8] = input();
arr[9] = input();
getarg(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8], arr[9]);
return 0;
}
826
-652
-395
146
704
859
728
556
609
-822
826
-652
-395
146
704
859
728
556
609
-822
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment