<commit_before>//=======================================================================
// Copyright <NAME> 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "assert.hpp"
#include "Variable.hpp"
#include "Type.hpp"
#include "VisitorUtils.hpp"
#include "FunctionContext.hpp"

#include "mtac/OffsetConstantPropagationProblem.hpp"
#include "mtac/GlobalOptimizations.hpp"
#include "mtac/LiveVariableAnalysisProblem.hpp"

using namespace eddic;

typedef mtac::OffsetConstantPropagationProblem::ProblemDomain ProblemDomain;

ProblemDomain mtac::OffsetConstantPropagationProblem::Boundary(std::shared_ptr<mtac::Function> function){
    pointer_escaped = mtac::escape_analysis(function);

    ProblemDomain::Values values;
    ProblemDomain out(values);
    
    for(auto& variable_pair : function->context->stored_variables()){
        auto variable = variable_pair.second; 

        if(variable->type()->is_array()){
            auto array_size = variable->type()->elements()* variable->type()->data_type()->size() + INT->size();

            if(variable->type()->data_type() == FLOAT){
                for(std::size_t i = INT->size(); i < array_size; i += INT->size()){
                    mtac::Offset offset(variable, i);
                    out[offset] = 0.0;
                }
            } else {
                for(std::size_t i = INT->size(); i < array_size; i += INT->size()){
                    mtac::Offset offset(variable, i);
                    out[offset] = 0;
                }
            }
        } else if(variable->type()->is_custom_type() || variable->type()->is_template()){
            auto struct_size = variable->type()->size();

            for(std::size_t i = 0; i < struct_size; i += INT->size()){
                mtac::Offset offset(variable, i);
                out[offset] = 0;
            }
        }
    }

    return out;
}

ProblemDomain mtac::OffsetConstantPropagationProblem::meet(ProblemDomain& in, ProblemDomain& out){
    auto result = mtac::intersection_meet(in, out);

    //Remove all the temporary
    for(auto it = std::begin(result.values()); it != std::end(result.values());){
        if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&it->second)){
            auto variable = *ptr;

            if (variable->position().isTemporary()){
                it = result.values().erase(it);
            } else {
                ++it;
            }
        } else {
            ++it;
        }
    }

    return result;
}

namespace {

struct ConstantCollector : public boost::static_visitor<> {
    ProblemDomain& out;
    const mtac::Offset& offset;

    ConstantCollector(ProblemDomain& out, const mtac::Offset& offset) : out(out), offset(offset) {}

    void operator()(int value){
        out[offset] = value;
    }
    
    void operator()(const std::string& value){
        out[offset] = value;
    }
    
    void operator()(double value){
        out[offset] = value;
    }
    
    void operator()(std::shared_ptr<Variable> variable){
        out[offset] = variable;
    }

    template<typename T>
    void operator()(T&){
        out.erase(offset);
    }
};

} //end of anonymous namespace

