#include #include #include "triton/codegen/analysis/liveness.h" #include "triton/codegen/analysis/layout.h" #include "triton/ir/function.h" #include "triton/ir/module.h" #include "triton/ir/utils.h" namespace triton{ namespace codegen{ namespace analysis{ void liveness::run(ir::module &mod) { intervals_.clear(); std::map> layouts_map; for(auto &x: layouts_->get_all()){ shared_layout* layout = x.second->to_shared(); if(!layout || layout->is_tmp()) continue; for(ir::value* v:layout->get_values()){ layouts_map[v].insert(layout); } } std::map> live_in; while(true){ bool changed = false; ir::instruction* last_inst = nullptr; ir::for_each_instruction_backward(mod, [&](ir::instruction* i){ // gen std::set gen; for(ir::value* v: i->ops()) for(shared_layout* layout: layouts_map[v]) gen.insert(layout); // kill std::set kill; for(shared_layout* layout: layouts_map[i]) kill.insert(layout); // temporaries are handled separately if(layouts_->has_tmp(i)){ gen.insert(layouts_->get(layouts_->tmp(i))->to_shared()); kill.insert(layouts_->get(layouts_->tmp(i))->to_shared()); } if(layouts_->has_tmp_index(i)){ gen.insert(layouts_->get(layouts_->tmp_index(i))->to_shared()); kill.insert(layouts_->get(layouts_->tmp_index(i))->to_shared()); } // live-out std::set live_out; std::vector succs = {last_inst}; if(i == i->get_parent()->get_inst_list().back()) for(ir::basic_block* succ: i->get_parent()->get_successors()) succs.push_back(succ->get_inst_list().front()); for(ir::instruction* succ: succs) for(shared_layout* layout: live_in[succ]) if(!layout->is_tmp()) live_out.insert(layout); // new sets std::set live_out_minus_kill; std::set_difference(live_out.begin(), live_out.end(), kill.begin(), kill.end(), std::inserter(live_out_minus_kill, live_out_minus_kill.end())); std::set new_live_in; std::set_union(gen.begin(), gen.end(), live_out_minus_kill.begin(), live_out_minus_kill.end(), std::inserter(new_live_in, new_live_in.end())); changed = changed || (new_live_in != live_in[i]); live_in[i] = new_live_in; last_inst = i; }); if(!changed) break; } // ir::for_each_instruction(mod, [&](ir::instruction* i){ // i->print(std::cout); // std::cout << " live_in: " << live_in[i].size() << std::endl; // }); // Assigns index to each instruction std::map indices; slot_index index = 0; ir::for_each_instruction(mod, [&](ir::instruction* instr){ index += 1; indices.insert({instr, index}); }); for(auto &x: layouts_->get_all()){ shared_layout* layout = x.second->to_shared(); if(layout) intervals_[layout] = segment{INT32_MAX, 0}; } for(auto& x: live_in) for(shared_layout* layout: x.second) intervals_[layout].start = std::min(intervals_[layout].start, indices[x.first]); for(auto& x: live_in) for(shared_layout* layout: x.second){ intervals_[layout].end = std::max(intervals_[layout].end, indices[x.first] + 1); } for(auto &x: layouts_->get_all()) { shared_layout* layout = x.second->to_shared(); if(!layout) continue; // std::cout << intervals_[layout].start << " " << intervals_[layout].end << std::endl; } } } } }