[ast] laying down the ground work for on-the-fly phi-node simplification

This commit is contained in:
Philippe Tillet
2019-01-06 15:16:02 -05:00
parent 6bfceae4a6
commit 179890c7ad
8 changed files with 60 additions and 14 deletions

View File

@@ -23,7 +23,7 @@ void test(fp32 *A, fp32 *B, fp32 *C, int32 i){\
int32 j = 1;\
int32 k;\
i = i + j;\
for(k = 0; k < 10; k = k+1){\
for(k = 0; k < 10; k = k+5){\
int32 u = 1;\
u = u + i;\
if(k == 0)\

View File

@@ -187,7 +187,9 @@ void lowering(ir::module &src, Module &dst){
for(unsigned i = 0; i < phi->get_num_incoming(); i++){
ir::value *inc_val = phi->get_incoming_value(i);
ir::basic_block *inc_block = phi->get_incoming_block(i);
dst_phi->addIncoming(vmap[inc_val], bmap[inc_block]);
Value *llvm_inc_val = llvm_value(inc_val, dst_ctx, vmap, bmap);
BasicBlock *llvm_block = bmap[inc_block];
dst_phi->addIncoming(llvm_inc_val, llvm_block);
}
}
}

View File

@@ -30,6 +30,7 @@ public:
private:
phi_node *make_phi(type *ty, unsigned num_values, basic_block *block);
value *try_remove_trivial_phis(ir::phi_node *&phi);
value *add_phi_operands(const std::string& name, phi_node *&phi);
value *get_value_recursive(const std::string& name, basic_block *block);
void push_function(function *fn) { functions_.push_back(fn); }

View File

@@ -10,6 +10,7 @@ namespace ir{
class type;
class use;
class user;
//===----------------------------------------------------------------------===//
// value class
@@ -21,7 +22,9 @@ public:
value(type *ty, const std::string &name = "");
virtual ~value(){ }
// uses
void add_use(use *arg);
void add_use(use arg);
const std::vector<use> &get_uses() { return uses_; }
virtual void replace_all_uses_with(value *target);
// name
void set_name(const std::string &name);
const std::string &get_name() const { return name_; }
@@ -30,6 +33,9 @@ public:
private:
type *ty_;
std::string name_;
protected:
std::vector<use> uses_;
};
//===----------------------------------------------------------------------===//
@@ -78,6 +84,9 @@ public:
value *get_operand(unsigned i);
unsigned get_num_operands() const ;
// Utils
void replace_all_uses_with(value *target);
private:
std::vector<use> ops_;
};

View File

@@ -105,7 +105,6 @@ ir::value* function_definition::codegen(ir::module *mod) const{
mod->seal_block(entry);
mod->get_builder().set_insert_point(entry);
body_->codegen(mod);
std::cout << mod->get_builder().get_insert_block()->get_name() << std::endl;
mod->get_builder().create_ret_void();
return nullptr;
}

View File

@@ -26,7 +26,9 @@ instruction::instruction(type *ty, unsigned num_ops, const std::string &name, in
//===----------------------------------------------------------------------===//
phi_node::phi_node(type *ty, unsigned num_reserved, std::string const &name, instruction *next)
: instruction(ty, num_reserved, name, next), blocks_(num_reserved){ }
: instruction(ty, 0, name, next) {
blocks_.reserve(num_reserved);
}
// Set incoming value
void phi_node::set_incoming_value(unsigned i, value *v){
@@ -44,11 +46,8 @@ void phi_node::set_incoming_block(unsigned i, basic_block *block){
// Add incoming
void phi_node::add_incoming(value *v, basic_block *block){
if(get_num_operands()==num_reserved_){
num_reserved_++;
resize_ops(num_reserved_);
blocks_.resize(num_reserved_);
}
resize_ops(get_num_operands() + 1);
blocks_.resize(get_num_operands() + 1);
set_incoming_value(get_num_operands() - 1, v);
set_incoming_block(get_num_operands() - 1, block);
}

View File

@@ -39,13 +39,34 @@ ir::phi_node* module::make_phi(ir::type *ty, unsigned num_values, ir::basic_bloc
return res;
}
ir::value *module::try_remove_trivial_phis(ir::phi_node *&phi){
ir::value *same = nullptr;
for(ir::value *op: phi->ops()){
// unique value or self-reference
if(op == same || op == phi)
continue;
// the phi-node merges at least two values; non-trivial
if(same)
return phi;
same = op;
}
assert(same && "the phi-node is unreachable or in the start block");
std::vector<ir::use> uses = phi->get_uses();
phi->replace_all_uses_with(same);
for(ir::use &u: uses)
if(auto *uphi = dynamic_cast<ir::phi_node*>(u.get()))
if(uphi != phi)
try_remove_trivial_phis(uphi);
return same;
}
ir::value *module::add_phi_operands(const std::string& name, ir::phi_node *&phi){
ir::basic_block *block = phi->get_parent();
for(ir::basic_block *pred: block->get_predecessors()){
ir::value *value = get_value(name, pred);
phi->add_incoming(value, pred);
}
return phi;
return try_remove_trivial_phis(phi);
}
ir::value *module::get_value_recursive(const std::string& name, ir::basic_block *block) {

View File

@@ -14,17 +14,26 @@ value::value(type *ty, const std::string &name): ty_(ty){
set_name(name);
}
void value::add_use(use arg) {
uses_.push_back(arg);
}
// TODO: automatic naming scheme + update symbol table
void value::set_name(const std::string &name){
name_ = name;
}
void value::replace_all_uses_with(value *target){
throw std::runtime_error("not implemented");
}
//===----------------------------------------------------------------------===//
// use class
//===----------------------------------------------------------------------===//
void use::set(value *val){
val_ = val;
val_->add_use(*this);
}
value *use::operator=(value *rhs){
@@ -40,19 +49,25 @@ const use &use::operator=(const use &rhs){
//===----------------------------------------------------------------------===//
// user class
//===----------------------------------------------------------------------===//
void user::set_operand(unsigned i, value *x){
void user::set_operand(unsigned i, value *x) {
assert(i < ops_.size() && "set_operand() out of range!");
ops_[i] = x;
}
value* user::get_operand(unsigned i){
value* user::get_operand(unsigned i) {
assert(i < ops_.size() && "get_operand() out of range!");
return ops_[i];
}
unsigned user::get_num_operands() const{
unsigned user::get_num_operands() const {
return ops_.size();
}
void user::replace_all_uses_with(value *target) {
for(use &u: uses_){
u.set(target);
}
}
}
}