ProblemDomain mtac::OffsetConstantPropagationProblem::transfer(std::shared_ptr<mtac::BasicBlock> /*basic_block*/, mtac::Statement& statement, ProblemDomain& in){
    auto out = in;

    if(boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
        auto quadruple = boost::get<std::shared_ptr<mtac::Quadruple>>(statement);

        //Store the value assigned to result+arg1
        if(quadruple->op == mtac::Operator::DOT_ASSIGN){
            if(auto* ptr = boost::get<int>(&*quadruple->arg1)){
                if(!quadruple->result->type()->is_pointer()){
                    mtac::Offset offset(quadruple->result, *ptr);
                    ConstantCollector collector(out, offset);

                    visit(collector, *quadruple->arg2);
                }
            }
        } 
        //PDOT Lets escape an offset
        else if(quadruple->op == mtac::Operator::PDOT){
            if(auto* ptr = boost::get<int>(&*quadruple->arg2)){<commit_msg>Fix support of float constant<commit_after>//=======================================================================
// Copyright <NAME> 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "assert.hpp"
#include "Variable.hpp"
#include "Type.hpp"
#include "VisitorUtils.hpp"
#include "FunctionContext.hpp"

#include "mtac/OffsetConstantPropagationProblem.hpp"
#include "mtac/GlobalOptimizations.hpp"
#include "mtac/LiveVariableAnalysisProblem.hpp"

using namespace eddic;

typedef mtac::OffsetConstantPropagationProblem::ProblemDomain ProblemDomain;

ProblemDomain mtac::OffsetConstantPropagationProblem::Boundary(std::shared_ptr<mtac::Function> function){
    pointer_escaped = mtac::escape_analysis(function);

    ProblemDomain::Values values;
    ProblemDomain out(values);
    
    for(auto& variable_pair : function->context->stored_variables()){
        auto variable = variable_pair.second; 

        if(variable->type()->is_array()){
            auto array_size = variable->type()->elements()* variable->type()->data_type()->size() + INT->size();

            if(variable->type()->data_type() == FLOAT){
                for(std::size_t i = INT->size(); i < array_size; i += INT->size()){
                    mtac::Offset offset(variable, i);
                    out[offset] = 0.0;
                }
            } else {
                for(std::size_t i = INT->size(); i < array_size; i += INT->size()){
                    mtac::Offset offset(variable, i);
                    out[offset] = 0;
                }
            }
        } else if(variable->type()->is_custom_type() || variable->type()->is_template()){
            auto struct_size = variable->type()->size();

            for(std::size_t i = 0; i < struct_size; i += INT->size()){
                mtac::Offset offset(variable, i);
                out[offset] = 0;
            }
        }
    }

    return out;
}

ProblemDomain mtac::OffsetConstantPropagationProblem::meet(ProblemDomain& in, ProblemDomain& out){
    auto result = mtac::intersection_meet(in, out);

    //Remove all the temporary
    for(auto it = std::begin(result.values()); it != std::end(result.values());){
        if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&it->second)){
            auto variable = *ptr;

            if (variable->position().isTemporary()){
                it = result.values().erase(it);
            } else {
                ++it;
            }
        } else {
            ++it;
        }
    }

    return result;
}

namespace {

struct ConstantCollector : public boost::static_visitor<> {
    ProblemDomain& out;
    const mtac::Offset& offset;

    ConstantCollector(ProblemDomain& out, const mtac::Offset& offset) : out(out), offset(offset) {}

    void operator()(int value){
        out[offset] = value;
    }
    
    void operator()(const std::string& value){
        out[offset] = value;
    }
    
    void operator()(double value){
        out[offset] = value;
    }
    
    void operator()(std::shared_ptr<Variable> variable){
        out[offset] = variable;
    }

    template<typename T>
    void operator()(T&){
        out.erase(offset);
    }
};

} //end of anonymous namespace

ProblemDomain mtac::OffsetConstantPropagationProblem::transfer(std::shared_ptr<mtac::BasicBlock> /*basic_block*/, mtac::Statement& statement, ProblemDomain& in){
    auto out = in;

    if(boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
        auto quadruple = boost::get<std::shared_ptr<mtac::Quadruple>>(statement);

        //Store the value assigned to result+arg1
        if(quadruple->op == mtac::Operator::DOT_ASSIGN || quadruple->op == mtac::Operator::DOT_FASSIGN){
            if(auto* ptr = boost::get<int>(&*quadruple->arg1)){
                if(!quadruple->result->type()->is_pointer()){
                    mtac::Offset offset(quadruple->result, *ptr);
                    
                    ConstantCollector collector(out, offset);
                    visit(collector, *quadruple->arg2);
                }
            }
        } 
        //PDOT Lets escape an offset
        else if(quadruple->op == mtac::Operator::PDOT){
            if(auto* ptr = boost::get<int>(&*quadruple->arg2)){
{'fraction_non_alphanumeric': 0.17794659300184162, 'fraction_numerical': 0.004373848987108656, 'mean_word_length': 2.656986531986532, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 100, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4660638', 'n_tokens_mistral': 2578, 'n_tokens_neox': 2447, 'n_words': 477}