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

finish part

parent f26d91aa
......@@ -2,6 +2,7 @@ build
Documentations/1-parser/*.pdf
compile_commands.json
.cache
.vscode
todo.txt
tmp.cminus
......@@ -204,13 +204,15 @@ class UniqueExpression : public Expression {
}
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)
: Expression(e_unique), instr_(instr) {}
private:
std::shared_ptr<Instruction> instr_;
Instruction *instr_;
};
} // namespace GVNExpression
......@@ -277,7 +279,7 @@ class GVN : public Pass {
BasicBlock *bb);
std::shared_ptr<GVNExpression::Expression> valueExpr(
Instruction *instr,
partitions *part = nullptr);
const partitions &part);
std::shared_ptr<GVNExpression::Expression> getVN(
const partitions &pout,
std::shared_ptr<GVNExpression::Expression> ve);
......@@ -293,11 +295,6 @@ class GVN : public Pass {
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:
bool dump_json_;
std::uint64_t next_value_number_ = 1;
......@@ -307,10 +304,24 @@ class GVN : public Pass {
std::unique_ptr<GVNExpression::ConstFolder> folder_;
std::unique_ptr<DeadCode> dce_;
// self add
// self add member
std::map<BasicBlock *, bool> _TOP;
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);
......@@ -235,9 +235,8 @@ GVN::join(const partitions &P1, const partitions &P2) {
return P;
}
std::shared_ptr<CongruenceClass>
GVN::intersect(std::shared_ptr<CongruenceClass> ci,
std::shared_ptr<CongruenceClass> cj) {
shared_ptr<CongruenceClass>
GVN::intersect(shared_ptr<CongruenceClass> ci, shared_ptr<CongruenceClass> cj) {
// TODO
auto c = createCongruenceClass();
std::set<Value *> intersection;
......@@ -256,15 +255,17 @@ GVN::intersect(std::shared_ptr<CongruenceClass> ci,
*ci->value_phi_ == *cj->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?
if (c->members_.size()) // not empty
{
if (c->index_ == 0) {
c->index_ = new_number();
c->value_phi_ =
c->value_expr_ = c->value_phi_ =
PhiExpression::create(ci->value_expr_, cj->value_expr_);
}
c->leader_ = *c->members_.begin();
}
return c;
}
......@@ -329,87 +330,119 @@ GVN::detectEquivalences() {
} while (changed);
}
// if v is already in one congruence set, return that value_expr_
// or return nullptr
shared_ptr<Expression>
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, partitions *part) {
GVN::valueExpr(Instruction *instr, const partitions &part) {
// TODO
// ?? should use part?
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()) {
auto op1 = instr->get_operand(0);
auto op2 = instr->get_operand(1);
auto op1_const = dynamic_cast<Constant *>(op1);
auto op2_const = dynamic_cast<Constant *>(op2);
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");
res = core_(instr, part, 2);
if (res.size() == 1) // constant fold
return res[0];
else
return BinaryExpression::create(
instr->get_instr_type(),
(op1_const ? ConstantExpression::create(op1_const)
: valueExpr(op1_instr)),
(op2_const ? ConstantExpression::create(op2_const)
: valueExpr(op2_instr)));
}
instr->get_instr_type(), res[0], res[1]);
} else if (instr->is_phi()) {
err = "phi";
} else if (instr->is_fp2si() or instr->is_si2fp() or instr->is_zext()) {
auto op = instr->get_operand(0);
auto op_const = dynamic_cast<Constant *>(op);
auto op_instr = dynamic_cast<Instruction *>(op);
assert(op_instr or op_const);
// get dest type
auto instr_fp2si = dynamic_cast<FpToSiInst *>(instr);
auto instr_si2fp = dynamic_cast<SiToFpInst *>(instr);
auto instr_zext = dynamic_cast<ZextInst *>(instr);
Type *dest_type = nullptr;
if (instr_fp2si)
dest_type = instr_fp2si->get_dest_type();
else if (instr_si2fp)
dest_type = instr_si2fp->get_dest_type();
else if (instr_zext)
dest_type = instr_zext->get_dest_type();
else
res = core_(instr, part, 1);
if (res[0]->get_expr_type() == Expression::e_constant)
return res[0];
Type *dest_type;
switch (instr->get_instr_type()) {
case Instruction::fptosi:
dest_type = static_cast<FpToSiInst *>(instr)->get_dest_type();
break;
case Instruction::sitofp:
dest_type = static_cast<SiToFpInst *>(instr)->get_dest_type();
break;
case Instruction::zext:
dest_type = static_cast<ZextInst *>(instr)->get_dest_type();
break;
default:
dest_type = nullptr;
err = "cast";
}
if (dest_type) {
if (op_const)
return ConstantExpression::create(
folder_->compute(instr, op_const));
else
return CastExpression::create(
instr->get_instr_type(), valueExpr(op_instr), dest_type);
instr->get_instr_type(), res[0], dest_type);
}
} else if (instr->is_gep()) {
auto operands = instr->get_operands();
auto ptr = operands[0];
std::vector<std::shared_ptr<Expression>> idxs;
// check for base address
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);
res = core_(instr, part, instr->get_operands().size(), false);
auto ptr = res[0];
res.erase(res.begin());
return GEPExpression::create(ptr, res);
} else if (instr->is_load() or instr->is_alloca() or instr->is_call()) {
return UniqueExpression::create(instr);
}
......@@ -450,31 +483,26 @@ GVN::transferFunction(Instruction *x, Value *e, partitions pin) {
if (e_const)
ve = ConstantExpression::create(e_const);
else
ve = valueExpr(e_instr, &pin);
ve = valueExpr(e_instr, pin);
} else
ve = valueExpr(x, &pin);
ve = valueExpr(x, pin);
auto vpf = valuePhiFunc(ve, curr_bb);
// TODO: set leader
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->members_.insert(x);
} else {
return pout;
}
}
auto c = createCongruenceClass(new_number());
c->members_.insert(x);
c->leader_ = x;
c->value_expr_ = ve;
c->value_phi_ = vpf;
pout.insert(c);
}
}
/* // first version: ignore ve and vpf
* // and only update index, leader and members
* auto c = createCongruenceClass(new_number());
* c->leader_ = x;
* c->members_.insert(x);
* pout.insert(c); */
return pout;
}
......@@ -492,6 +520,8 @@ GVN::transferFunction(BasicBlock *bb) {
* utils::print_partitions(pin_[bb]);
* LOG_INFO << "pout before:\n";
* 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
for (auto &instr : bb->get_instructions()) {
......@@ -503,7 +533,7 @@ GVN::transferFunction(BasicBlock *bb) {
for (auto succ : bb->get_succ_basic_blocks()) {
for (auto &instr : succ->get_instructions()) {
if (instr.is_phi()) {
if ((res = pretend_copy_stmt(&instr, bb) == -1))
if ((res = pretend_copy_stmt(&instr, bb)) == -1)
continue;
part = transferFunction(&instr, instr.get_operand(res), part);
}
......@@ -572,19 +602,19 @@ GVN::initPerFunction() {
void
GVN::replace_cc_members() {
for (auto &[_bb, part] : pout_) {
auto bb =
_bb; // workaround: structured bindings can't be captured in C++17
auto bb = _bb; // workaround: structured bindings can't be captured
// in C++17
for (auto &cc : part) {
if (cc->index_ == 0)
continue;
// if you are planning to do constant propagation, leaders should be
// set to constant at some point
// if you are planning to do constant propagation, leaders
// should be set to constant at some point
for (auto &member : cc->members_) {
bool member_is_phi = dynamic_cast<PhiInst *>(member);
bool value_phi = cc->value_phi_ != nullptr;
if (member != cc->leader_ and (value_phi or !member_is_phi)) {
// only replace the members if users are in the same block
// as bb
// only replace the members if users are in the same
// block as bb
member->replace_use_with_when(
cc->leader_, [bb](User *user) {
if (auto instr =
......@@ -650,7 +680,8 @@ GVN::run() {
gvn_json << "\n\"pout\": " << utils::dump_bb2partition(pout_);
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
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