Commit 08898ecb authored by 李晓奇's avatar 李晓奇

now shuold pass loop3!

parent b1f2b21d
......@@ -69,6 +69,8 @@ class ConstantExpression : public Expression {
}
ConstantExpression(Constant *c) : Expression(e_constant), c_(c) {}
Constant *get_val() { return c_; }
private:
Constant *c_;
};
......@@ -199,20 +201,24 @@ class GEPExpression : public Expression {
// unique expression: not equal to any one else
class UniqueExpression : public Expression {
public:
static std::shared_ptr<UniqueExpression> create(Instruction *instr) {
return std::make_shared<UniqueExpression>(instr);
static std::shared_ptr<UniqueExpression> create(Instruction *instr,
size_t index) {
return std::make_shared<UniqueExpression>(instr, index);
}
virtual std::string print() { return "(UNIQUE " + instr_->print() + ")"; }
// virtual std::string print() { return "(UNIQUE " + instr_->print() + ")";
// }
virtual std::string print() { return "v" + std::to_string(index_); }
bool equiv(const UniqueExpression *other) const {
return instr_ == other->instr_;
}
UniqueExpression(Instruction *instr)
: Expression(e_unique), instr_(instr) {}
UniqueExpression(Instruction *instr, size_t index)
: Expression(e_unique), instr_(instr), index_(index) {}
private:
Instruction *instr_;
size_t index_;
};
} // namespace GVNExpression
......@@ -276,7 +282,8 @@ class GVN : public Pass {
partitions transferFunction(BasicBlock *bb);
std::shared_ptr<GVNExpression::PhiExpression> valuePhiFunc(
std::shared_ptr<GVNExpression::Expression>,
BasicBlock *bb);
BasicBlock *bb,
Instruction *instr);
std::shared_ptr<GVNExpression::Expression> valueExpr(
Instruction *instr,
const partitions &part);
......@@ -308,6 +315,7 @@ class GVN : public Pass {
std::map<BasicBlock *, bool> _TOP;
partitions join_helper(BasicBlock *pre1, BasicBlock *pre2);
BasicBlock *curr_bb;
std::map<std::pair<Instruction *, Value *>, size_t> start_idx_;
//
// self add function
//
......@@ -317,11 +325,17 @@ class GVN : public Pass {
Value *v,
const partitions &part);
std::vector<std::shared_ptr<GVNExpression::Expression>> core_(
std::vector<std::shared_ptr<GVNExpression::Expression>> valueExpr_core_(
Instruction *instr,
const partitions &part,
size_t count,
const size_t count,
bool fold_ = true);
Constant *constFold_core(const size_t count,
const partitions &part,
Instruction *instr,
const std::vector<Value *> &operands);
void assign_start_idx_();
void dump_tmp(Function &);
};
bool operator==(const GVN::partitions &p1, const GVN::partitions &p2);
......@@ -199,6 +199,8 @@ dump_bb2partition(const std::map<BasicBlock *, GVN::partitions> &map) {
static void
print_partitions(const GVN::partitions &p) {
if (p.empty()) {
// to del
// std::cout << "empty partitions\n";
LOG_DEBUG << "empty partitions\n";
return;
}
......@@ -206,13 +208,14 @@ print_partitions(const GVN::partitions &p) {
for (auto &cc : p)
log += print_congruence_class(*cc);
LOG_DEBUG << log; // please don't use std::cout
// to del
// std::cout << log;
}
} // namespace utils
GVN::partitions
GVN::join_helper(BasicBlock *pre1, BasicBlock *pre2) {
assert(not _TOP[pre1] or not _TOP[pre2] && "should flow here, not jump");
if (_TOP[pre1])
return pout_[pre2];
else if (_TOP[pre2])
......@@ -260,25 +263,70 @@ GVN::intersect(shared_ptr<CongruenceClass> ci, shared_ptr<CongruenceClass> cj) {
if (c->members_.size()) // not empty
{
if (c->index_ == 0) {
c->index_ = new_number();
// it must be a phi instruction
// and be separated to 2 copy statement
// we should use the copy-stmt int the previous block
auto instr = static_cast<Instruction *>(*c->members_.begin());
auto instr_phi = dynamic_cast<PhiInst *>(instr);
int exact_idx;
// trick here: use the exact value number
if (instr_phi) {
auto exact_pre_bb =
*(instr_phi->get_parent()->get_pre_basic_blocks().begin());
auto e = instr_phi->get_operand(
pretend_copy_stmt(instr_phi, exact_pre_bb));
exact_idx = start_idx_.at(std::make_pair(instr_phi, e));
} else {
exact_idx = start_idx_.at(std::make_pair(instr, nullptr));
}
c->index_ = exact_idx;
c->value_expr_ = c->value_phi_ =
PhiExpression::create(ci->value_expr_, cj->value_expr_);
}
// ??
c->leader_ = *c->members_.begin();
}
return c;
}
// assign start index for each instruction, including copy statement
// ther logic here:
// - use the same traver order as main run
// - assign an incremental number for each instruction
void
GVN::assign_start_idx_() {
int res;
for (auto &bb : func_->get_basic_blocks()) {
for (auto &instr : bb.get_instructions()) {
if (not instr.is_phi() and not instr.is_void())
start_idx_[std::make_pair(&instr, nullptr)] = new_number();
}
// and the phi instruction in all the successors
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)
continue;
start_idx_[std::make_pair(&instr, instr.get_operand(res))] =
new_number();
}
}
}
}
next_value_number_ = 1;
}
void
GVN::detectEquivalences() {
int times = 0;
bool changed;
std::cout << "all the instruction address:" << std::endl;
for (auto &bb : func_->get_basic_blocks()) {
for (auto &instr : bb.get_instructions())
std::cout << &instr << "\t" << instr.print() << std::endl;
}
assign_start_idx_();
// initialize pout with top
for (auto &bb : func_->get_basic_blocks()) {
_TOP[&bb] = true;
......@@ -293,6 +341,7 @@ GVN::detectEquivalences() {
// iterate until converge
do {
changed = false;
std::cout << ++times << "th iteration" << std::endl;
for (auto &_bb : func_->get_basic_blocks()) {
auto bb = &_bb;
if (bb == Entry)
......@@ -306,12 +355,12 @@ GVN::detectEquivalences() {
case 2: {
auto pre_1 = *pre_bbs_.begin();
auto pre_2 = *(++pre_bbs_.begin());
pin_[bb] = join_helper(pre_1, pre_2);
pin_[bb] = clone(join_helper(pre_1, pre_2));
break;
}
case 1: {
auto pre = *(pre_bbs_.begin());
pin_[bb] = pout_[pre];
pin_[bb] = clone(pout_[pre]);
break;
}
default:
......@@ -324,9 +373,15 @@ GVN::detectEquivalences() {
// check changes in pout
changed |= not(part == pout_[bb]);
pout_[bb] = part;
pout_[bb] = clone(part);
_TOP[bb] = false;
/* std::cout << "//-------\n"
* << "//after transferFunction(basic-block="
* << bb->get_name() << "), all pout:" << std::endl; */
// dump_tmp(*func_);
}
// reset value number
} while (changed);
}
......@@ -343,12 +398,52 @@ GVN::search_ve(Value *v, const GVN::partitions &part) {
return nullptr;
}
// try constant fold for `count` operands
// the related instr is `instr`
Constant *
GVN::constFold_core(const size_t count,
const partitions &part,
Instruction *instr,
const std::vector<Value *> &operands) {
assert(count == 1 or count == 2);
Constant *res = nullptr;
// the first operand
auto op0_const_value = dynamic_cast<Constant *>(operands[0]);
auto op0_search_ = search_ve(operands[0], part);
auto op0_const_expr =
op0_search_ ? dynamic_cast<ConstantExpression *>(op0_search_.get())
: nullptr;
if ((op0_const_value or op0_const_expr)) {
auto op0_const =
op0_const_value ? op0_const_value : op0_const_expr->get_val();
// by now: the type cast instruction can do constant fold
if (count == 1)
res = folder_->compute(instr, op0_const);
if (count == 2) {
// the second operand
auto op1_const_value = dynamic_cast<Constant *>(operands[1]);
auto op1_search_ = search_ve(operands[1], part);
auto op1_const_expr =
op1_search_
? dynamic_cast<ConstantExpression *>(op1_search_.get())
: nullptr;
if (op1_const_value or op1_const_expr) {
auto op1_const = op1_const_value ? op1_const_value
: op1_const_expr->get_val();
res = folder_->compute(instr, op0_const, op1_const);
}
}
}
return res;
}
// for each op, try to find the
std::vector<shared_ptr<Expression>>
GVN::core_(Instruction *instr,
const partitions &part,
size_t count,
bool fold_) {
GVN::valueExpr_core_(Instruction *instr,
const partitions &part,
const size_t count,
bool fold_) {
assert(not(fold_ and count > 2));
Value *v;
......@@ -357,22 +452,12 @@ GVN::core_(Instruction *instr,
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]));
Constant *res = nullptr;
if ((res = constFold_core(count, part, instr, operands))) {
ret.push_back(ConstantExpression::create(res));
return ret;
}
ret.push_back(ConstantExpression::create(res));
return ret;
}
// normal case:
......@@ -405,7 +490,7 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
return tmp;
if (instr->isBinary() or instr->is_cmp() or instr->is_fcmp()) {
res = core_(instr, part, 2);
res = valueExpr_core_(instr, part, 2);
if (res.size() == 1) // constant fold
return res[0];
else
......@@ -414,7 +499,7 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
} else if (instr->is_phi()) {
err = "phi";
} else if (instr->is_fp2si() or instr->is_si2fp() or instr->is_zext()) {
res = core_(instr, part, 1);
res = valueExpr_core_(instr, part, 1);
if (res[0]->get_expr_type() == Expression::e_constant)
return res[0];
Type *dest_type;
......@@ -439,12 +524,16 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
instr->get_instr_type(), res[0], dest_type);
}
} else if (instr->is_gep()) {
res = core_(instr, part, instr->get_operands().size(), false);
res = valueExpr_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);
auto ret = search_ve(instr, part);
if (ret)
return ret;
else
return UniqueExpression::create(instr, next_value_number_);
}
std::cerr << "Undefined case: " << err << std::endl;
......@@ -459,8 +548,10 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
//
/// \param bb basic block in which the transfer function is called
GVN::partitions
GVN::transferFunction(Instruction *x, Value *e, partitions pin) {
partitions pout = pin;
GVN::transferFunction(Instruction *instr, Value *e, partitions pin) {
next_value_number_ = start_idx_[std::make_pair(instr, e)];
partitions pout = clone(pin);
// TODO: deal with copy-stmt case
// ?? deal with copy statement
auto e_instr = dynamic_cast<Instruction *>(e);
......@@ -469,10 +560,13 @@ GVN::transferFunction(Instruction *x, Value *e, partitions pin) {
"A value must be from an instruction or constant");
// erase the old record for x
std::set<Value *>::iterator it;
for (auto c : pin)
if ((it = std::find(c->members_.begin(), c->members_.end(), x)) !=
for (auto c : pout)
if ((it = std::find(c->members_.begin(), c->members_.end(), instr)) !=
c->members_.end()) {
c->members_.erase(it);
if (c->members_.empty())
pout.erase(c);
break;
}
// TODO: get different ValueExpr by Instruction::OpID, modify pout
......@@ -483,25 +577,29 @@ 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, pout);
} else
ve = valueExpr(x, pin);
auto vpf = valuePhiFunc(ve, curr_bb);
ve = valueExpr(instr, pout);
auto vpf = valuePhiFunc(ve, curr_bb, instr);
// TODO: set leader
for (auto c : pout) {
if (ve == c->value_expr_ or
(vpf and c->value_phi_ and *vpf == *c->value_phi_)) {
c->value_expr_ = ve;
c->members_.insert(x);
// c->value_expr_ = ve;
c->members_.insert(instr);
return pout;
}
}
auto c = createCongruenceClass(new_number());
c->members_.insert(x);
c->leader_ = x;
c->members_.insert(instr);
c->value_expr_ = ve;
c->value_phi_ = vpf;
if (c->value_expr_->get_expr_type() == Expression::e_constant)
c->leader_ =
static_cast<ConstantExpression *>(c->value_expr_.get())->get_val();
else
c->leader_ = instr;
pout.insert(c);
return pout;
}
......@@ -520,8 +618,6 @@ 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()) {
......@@ -539,39 +635,88 @@ GVN::transferFunction(BasicBlock *bb) {
}
}
}
/* LOG_INFO << "pout after:\n";
* utils::print_partitions(part);
* std::cout << std::endl; */
std::cout << "-------\n"
<< "for basic block " << bb->get_name() << ", pout:" << std::endl;
utils::print_partitions(part);
return part;
}
// NOTE: only instruction op matter
shared_ptr<PhiExpression>
GVN::valuePhiFunc(shared_ptr<Expression> ve, BasicBlock *bb) {
GVN::valuePhiFunc(shared_ptr<Expression> ve,
BasicBlock *bb,
Instruction *instr) {
// TODO
// get 2 predecessors
auto pre_bbs_ = bb->get_pre_basic_blocks();
if (pre_bbs_.size() == 1)
return nullptr;
auto pre_1 = *pre_bbs_.begin();
auto pre_2 = *(++pre_bbs_.begin());
// check expression form
if (ve->get_expr_type() != Expression::e_bin)
return nullptr;
auto ve_bin = static_cast<BinaryExpression *>(ve.get());
if (ve_bin->lhs_->get_expr_type() != Expression::e_phi or
if (ve_bin->lhs_->get_expr_type() != Expression::e_phi and
ve_bin->rhs_->get_expr_type() != Expression::e_phi)
return nullptr;
shared_ptr<Expression> vi{}, vj{};
shared_ptr<BinaryExpression> vl_merge{}, vr_merge{};
shared_ptr<Expression> vl_merge_E{}, vr_merge_E{};
// get 2 phi expressions
auto lhs = static_cast<PhiExpression *>(ve_bin->lhs_.get());
auto rhs = static_cast<PhiExpression *>(ve_bin->rhs_.get());
// get 2 predecessors
auto pre_bbs_ = bb->get_pre_basic_blocks();
auto pre_1 = *pre_bbs_.begin();
auto pre_2 = *(++pre_bbs_.begin());
auto lhs_phi = dynamic_cast<PhiExpression *>(ve_bin->lhs_.get());
auto rhs_phi = dynamic_cast<PhiExpression *>(ve_bin->rhs_.get());
// set vl_merge and vr_merge
if (ve_bin->lhs_->get_expr_type() == Expression::e_phi and
ve_bin->rhs_->get_expr_type() == Expression::e_phi) {
// try to get the merged value expression
vl_merge =
BinaryExpression::create(ve_bin->op_, lhs_phi->lhs_, rhs_phi->lhs_);
vr_merge =
BinaryExpression::create(ve_bin->op_, lhs_phi->rhs_, rhs_phi->rhs_);
} else if (ve_bin->lhs_->get_expr_type() == Expression::e_phi) {
vl_merge =
BinaryExpression::create(ve_bin->op_, lhs_phi->lhs_, ve_bin->rhs_);
vr_merge =
BinaryExpression::create(ve_bin->op_, lhs_phi->rhs_, ve_bin->rhs_);
} else {
vl_merge =
BinaryExpression::create(ve_bin->op_, ve_bin->lhs_, rhs_phi->lhs_);
vr_merge =
BinaryExpression::create(ve_bin->op_, ve_bin->lhs_, rhs_phi->rhs_);
}
// constant fold
if (vl_merge->lhs_->get_expr_type() == Expression::e_constant and
vl_merge->rhs_->get_expr_type() == Expression::e_constant) {
auto vl_merge_l =
dynamic_cast<ConstantExpression *>(vl_merge->lhs_.get());
auto vl_merge_r =
dynamic_cast<ConstantExpression *>(vl_merge->rhs_.get());
vl_merge_E = ConstantExpression::create(folder_->compute(
instr, vl_merge_l->get_val(), vl_merge_r->get_val()));
} else
vl_merge_E = vl_merge;
if (vr_merge->lhs_->get_expr_type() == Expression::e_constant and
vr_merge->rhs_->get_expr_type() == Expression::e_constant) {
auto vr_merge_l =
dynamic_cast<ConstantExpression *>(vr_merge->lhs_.get());
auto vr_merge_r =
dynamic_cast<ConstantExpression *>(vr_merge->rhs_.get());
vr_merge_E = ConstantExpression::create(folder_->compute(
instr, vr_merge_l->get_val(), vr_merge_r->get_val()));
} else
vr_merge_E = vr_merge;
// try to get the merged value expression
auto vl_merge = BinaryExpression::create(ve_bin->op_, lhs->lhs_, rhs->lhs_);
auto vr_merge = BinaryExpression::create(ve_bin->op_, lhs->rhs_, rhs->rhs_);
auto vi = getVN(pout_[pre_1], vl_merge);
auto vj = getVN(pout_[pre_2], vr_merge);
vi = getVN(pout_[pre_1], vl_merge_E);
vj = getVN(pout_[pre_2], vr_merge_E);
if (vi == nullptr)
vi = valuePhiFunc(vl_merge, pre_1);
vi = valuePhiFunc(vl_merge_E, pre_1, instr);
if (vj == nullptr)
vj = valuePhiFunc(vr_merge, pre_2);
vj = valuePhiFunc(vr_merge_E, pre_2, instr);
if (vi and vj)
return PhiExpression::create(vi, vj);
......@@ -688,6 +833,19 @@ GVN::run() {
gvn_json << "]";
}
void
GVN::dump_tmp(Function &f) {
std::string gvn_json;
if (dump_json_) {
gvn_json += "{\n\"function\": ";
gvn_json += "\"" + f.get_name() + "\", ";
gvn_json += "\n\"pout\": " + utils::dump_bb2partition(pout_);
gvn_json += "},";
}
gvn_json += "]";
std::cout << gvn_json << std::endl;
}
template <typename T>
static bool
equiv_as(const Expression &lhs, const Expression &rhs) {
......@@ -729,6 +887,7 @@ GVN::partitions
GVN::clone(const partitions &p) {
partitions data;
for (auto &cc : p) {
assert(not cc->members_.empty());
data.insert(std::make_shared<CongruenceClass>(*cc));
}
return data;
......
rm -rf *.ll
rm -rf gvn.json
rm -rf `ls | grep -v "\."`
rm -rf tmp*
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