[ast] laying down the ground work for on-the-fly phi-node simplification
This commit is contained in:
@@ -23,7 +23,7 @@ void test(fp32 *A, fp32 *B, fp32 *C, int32 i){\
|
|||||||
int32 j = 1;\
|
int32 j = 1;\
|
||||||
int32 k;\
|
int32 k;\
|
||||||
i = i + j;\
|
i = i + j;\
|
||||||
for(k = 0; k < 10; k = k+1){\
|
for(k = 0; k < 10; k = k+5){\
|
||||||
int32 u = 1;\
|
int32 u = 1;\
|
||||||
u = u + i;\
|
u = u + i;\
|
||||||
if(k == 0)\
|
if(k == 0)\
|
||||||
|
@@ -187,7 +187,9 @@ void lowering(ir::module &src, Module &dst){
|
|||||||
for(unsigned i = 0; i < phi->get_num_incoming(); i++){
|
for(unsigned i = 0; i < phi->get_num_incoming(); i++){
|
||||||
ir::value *inc_val = phi->get_incoming_value(i);
|
ir::value *inc_val = phi->get_incoming_value(i);
|
||||||
ir::basic_block *inc_block = phi->get_incoming_block(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,6 +30,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
phi_node *make_phi(type *ty, unsigned num_values, basic_block *block);
|
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 *add_phi_operands(const std::string& name, phi_node *&phi);
|
||||||
value *get_value_recursive(const std::string& name, basic_block *block);
|
value *get_value_recursive(const std::string& name, basic_block *block);
|
||||||
void push_function(function *fn) { functions_.push_back(fn); }
|
void push_function(function *fn) { functions_.push_back(fn); }
|
||||||
|
@@ -10,6 +10,7 @@ namespace ir{
|
|||||||
|
|
||||||
class type;
|
class type;
|
||||||
class use;
|
class use;
|
||||||
|
class user;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// value class
|
// value class
|
||||||
@@ -21,7 +22,9 @@ public:
|
|||||||
value(type *ty, const std::string &name = "");
|
value(type *ty, const std::string &name = "");
|
||||||
virtual ~value(){ }
|
virtual ~value(){ }
|
||||||
// uses
|
// 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
|
// name
|
||||||
void set_name(const std::string &name);
|
void set_name(const std::string &name);
|
||||||
const std::string &get_name() const { return name_; }
|
const std::string &get_name() const { return name_; }
|
||||||
@@ -30,6 +33,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
type *ty_;
|
type *ty_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<use> uses_;
|
||||||
};
|
};
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@@ -78,6 +84,9 @@ public:
|
|||||||
value *get_operand(unsigned i);
|
value *get_operand(unsigned i);
|
||||||
unsigned get_num_operands() const ;
|
unsigned get_num_operands() const ;
|
||||||
|
|
||||||
|
// Utils
|
||||||
|
void replace_all_uses_with(value *target);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<use> ops_;
|
std::vector<use> ops_;
|
||||||
};
|
};
|
||||||
|
@@ -105,7 +105,6 @@ ir::value* function_definition::codegen(ir::module *mod) const{
|
|||||||
mod->seal_block(entry);
|
mod->seal_block(entry);
|
||||||
mod->get_builder().set_insert_point(entry);
|
mod->get_builder().set_insert_point(entry);
|
||||||
body_->codegen(mod);
|
body_->codegen(mod);
|
||||||
std::cout << mod->get_builder().get_insert_block()->get_name() << std::endl;
|
|
||||||
mod->get_builder().create_ret_void();
|
mod->get_builder().create_ret_void();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
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
|
// Set incoming value
|
||||||
void phi_node::set_incoming_value(unsigned i, value *v){
|
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
|
// Add incoming
|
||||||
void phi_node::add_incoming(value *v, basic_block *block){
|
void phi_node::add_incoming(value *v, basic_block *block){
|
||||||
if(get_num_operands()==num_reserved_){
|
resize_ops(get_num_operands() + 1);
|
||||||
num_reserved_++;
|
blocks_.resize(get_num_operands() + 1);
|
||||||
resize_ops(num_reserved_);
|
|
||||||
blocks_.resize(num_reserved_);
|
|
||||||
}
|
|
||||||
set_incoming_value(get_num_operands() - 1, v);
|
set_incoming_value(get_num_operands() - 1, v);
|
||||||
set_incoming_block(get_num_operands() - 1, block);
|
set_incoming_block(get_num_operands() - 1, block);
|
||||||
}
|
}
|
||||||
|
@@ -39,13 +39,34 @@ ir::phi_node* module::make_phi(ir::type *ty, unsigned num_values, ir::basic_bloc
|
|||||||
return res;
|
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::value *module::add_phi_operands(const std::string& name, ir::phi_node *&phi){
|
||||||
ir::basic_block *block = phi->get_parent();
|
ir::basic_block *block = phi->get_parent();
|
||||||
for(ir::basic_block *pred: block->get_predecessors()){
|
for(ir::basic_block *pred: block->get_predecessors()){
|
||||||
ir::value *value = get_value(name, pred);
|
ir::value *value = get_value(name, pred);
|
||||||
phi->add_incoming(value, 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) {
|
ir::value *module::get_value_recursive(const std::string& name, ir::basic_block *block) {
|
||||||
|
@@ -14,17 +14,26 @@ value::value(type *ty, const std::string &name): ty_(ty){
|
|||||||
set_name(name);
|
set_name(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void value::add_use(use arg) {
|
||||||
|
uses_.push_back(arg);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: automatic naming scheme + update symbol table
|
// TODO: automatic naming scheme + update symbol table
|
||||||
void value::set_name(const std::string &name){
|
void value::set_name(const std::string &name){
|
||||||
name_ = name;
|
name_ = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void value::replace_all_uses_with(value *target){
|
||||||
|
throw std::runtime_error("not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// use class
|
// use class
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
void use::set(value *val){
|
void use::set(value *val){
|
||||||
val_ = val;
|
val_ = val;
|
||||||
|
val_->add_use(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
value *use::operator=(value *rhs){
|
value *use::operator=(value *rhs){
|
||||||
@@ -54,5 +63,11 @@ unsigned user::get_num_operands() const{
|
|||||||
return ops_.size();
|
return ops_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void user::replace_all_uses_with(value *target) {
|
||||||
|
for(use &u: uses_){
|
||||||
|
u.set(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user