Example #1
0
mtac::basic_block_p mtac::loop::find_safe_preheader(mtac::Function& function, bool create) const {
    auto first_bb = find_entry();

    //Step 1: Try to find if there is already a preheader
    
    auto pred = find_preheader();

    if(pred){
        //It must be the only successor and a fall through edge
        if(pred->successors.size() == 1 && pred->next == first_bb){
            LOG<Trace>("Control-Flow") << "Found " << *pred << " as safe preheader of " << *this << log::endl;

            return pred;
        }
    }

    if(!create){
        return nullptr;
    }

    //Step 2: If not found, create a new preheader

    auto pre_header = function.new_bb();

    //Redispatch all the predecessors

    auto predecessors = first_bb->predecessors;
    for(auto& pred : predecessors){
        if(blocks().find(pred) == blocks().end()){
            mtac::remove_edge(pred, first_bb);
            mtac::make_edge(pred, pre_header);

            auto& quadruple = pred->statements.back();

            if(quadruple.block == first_bb){
                quadruple.block = pre_header;
            }
        }
    }

    function.insert_before(function.at(first_bb), pre_header);

    //Create the fall through edge
    mtac::make_edge(pre_header, first_bb);
                
    LOG<Trace>("Control-Flow") << "Create " << *pre_header << " as safe preheader of " << *this << log::endl;
    
    return pre_header;
}
Example #2
0
void as::IntelX86CodeGenerator::compile(mtac::Function& function){
    writer.stream() << '\n' << function.get_name() << ":" << '\n';

    for(auto& bb : function){
        for(auto& statement : bb->l_statements){
            compile_statement(writer, statement);
        }
    }
}
Example #3
0
bool mtac::loop_unswitching::operator()(mtac::Function& function){
    if(function.loops().empty()){
        return false;
    }

    bool optimized = false;

    for(auto& loop : function.loops()){
        if(loop.single_exit()){
            auto entry = loop.find_entry();
            auto exit = loop.find_exit();

            if(entry && exit && entry->size() == 1){
                if(entry->successors.size() == 2 && exit->predecessors.size() == 2){
                    if(std::is_permutation(entry->successors.begin(), entry->successors.end(), exit->predecessors.begin())){
                        auto& condition = *entry->begin();

                        if(condition.is_if() || condition.is_if_false()){
                            auto usage = mtac::compute_write_usage(loop);

                            if(condition.arg1){
                                if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&*condition.arg1)){
                                    if(usage.written[*ptr] > 0){
                                        continue;
                                    }
                                }
                            }
                            
                            if(condition.arg2){
                                if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&*condition.arg2)){
                                    if(usage.written[*ptr] > 0){
                                        continue;
                                    }
                                }
                            }

                            auto loop_1_entry = entry->successors.front();
                            auto loop_2_entry = entry->successors.back();

                            if(loop_2_entry->next == loop_1_entry){
                                std::swap(loop_1_entry, loop_2_entry);
                            }
                            
                            entry->predecessors.erase(std::remove(entry->predecessors.begin(), entry->predecessors.end(), entry), entry->predecessors.end());

                            auto exit_copy = mtac::clone(function, exit);
                            
                            entry->successors.erase(std::remove(entry->successors.begin(), entry->successors.end(), exit), entry->successors.end());

                            exit->successors.erase(std::remove(exit->successors.begin(), exit->successors.end(), entry), exit->successors.end());
                            exit->successors.push_back(loop_2_entry);
                            
                            exit_copy->successors.erase(std::remove(exit_copy->successors.begin(), exit_copy->successors.end(), entry), exit_copy->successors.end());
                            exit_copy->successors.push_back(loop_1_entry);
                            
                            exit_copy->predecessors.erase(std::remove(exit_copy->predecessors.begin(), exit_copy->predecessors.end(), loop_2_entry), exit_copy->predecessors.end());
                            exit_copy->predecessors.pop_back();

                            mtac::BBClones bb_clones;
                            
                            bb_clones[entry] = loop_1_entry;
                            mtac::replace_bbs(bb_clones, exit_copy);
                            
                            bb_clones[entry] = loop_2_entry;
                            mtac::replace_bbs(bb_clones, exit);

                            loop_1_entry->statements.pop_back();
                            loop_1_entry->predecessors.push_back(exit_copy);

                            auto after_exit = exit->next;

                            mtac::Quadruple goto_(mtac::Operator::GOTO);
                            goto_.block = after_exit;
                            
                            auto new_goto_bb = function.new_bb();
                            new_goto_bb->statements.push_back(std::move(goto_));

                            function.insert_after(function.at(loop_1_entry), exit_copy);
                            function.insert_after(function.at(exit_copy), new_goto_bb);
    
                            mtac::remove_edge(loop_1_entry, exit);
                            mtac::make_edge(loop_1_entry, exit_copy);

                            mtac::remove_edge(exit_copy, after_exit);

                            mtac::make_edge(new_goto_bb, after_exit);
                            
                            mtac::make_edge(exit_copy, new_goto_bb);
                    
                            LOG<Trace>("loops") << "Unswitch loop" << log::endl;
                            function.context->global()->stats().inc_counter("loop_unswitched");

                            optimized = true;
                        }
                    }
                }
            }
        }
    }

    return optimized;
}
Example #4
0
bool mtac::is_recursive(mtac::Function& function){
    for(auto& basic_block : function){
        for(auto& quadruple : basic_block->statements){
            if(quadruple.op == mtac::Operator::CALL && quadruple.function().mangled_name() == function.definition().mangled_name()){
                return true;
            }
        }
    }

    return false;
}
Example #5
0
bool mtac::loop_unrolling::operator()(mtac::Function& function){
    if(function.loops().empty()){
        return false;
    }

    bool optimized = false;

    for(auto& loop : function.loops()){
        if(loop.has_estimate() && loop.blocks().size() == 1){
            auto it = loop.estimate();

            if(it > 100){
                auto bb = *loop.begin();

                //Do not increase too much the size of the body
                if(bb->statements.size() < 20){
                    unsigned int factor = 0;
                    if((it % 8) == 0){
                        factor = 8;
                    } else if((it % 4) == 0){
                        factor = 4;
                    } else if((it % 2) == 0){
                        factor = 2;
                    }

                    if(factor == 0){
                        continue;
                    }

                    LOG<Trace>("loops") << "Unroll the loop with a factor " << factor << log::endl;
                    function.context->global()->stats().inc_counter("loop_unrolled");

                    optimized = true;
                    
                    auto& statements = bb->statements;

                    //The comparison is not necessary here anymore
                    auto comparison = statements.back();
                    statements.pop_back();

                    int limit = statements.size();
                    
                    //There are perhaps new references to functions
                    for(auto& statement : statements){
                        if(statement.op == mtac::Operator::CALL){
                            program.call_graph.edge(function.definition(), statement.function())->count += (factor - 1);
                        }
                    }

                    //Save enough space for the new statements
                    statements.reserve(limit * factor + 1);

                    //Start at 1 because there is already the original body
                    for(unsigned int i = 1; i < factor; ++i){
                        for(int j = 0; j < limit; ++j){
                            statements.push_back(statements[j]); 
                        }
                    }

                    //Put the comparison again at the end
                    statements.push_back(comparison);
                }
            }
        }
    }

    return optimized;
}
Example #6
0
bool mtac::remove_empty_loops::operator()(mtac::Function& function){
    if(function.loops().empty()){
        return false;
    }

    bool optimized = false;
    
    auto lit = iterate(function.loops());

    while(lit.has_next()){
        auto loop = *lit;

        if(loop.has_estimate() && loop.blocks().size() == 1){
            auto it = loop.estimate();
            auto bb = *loop.begin();

            if(bb->size_no_nop() == 2){
                std::shared_ptr<Variable> result;
                for(auto&  statement : bb->statements){
                    if(statement.op != mtac::Operator::NOP){
                       result = statement.result; 
                       break;
                    }
                }

                auto& basic_induction_variables = loop.basic_induction_variables();
                if(basic_induction_variables.find(result) != basic_induction_variables.end()){
                    auto linear_equation = basic_induction_variables.begin()->second;
                    auto initial_value = loop.initial_value();

                    bool loop_removed = false;

                    //The loop does not iterate
                    if(it == 0){
                        bb->statements.clear();
                        loop_removed = true;
                    } else if(it > 0){
                        bb->statements.clear();
                        loop_removed = true;

                        bb->emplace_back(result, static_cast<int>(initial_value + it * linear_equation.d), mtac::Operator::ASSIGN);
                    }

                    if(loop_removed){
                        function.context->global()->stats().inc_counter("empty_loop_removed");

                        //It is not a loop anymore
                        mtac::remove_edge(bb, bb);

                        lit.erase();

                        optimized = true;

                        continue;
                    }
                }
            }
        }

        ++lit;
    }

    return optimized;
}
Example #7
0
void mtac::compute_dominators(mtac::Function& function){
    auto n = function.bb_count();

    dominators dom(n, function);
    dom.compute_dominators();
}