[syntax tree] fixed bugs in control flow lowering

This commit is contained in:
Philippe Tillet
2019-02-17 21:35:03 -05:00
parent cf1a583dbf
commit f3094a512b
8 changed files with 201 additions and 35 deletions

View File

@@ -29,6 +29,14 @@ void module::set_value(const std::string& name, ir::value *value){
return set_value(name, builder_.get_insert_block(), value);
}
void module::set_type(const std::string& name, ir::basic_block *block, ir::type *type){
types_[val_key_t{name, block}] = type;
}
void module::set_type(const std::string& name, ir::type *type){
return set_type(name, builder_.get_insert_block(), type);
}
ir::phi_node* module::make_phi(ir::type *ty, unsigned num_values, ir::basic_block *block){
basic_block::iterator insert = block->get_first_non_phi();
if(insert != block->end()){
@@ -42,14 +50,14 @@ 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){
// 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; });
std::set<ir::value*> non_self_ref;
std::copy_if(phi->ops().begin(), phi->ops().end(), std::inserter(non_self_ref, non_self_ref.begin()),
[phi](ir::value* op){ return op != phi && op; });
// non-trivial
if(non_self_ref.size() > 1)
if(non_self_ref.size() != 1)
return phi;
// unique value or self-reference
ir::value *same = non_self_ref[0];
ir::value *same = *non_self_ref.begin();
std::set<ir::user*> users = phi->get_users();
phi->replace_all_uses_with(same);
phi->erase_from_parent();
@@ -57,9 +65,12 @@ ir::value *module::try_remove_trivial_phis(ir::phi_node *&phi){
if(auto *uphi = dynamic_cast<ir::phi_node*>(u))
if(uphi != phi)
try_remove_trivial_phis(uphi);
if(auto *new_phi = dynamic_cast<ir::phi_node*>(same))
return try_remove_trivial_phis(new_phi);
return same;
}
ir::value *module::add_phi_operands(const std::string& name, ir::phi_node *&phi){
// already initialized
if(phi->get_num_operands())
@@ -75,9 +86,9 @@ ir::value *module::add_phi_operands(const std::string& name, ir::phi_node *&phi)
ir::value *module::get_value_recursive(const std::string& name, ir::basic_block *block) {
ir::value *result;
auto &preds = block->get_predecessors();
if(block)
if(sealed_blocks_.find(block) == sealed_blocks_.end()){
ir::value *pred = get_value(name, preds.front());
incomplete_phis_[block][name] = make_phi(pred->get_type(), 1, block);
incomplete_phis_[block][name] = make_phi(get_type(name, block), 1, block);
result = (ir::value*)incomplete_phis_[block][name];
}
else if(preds.size() <= 1){
@@ -85,8 +96,7 @@ ir::value *module::get_value_recursive(const std::string& name, ir::basic_block
result = get_value(name, has_pred?preds.front():nullptr);
}
else{
ir::value *pred = get_value(name, preds.front());
result = make_phi(pred->get_type(), 1, block);
result = make_phi(get_type(name, block), 1, block);
set_value(name, block, result);
result = add_phi_operands(name, (ir::phi_node*&)result);
}
@@ -112,6 +122,21 @@ ir::value *module::get_value(const std::string& name) {
return get_value(name, builder_.get_insert_block());
}
ir::type *module::get_type(const std::string &name, basic_block *block) {
val_key_t key(name, block);
if(types_.find(key) != types_.end())
return types_.at(key);
assert(block);
const auto& predecessors = block->get_predecessors();
if(predecessors.empty())
return get_type(name, nullptr);
return get_type(name, predecessors[0]);
}
ir::type *module::get_type(const std::string &name) {
return types_.at({name, builder_.get_insert_block()});
}
void module::seal_block(ir::basic_block *block){
for(auto &x: incomplete_phis_[block])
add_phi_operands(x.first, x.second);