Commit b1f2b21d authored by 李晓奇's avatar 李晓奇

finish part

parent f26d91aa
...@@ -2,6 +2,7 @@ build ...@@ -2,6 +2,7 @@ build
Documentations/1-parser/*.pdf Documentations/1-parser/*.pdf
compile_commands.json compile_commands.json
.cache .cache
.vscode
todo.txt todo.txt
tmp.cminus tmp.cminus
...@@ -204,13 +204,15 @@ class UniqueExpression : public Expression { ...@@ -204,13 +204,15 @@ class UniqueExpression : public Expression {
} }
virtual std::string print() { return "(UNIQUE " + instr_->print() + ")"; } virtual std::string print() { return "(UNIQUE " + instr_->print() + ")"; }
bool equiv(const UniqueExpression *other) const { return false; } bool equiv(const UniqueExpression *other) const {
return instr_ == other->instr_;
}
UniqueExpression(Instruction *instr) UniqueExpression(Instruction *instr)
: Expression(e_unique), instr_(instr) {} : Expression(e_unique), instr_(instr) {}
private: private:
std::shared_ptr<Instruction> instr_; Instruction *instr_;
}; };
} // namespace GVNExpression } // namespace GVNExpression
...@@ -277,7 +279,7 @@ class GVN : public Pass { ...@@ -277,7 +279,7 @@ class GVN : public Pass {
BasicBlock *bb); BasicBlock *bb);
std::shared_ptr<GVNExpression::Expression> valueExpr( std::shared_ptr<GVNExpression::Expression> valueExpr(
Instruction *instr, Instruction *instr,
partitions *part = nullptr); const partitions &part);
std::shared_ptr<GVNExpression::Expression> getVN( std::shared_ptr<GVNExpression::Expression> getVN(
const partitions &pout, const partitions &pout,
std::shared_ptr<GVNExpression::Expression> ve); std::shared_ptr<GVNExpression::Expression> ve);
...@@ -293,11 +295,6 @@ class GVN : public Pass { ...@@ -293,11 +295,6 @@ class GVN : public Pass {
return std::make_shared<CongruenceClass>(index); return std::make_shared<CongruenceClass>(index);
} }
// self add
//
std::uint64_t new_number() { return next_value_number_++; }
static int pretend_copy_stmt(Instruction *inst, BasicBlock *bb);
private: private:
bool dump_json_; bool dump_json_;
std::uint64_t next_value_number_ = 1; std::uint64_t next_value_number_ = 1;
...@@ -307,10 +304,24 @@ class GVN : public Pass { ...@@ -307,10 +304,24 @@ class GVN : public Pass {
std::unique_ptr<GVNExpression::ConstFolder> folder_; std::unique_ptr<GVNExpression::ConstFolder> folder_;
std::unique_ptr<DeadCode> dce_; std::unique_ptr<DeadCode> dce_;
// self add // self add member
std::map<BasicBlock *, bool> _TOP; std::map<BasicBlock *, bool> _TOP;
partitions join_helper(BasicBlock *pre1, BasicBlock *pre2); partitions join_helper(BasicBlock *pre1, BasicBlock *pre2);
BasicBlock* curr_bb; BasicBlock *curr_bb;
//
// self add function
//
std::uint64_t new_number() { return next_value_number_++; }
static int pretend_copy_stmt(Instruction *inst, BasicBlock *bb);
std::shared_ptr<GVNExpression::Expression> search_ve(
Value *v,
const partitions &part);
std::vector<std::shared_ptr<GVNExpression::Expression>> core_(
Instruction *instr,
const partitions &part,
size_t count,
bool fold_ = true);
}; };
bool operator==(const GVN::partitions &p1, const GVN::partitions &p2); bool operator==(const GVN::partitions &p1, const GVN::partitions &p2);
...@@ -235,9 +235,8 @@ GVN::join(const partitions &P1, const partitions &P2) { ...@@ -235,9 +235,8 @@ GVN::join(const partitions &P1, const partitions &P2) {
return P; return P;
} }
std::shared_ptr<CongruenceClass> shared_ptr<CongruenceClass>
GVN::intersect(std::shared_ptr<CongruenceClass> ci, GVN::intersect(shared_ptr<CongruenceClass> ci, shared_ptr<CongruenceClass> cj) {
std::shared_ptr<CongruenceClass> cj) {
// TODO // TODO
auto c = createCongruenceClass(); auto c = createCongruenceClass();
std::set<Value *> intersection; std::set<Value *> intersection;
...@@ -256,15 +255,17 @@ GVN::intersect(std::shared_ptr<CongruenceClass> ci, ...@@ -256,15 +255,17 @@ GVN::intersect(std::shared_ptr<CongruenceClass> ci,
*ci->value_phi_ == *cj->value_phi_) *ci->value_phi_ == *cj->value_phi_)
c->value_phi_ = ci->value_phi_; c->value_phi_ = ci->value_phi_;
// if (c->members_.size() or c->value_expr_ or c->value_phi_) // not empty
// ?? // ??
// What if the ve is nullptr? // What if the ve is nullptr?
if (c->members_.size()) // not empty if (c->members_.size()) // not empty
{
if (c->index_ == 0) { if (c->index_ == 0) {
c->index_ = new_number(); c->index_ = new_number();
c->value_phi_ = c->value_expr_ = c->value_phi_ =
PhiExpression::create(ci->value_expr_, cj->value_expr_); PhiExpression::create(ci->value_expr_, cj->value_expr_);
} }
c->leader_ = *c->members_.begin();
}
return c; return c;
} }
...@@ -276,7 +277,7 @@ GVN::detectEquivalences() { ...@@ -276,7 +277,7 @@ GVN::detectEquivalences() {
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())
std::cout << &instr << "\t" << instr.print() << std::endl; std::cout << &instr << "\t" << instr.print() << std::endl;
} }
// initialize pout with top // initialize pout with top
for (auto &bb : func_->get_basic_blocks()) { for (auto &bb : func_->get_basic_blocks()) {
...@@ -329,87 +330,119 @@ GVN::detectEquivalences() { ...@@ -329,87 +330,119 @@ GVN::detectEquivalences() {
} while (changed); } while (changed);
} }
// if v is already in one congruence set, return that value_expr_
// or return nullptr
shared_ptr<Expression> shared_ptr<Expression>
GVN::valueExpr(Instruction *instr, partitions *part) { GVN::search_ve(Value *v, const GVN::partitions &part) {
for (auto c : part) {
if (std::find(c->members_.begin(), c->members_.end(), v) !=
c->members_.end()) {
return c->value_expr_;
}
}
return nullptr;
}
// for each op, try to find the
std::vector<shared_ptr<Expression>>
GVN::core_(Instruction *instr,
const partitions &part,
size_t count,
bool fold_) {
assert(not(fold_ and count > 2));
Value *v;
Constant *v_const;
auto operands = instr->get_operands();
std::vector<shared_ptr<Expression>> ret;
// if able to fold, then fold
fold_ &= bool(dynamic_cast<Constant *>(operands[0]));
if (count == 2)
fold_ &= bool(dynamic_cast<Constant *>(operands[1]));
if (fold_) {
Constant *res;
if (count == 1) {
res =
folder_->compute(instr, dynamic_cast<Constant *>(operands[0]));
} else {
// count == 2
res = folder_->compute(instr,
dynamic_cast<Constant *>(operands[0]),
dynamic_cast<Constant *>(operands[1]));
}
ret.push_back(ConstantExpression::create(res));
return ret;
}
// normal case:
// - try to find expression that already exists
// - take care of constant
for (int i = 0; i != count; i++) {
v = operands[i];
v_const = dynamic_cast<Constant *>(v);
if (v_const) {
ret.push_back(ConstantExpression::create(v_const));
} else {
auto res = search_ve(v, part);
assert(res);
ret.push_back(res);
}
}
return ret;
}
shared_ptr<Expression>
GVN::valueExpr(Instruction *instr, const partitions &part) {
// TODO // TODO
// ?? should use part? // ?? should use part?
std::string err{"Undefined"}; std::string err{"Undefined"};
std::cout << instr->print() << std::endl; std::vector<shared_ptr<Expression>> res;
// first check if there is already one congruence class inside
auto tmp = search_ve(instr, part);
if (tmp)
return tmp;
if (instr->isBinary() or instr->is_cmp() or instr->is_fcmp()) { if (instr->isBinary() or instr->is_cmp() or instr->is_fcmp()) {
auto op1 = instr->get_operand(0); res = core_(instr, part, 2);
auto op2 = instr->get_operand(1); if (res.size() == 1) // constant fold
auto op1_const = dynamic_cast<Constant *>(op1); return res[0];
auto op2_const = dynamic_cast<Constant *>(op2); else
if (op1_const and op2_const) {
// both are constant number, so:
// constant fold!
return ConstantExpression::create(
folder_->compute(instr, op1_const, op2_const));
} else {
// both none constant
auto op1_instr = dynamic_cast<Instruction *>(op1);
auto op2_instr = dynamic_cast<Instruction *>(op2);
assert((op1_instr or op1_const) and (op2_instr or op2_const) &&
"must be this case");
return BinaryExpression::create( return BinaryExpression::create(
instr->get_instr_type(), instr->get_instr_type(), res[0], res[1]);
(op1_const ? ConstantExpression::create(op1_const)
: valueExpr(op1_instr)),
(op2_const ? ConstantExpression::create(op2_const)
: valueExpr(op2_instr)));
}
} else if (instr->is_phi()) { } else if (instr->is_phi()) {
err = "phi"; err = "phi";
} else if (instr->is_fp2si() or instr->is_si2fp() or instr->is_zext()) { } else if (instr->is_fp2si() or instr->is_si2fp() or instr->is_zext()) {
auto op = instr->get_operand(0); res = core_(instr, part, 1);
auto op_const = dynamic_cast<Constant *>(op); if (res[0]->get_expr_type() == Expression::e_constant)
auto op_instr = dynamic_cast<Instruction *>(op); return res[0];
assert(op_instr or op_const); Type *dest_type;
// get dest type switch (instr->get_instr_type()) {
auto instr_fp2si = dynamic_cast<FpToSiInst *>(instr); case Instruction::fptosi:
auto instr_si2fp = dynamic_cast<SiToFpInst *>(instr); dest_type = static_cast<FpToSiInst *>(instr)->get_dest_type();
auto instr_zext = dynamic_cast<ZextInst *>(instr); break;
Type *dest_type = nullptr; case Instruction::sitofp:
if (instr_fp2si) dest_type = static_cast<SiToFpInst *>(instr)->get_dest_type();
dest_type = instr_fp2si->get_dest_type(); break;
else if (instr_si2fp) case Instruction::zext:
dest_type = instr_si2fp->get_dest_type(); dest_type = static_cast<ZextInst *>(instr)->get_dest_type();
else if (instr_zext) break;
dest_type = instr_zext->get_dest_type(); default:
else dest_type = nullptr;
err = "cast"; err = "cast";
}
if (dest_type) { if (dest_type) {
if (op_const) return CastExpression::create(
return ConstantExpression::create( instr->get_instr_type(), res[0], dest_type);
folder_->compute(instr, op_const));
else
return CastExpression::create(
instr->get_instr_type(), valueExpr(op_instr), dest_type);
} }
} else if (instr->is_gep()) { } else if (instr->is_gep()) {
auto operands = instr->get_operands(); res = core_(instr, part, instr->get_operands().size(), false);
auto ptr = operands[0]; auto ptr = res[0];
std::vector<std::shared_ptr<Expression>> idxs; res.erase(res.begin());
// check for base address return GEPExpression::create(ptr, res);
assert(not dynamic_cast<Constant *>(ptr) and
dynamic_cast<Instruction *>(ptr) &&
"base address should only be from instruction");
// set idxes
for (int i = 1; i < operands.size(); i++) {
if (dynamic_cast<Constant *>(operands[i]))
idxs.push_back(ConstantExpression::create(
dynamic_cast<Constant *>(operands[i])));
else {
assert(dynamic_cast<Instruction *>(operands[i]));
idxs.push_back(
valueExpr(dynamic_cast<Instruction *>(operands[i])));
}
}
return GEPExpression::create(
valueExpr(dynamic_cast<Instruction *>(ptr)), idxs);
} else if (instr->is_load() or instr->is_alloca() or instr->is_call()) { } else if (instr->is_load() or instr->is_alloca() or instr->is_call()) {
return UniqueExpression::create(instr); return UniqueExpression::create(instr);
} }
...@@ -450,31 +483,26 @@ GVN::transferFunction(Instruction *x, Value *e, partitions pin) { ...@@ -450,31 +483,26 @@ GVN::transferFunction(Instruction *x, Value *e, partitions pin) {
if (e_const) if (e_const)
ve = ConstantExpression::create(e_const); ve = ConstantExpression::create(e_const);
else else
ve = valueExpr(e_instr, &pin); ve = valueExpr(e_instr, pin);
} else } else
ve = valueExpr(x, &pin); ve = valueExpr(x, pin);
auto vpf = valuePhiFunc(ve, curr_bb); auto vpf = valuePhiFunc(ve, curr_bb);
// TODO: set leader
for (auto c : pout) { for (auto c : pout) {
if (ve == c->value_expr_ or (vpf and vpf == c->value_phi_)) { if (ve == c->value_expr_ or
(vpf and c->value_phi_ and *vpf == *c->value_phi_)) {
c->value_expr_ = ve; c->value_expr_ = ve;
c->members_.insert(x); c->members_.insert(x);
} else { return pout;
auto c = createCongruenceClass(new_number());
c->members_.insert(x);
c->value_expr_ = ve;
c->value_phi_ = vpf;
pout.insert(c);
} }
} }
auto c = createCongruenceClass(new_number());
/* // first version: ignore ve and vpf c->members_.insert(x);
* // and only update index, leader and members c->leader_ = x;
* auto c = createCongruenceClass(new_number()); c->value_expr_ = ve;
* c->leader_ = x; c->value_phi_ = vpf;
* c->members_.insert(x); pout.insert(c);
* pout.insert(c); */
return pout; return pout;
} }
...@@ -491,7 +519,9 @@ GVN::transferFunction(BasicBlock *bb) { ...@@ -491,7 +519,9 @@ GVN::transferFunction(BasicBlock *bb) {
* LOG_INFO << "pin:\n"; * LOG_INFO << "pin:\n";
* utils::print_partitions(pin_[bb]); * utils::print_partitions(pin_[bb]);
* LOG_INFO << "pout before:\n"; * LOG_INFO << "pout before:\n";
* utils::print_partitions(pout_[bb]); */ * utils::print_partitions(pout_[bb]); */
std::cout << "for basic block " << bb->get_name() << ", pin:" << std::endl;
utils::print_partitions(pin_[bb]);
// iterate through all instructions in the block // iterate through all instructions in the block
for (auto &instr : bb->get_instructions()) { for (auto &instr : bb->get_instructions()) {
...@@ -503,7 +533,7 @@ GVN::transferFunction(BasicBlock *bb) { ...@@ -503,7 +533,7 @@ GVN::transferFunction(BasicBlock *bb) {
for (auto succ : bb->get_succ_basic_blocks()) { for (auto succ : bb->get_succ_basic_blocks()) {
for (auto &instr : succ->get_instructions()) { for (auto &instr : succ->get_instructions()) {
if (instr.is_phi()) { if (instr.is_phi()) {
if ((res = pretend_copy_stmt(&instr, bb) == -1)) if ((res = pretend_copy_stmt(&instr, bb)) == -1)
continue; continue;
part = transferFunction(&instr, instr.get_operand(res), part); part = transferFunction(&instr, instr.get_operand(res), part);
} }
...@@ -572,19 +602,19 @@ GVN::initPerFunction() { ...@@ -572,19 +602,19 @@ GVN::initPerFunction() {
void void
GVN::replace_cc_members() { GVN::replace_cc_members() {
for (auto &[_bb, part] : pout_) { for (auto &[_bb, part] : pout_) {
auto bb = auto bb = _bb; // workaround: structured bindings can't be captured
_bb; // workaround: structured bindings can't be captured in C++17 // in C++17
for (auto &cc : part) { for (auto &cc : part) {
if (cc->index_ == 0) if (cc->index_ == 0)
continue; continue;
// if you are planning to do constant propagation, leaders should be // if you are planning to do constant propagation, leaders
// set to constant at some point // should be set to constant at some point
for (auto &member : cc->members_) { for (auto &member : cc->members_) {
bool member_is_phi = dynamic_cast<PhiInst *>(member); bool member_is_phi = dynamic_cast<PhiInst *>(member);
bool value_phi = cc->value_phi_ != nullptr; bool value_phi = cc->value_phi_ != nullptr;
if (member != cc->leader_ and (value_phi or !member_is_phi)) { if (member != cc->leader_ and (value_phi or !member_is_phi)) {
// only replace the members if users are in the same block // only replace the members if users are in the same
// as bb // block as bb
member->replace_use_with_when( member->replace_use_with_when(
cc->leader_, [bb](User *user) { cc->leader_, [bb](User *user) {
if (auto instr = if (auto instr =
...@@ -592,7 +622,7 @@ GVN::replace_cc_members() { ...@@ -592,7 +622,7 @@ GVN::replace_cc_members() {
auto parent = instr->get_parent(); auto parent = instr->get_parent();
auto &bb_pre = parent->get_pre_basic_blocks(); auto &bb_pre = parent->get_pre_basic_blocks();
if (instr->is_phi()) // as copy stmt, the phi if (instr->is_phi()) // as copy stmt, the phi
// belongs to this block // belongs to this block
return std::find(bb_pre.begin(), return std::find(bb_pre.begin(),
bb_pre.end(), bb_pre.end(),
bb) != bb_pre.end(); bb) != bb_pre.end();
...@@ -650,7 +680,8 @@ GVN::run() { ...@@ -650,7 +680,8 @@ GVN::run() {
gvn_json << "\n\"pout\": " << utils::dump_bb2partition(pout_); gvn_json << "\n\"pout\": " << utils::dump_bb2partition(pout_);
gvn_json << "},"; gvn_json << "},";
} }
replace_cc_members(); // don't delete instructions, just replace them replace_cc_members(); // don't delete instructions, just replace
// them
} }
dce_->run(); // let dce do that for us dce_->run(); // let dce do that for us
if (dump_json_) if (dump_json_)
......
rm -rf *.ll
rm -rf gvn.json
rm -rf `ls | grep -v "\."`
rm -rf const-prop
rm -rf transpose
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