[syntax tree] trivial phi-node elimination

This commit is contained in:
Philippe Tillet
2019-01-06 22:43:18 -05:00
parent 0dd4a52ce5
commit ce1c0a62c0
8 changed files with 49 additions and 72 deletions

View File

@@ -139,8 +139,8 @@ Value* llvm_value(ir::value *v, LLVMContext &ctx,
return vmap.at(v);
// create operands
if(auto *uu = dynamic_cast<ir::user*>(v))
for(ir::use u: uu->ops()){
vmap[u.get()] = llvm_value(u, ctx, vmap, bmap);
for(ir::value* u: uu->ops()){
vmap[u] = llvm_value(u, ctx, vmap, bmap);
}
if(auto *cc = dynamic_cast<ir::constant*>(v))
return llvm_constant(cc, ctx);

View File

@@ -36,6 +36,7 @@ public:
// get instruction list
inst_list_t &get_inst_list() { return inst_list_; }
void erase(instruction *i) { inst_list_.remove(i); }
// instruction iterator functions
inline iterator begin() { return inst_list_.begin(); }

View File

@@ -21,11 +21,11 @@ protected:
instruction(type *ty, unsigned num_ops, const std::string &name = "", instruction *next = nullptr);
public:
// parent
void set_parent(basic_block *block) { parent_ = block; }
const basic_block *get_parent() const { return parent_; }
basic_block *get_parent() { return parent_; }
void erase_from_parent();
private:
basic_block *parent_;

View File

@@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include <memory>
#include <set>
namespace tdl{
namespace ir{
@@ -22,8 +23,9 @@ public:
value(type *ty, const std::string &name = "");
virtual ~value(){ }
// uses
void add_use(use arg);
const std::vector<use> &get_uses() { return uses_; }
void add_use(user* arg);
unsigned erase_use(user* arg);
const std::set<user*> &get_users() { return users_; }
virtual void replace_all_uses_with(value *target);
// name
void set_name(const std::string &name);
@@ -35,27 +37,7 @@ private:
std::string name_;
protected:
std::vector<use> uses_;
};
//===----------------------------------------------------------------------===//
// use class
//===----------------------------------------------------------------------===//
class use {
public:
// Implicit conversions to/from value
friend class value;
operator value *() const { return val_; }
value *get() const { return val_; }
value *operator->() { return val_; }
const value *operator->() const { return val_; }
inline void set(value *val);
inline value *operator=(value *rhs);
inline const use &operator=(const use &rhs);
private:
value *val_;
std::set<user*> users_;
};
//===----------------------------------------------------------------------===//
@@ -64,7 +46,7 @@ private:
class user: public value{
public:
typedef std::vector<use> ops_t;
typedef std::vector<value*> ops_t;
typedef ops_t::iterator op_iterator;
typedef ops_t::const_iterator const_op_iterator;
@@ -77,7 +59,7 @@ public:
: value(ty, name), ops_(num_ops){ }
// Operands
const std::vector<use>& ops() { return ops_; }
const ops_t& ops() { return ops_; }
op_iterator op_begin() { return ops_.begin(); }
op_iterator op_end() { return ops_.end(); }
void set_operand(unsigned i, value *x);
@@ -89,7 +71,7 @@ public:
void replace_uses_of_with(value *before, value *after);
private:
std::vector<use> ops_;
ops_t ops_;
};
}

View File

@@ -23,6 +23,8 @@ void basic_block::add_predecessor(basic_block *pred) {
preds_.push_back(pred);
}
basic_block::iterator basic_block::get_first_non_phi(){
auto it = begin();
for(; it != end(); it++)

View File

@@ -21,6 +21,11 @@ instruction::instruction(type *ty, unsigned num_ops, const std::string &name, in
}
}
void instruction::erase_from_parent() {
parent_->erase(this);
}
//===----------------------------------------------------------------------===//
// phi_node classes
//===----------------------------------------------------------------------===//

View File

@@ -40,23 +40,22 @@ ir::phi_node* module::make_phi(ir::type *ty, unsigned num_values, ir::basic_bloc
}
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();
// find non-self references
std::vector<ir::value*> non_self_ref;
std::copy_if(phi->ops().begin(), phi->ops().end(), std::back_inserter(non_self_ref),
[phi](ir::value* op){ return op != phi; });
// non-trivial
if(non_self_ref.size() > 1)
return phi;
// unique value or self-reference
ir::value *same = non_self_ref[0];
std::set<ir::user*> users = phi->get_users();
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);
phi->erase_from_parent();
for(ir::user* u: users)
if(auto *uphi = dynamic_cast<ir::phi_node*>(u))
if(uphi != phi)
try_remove_trivial_phis(uphi);
return same;
}

View File

@@ -1,4 +1,5 @@
#include "ir/value.h"
#include "ir/instructions.h"
#include <iostream>
#include <cassert>
@@ -15,8 +16,12 @@ value::value(type *ty, const std::string &name): ty_(ty){
set_name(name);
}
void value::add_use(use arg) {
uses_.push_back(arg);
void value::add_use(user *arg) {
users_.insert(arg);
}
unsigned value::erase_use(user *arg){
return users_.erase(arg);
}
// TODO: automatic naming scheme + update symbol table
@@ -29,30 +34,13 @@ void value::replace_all_uses_with(value *target){
}
//===----------------------------------------------------------------------===//
// use class
//===----------------------------------------------------------------------===//
void use::set(value *val){
val_ = val;
val_->add_use(*this);
}
value *use::operator=(value *rhs){
set(rhs);
return rhs;
}
const use &use::operator=(const use &rhs){
set(rhs.val_);
return rhs;
}
//===----------------------------------------------------------------------===//
// user class
//===----------------------------------------------------------------------===//
void user::set_operand(unsigned i, value *x) {
assert(i < ops_.size() && "set_operand() out of range!");
ops_[i] = x;
x->add_use(this);
}
value* user::get_operand(unsigned i) {
@@ -65,17 +53,17 @@ unsigned user::get_num_operands() const {
}
void user::replace_all_uses_with(value *target) {
for(use &u: uses_)
if(auto *usr = dynamic_cast<user*>(u.get())){
std::cout << "replacing " << this << " by " << target << " in " << usr << std::endl;
usr->replace_uses_of_with(this, target);
for(auto it = users_.begin(); it != users_.end();){
(*it)->replace_uses_of_with(this, target);
target->add_use(*it);
erase_use(*it++);
}
}
void user::replace_uses_of_with(value *before, value *after) {
for(use &u: ops_)
if(u.get() == before)
u.set(after);
for(size_t i = 0; i < ops_.size(); i++)
if(ops_[i] == before)
ops_[i] = after;
}
}