/* -*- mesa-c++ -*- * * Copyright (c) 2018 Collabora LTD * * Author: Gert Wollny * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * on the rights to use, copy, modify, merge, publish, distribute, sub * license, and/or sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include "sfn_instruction_base.h" #include "sfn_liverange.h" #include "sfn_valuepool.h" namespace r600 { ValueRemapper::ValueRemapper(std::vector& m, ValueMap& values): m_map(m), m_values(values) { } void ValueRemapper::remap(PValue& v) { if (!v) return; if (v->type() == Value::gpr) { v = remap_one_registers(v); } else if (v->type() == Value::gpr_array_value) { GPRArrayValue& val = static_cast(*v); auto value = val.value(); auto addr = val.indirect(); val.reset_value(remap_one_registers(value)); if (addr) { if (addr->type() == Value::gpr) val.reset_addr(remap_one_registers(addr)); } size_t range_start = val.sel(); size_t range_end = range_start + val.array_size(); while (range_start < range_end) m_map[range_start++].used = true; } else if (v->type() == Value::kconst) { auto& val = static_cast(*v); auto addr = val.addr(); if (addr && addr->type() == Value::gpr) val.reset_addr(remap_one_registers(addr)); } } void ValueRemapper::remap(GPRVector& v) { for (int i = 0; i < 4; ++i) { if (v.reg_i(i)) { auto& ns_idx = m_map[v.reg_i(i)->sel()]; if (ns_idx.valid) v.set_reg_i(i,m_values.get_or_inject(ns_idx.new_reg, v.reg_i(i)->chan())); m_map[v.reg_i(i)->sel()].used = true; } } } PValue ValueRemapper::remap_one_registers(PValue& reg) { auto new_index = m_map[reg->sel()]; if (new_index.valid) reg = m_values.get_or_inject(new_index.new_reg, reg->chan()); m_map[reg->sel()].used = true; return reg; } Instruction::Instruction(instr_type t): m_type(t) { } Instruction::~Instruction() { } void Instruction::print(std::ostream& os) const { os << "OP:"; do_print(os); } void Instruction::remap_registers(ValueRemapper& map) { sfn_log << SfnLog::merge << "REMAP " << *this << "\n"; for (auto& v: m_mappable_src_registers) map.remap(*v); for (auto& v: m_mappable_src_vectors) map.remap(*v); for (auto& v: m_mappable_dst_registers) map.remap(*v); for (auto& v: m_mappable_dst_vectors) map.remap(*v); sfn_log << SfnLog::merge << "TO " << *this << "\n\n"; } void Instruction::add_remappable_src_value(PValue *v) { if (*v) m_mappable_src_registers.push_back(v); } void Instruction::add_remappable_src_value(GPRVector *v) { m_mappable_src_vectors.push_back(v); } void Instruction::add_remappable_dst_value(PValue *v) { if (v) m_mappable_dst_registers.push_back(v); } void Instruction::add_remappable_dst_value(GPRVector *v) { m_mappable_dst_vectors.push_back(v); } void Instruction::replace_values(UNUSED const ValueSet& candidates, UNUSED PValue new_value) { } void Instruction::evalue_liveness(LiverangeEvaluator& eval) const { sfn_log << SfnLog::merge << "Scan " << *this << "\n"; for (const auto& s: m_mappable_src_registers) if (*s) eval.record_read(**s); for (const auto& s: m_mappable_src_vectors) eval.record_read(*s); for (const auto& s: m_mappable_dst_registers) if (*s) eval.record_write(**s); for (const auto& s: m_mappable_dst_vectors) eval.record_write(*s); do_evalue_liveness(eval); } void Instruction::do_evalue_liveness(UNUSED LiverangeEvaluator& eval) const { } bool operator == (const Instruction& lhs, const Instruction& rhs) { if (rhs.m_type != lhs.m_type) return false; return lhs.is_equal_to(rhs); } }