1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2018 Collabora LTD
4  *
5  * Author: Gert Wollny <gert.wollny@collabora.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * on the rights to use, copy, modify, merge, publish, distribute, sub
11  * license, and/or sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26 
27 #include "sfn_instruction_alu.h"
28 #include "sfn_valuepool.h"
29 
30 namespace r600  {
31 
32 const AluModifiers AluInstruction::src_abs_flags[2] =
33    {alu_src0_abs, alu_src1_abs};
34 const AluModifiers AluInstruction::src_neg_flags[3] =
35    {alu_src0_neg, alu_src1_neg, alu_src2_neg};
36 const AluModifiers AluInstruction::src_rel_flags[3] =
37    {alu_src0_rel, alu_src1_rel, alu_src2_rel};
38 
AluInstruction(EAluOp opcode)39 AluInstruction::AluInstruction(EAluOp opcode):
40    Instruction (Instruction::alu),
41    m_opcode(opcode),
42    m_src(alu_ops.at(opcode).nsrc),
43    m_bank_swizzle(alu_vec_unknown),
44    m_cf_type(cf_alu)
45 {
46    if (alu_ops.at(opcode).nsrc == 3)
47       m_flags.set(alu_op3);
48 }
49 
AluInstruction(EAluOp opcode,PValue dest,std::vector<PValue> src,const std::set<AluModifiers> & flags)50 AluInstruction::AluInstruction(EAluOp opcode, PValue dest,
51                                std::vector<PValue> src,
52                                const std::set<AluModifiers>& flags):
53    Instruction (Instruction::alu),
54    m_opcode(opcode),
55    m_dest(dest),
56    m_bank_swizzle(alu_vec_unknown),
57    m_cf_type(cf_alu)
58 {
59    assert(dest);
60    m_src.swap(src);
61    for (auto f : flags)
62       m_flags.set(f);
63 
64    if (alu_ops.at(opcode).nsrc == 3)
65       m_flags.set(alu_op3);
66 
67    for (auto &s: m_src)
68       add_remappable_src_value(&s);
69 
70    add_remappable_dst_value(&m_dest);
71 }
72 
AluInstruction(EAluOp opcode,PValue dest,PValue src0,const std::set<AluModifiers> & flags)73 AluInstruction::AluInstruction(EAluOp opcode, PValue dest, PValue src0,
74                                const std::set<AluModifiers>& flags):
75    AluInstruction(opcode, dest, std::vector<PValue>{src0}, flags)
76 {
77 }
78 
AluInstruction(EAluOp opcode,PValue dest,PValue src0,PValue src1,const std::set<AluModifiers> & m_flags)79 AluInstruction::AluInstruction(EAluOp opcode, PValue dest,
80                                PValue src0, PValue src1,
81                                const std::set<AluModifiers> &m_flags):
82    AluInstruction(opcode, dest, {src0, src1}, m_flags)
83 {
84 }
85 
AluInstruction(EAluOp opcode,PValue dest,PValue src0,PValue src1,PValue src2,const std::set<AluModifiers> & flags)86 AluInstruction::AluInstruction(EAluOp opcode, PValue dest, PValue src0,
87                                PValue src1, PValue src2,
88                                const std::set<AluModifiers> &flags):
89    AluInstruction(opcode, dest, {src0, src1, src2}, flags)
90 {
91 }
92 
is_equal_to(const Instruction & lhs) const93 bool AluInstruction::is_equal_to(const Instruction& lhs) const
94 {
95    assert(lhs.type() == alu);
96    const auto& oth = static_cast<const AluInstruction&>(lhs);
97 
98    if (m_opcode != oth.m_opcode) {
99       return false;
100    }
101 
102    if (*m_dest != *oth.m_dest)
103       return false;
104 
105    if (m_src.size() != oth.m_src.size())
106       return false;
107 
108    for (unsigned i = 0; i < m_src.size(); ++i)
109      if (*m_src[i] != *oth.m_src[i]) {
110         return false;
111      }
112    return (m_flags == oth.m_flags && m_cf_type == oth.m_cf_type);
113 }
114 
replace_values(const ValueSet & candidates,PValue new_value)115 void AluInstruction::replace_values(const ValueSet& candidates, PValue new_value)
116 {
117    for (auto c: candidates) {
118       if (*c == *m_dest)
119          m_dest = new_value;
120 
121       for (auto& s: m_src) {
122          if (*c == *s)
123             s = new_value;
124       }
125    }
126 }
127 
remap_one_registers(PValue reg,std::vector<rename_reg_pair> & map,ValueMap & values)128 PValue AluInstruction::remap_one_registers(PValue reg, std::vector<rename_reg_pair>& map,
129                                            ValueMap &values)
130 {
131    auto new_index = map[reg->sel()];
132    if (new_index.valid)
133       reg = values.get_or_inject(new_index.new_reg, reg->chan());
134    map[reg->sel()].used = true;
135    return reg;
136 }
137 
138 
set_flag(AluModifiers flag)139 void AluInstruction::set_flag(AluModifiers flag)
140 {
141    m_flags.set(flag);
142 }
143 
set_bank_swizzle(AluBankSwizzle bswz)144 void AluInstruction::set_bank_swizzle(AluBankSwizzle bswz)
145 {
146    m_bank_swizzle = bswz;
147 }
148 
n_sources() const149 unsigned AluInstruction::n_sources() const
150 {
151    return m_src.size();
152 }
153 
do_print(std::ostream & os) const154 void AluInstruction::do_print(std::ostream& os) const
155 {
156    os << "ALU " << alu_ops.at(m_opcode).name;
157    if (m_flags.test(alu_dst_clamp))
158       os << "_CLAMP";
159    if (m_dest)
160       os << ' ' << *m_dest << " : "  ;
161 
162    for (unsigned i = 0; i < m_src.size(); ++i) {
163       int pflags = 0;
164       if (i)
165          os << ' ';
166       if (m_flags.test(src_neg_flags[i])) pflags |= Value::PrintFlags::has_neg;
167       if (m_flags.test(src_rel_flags[i])) pflags |= Value::PrintFlags::is_rel;
168       if (i < 2)
169          if (m_flags.test(src_abs_flags[i])) pflags |= Value::PrintFlags::has_abs;
170       m_src[i]->print(os, Value::PrintFlags(0, pflags));
171    }
172    os << " {";
173    os << (m_flags.test(alu_write) ? 'W' : ' ');
174    os << (m_flags.test(alu_last_instr) ? 'L' : ' ');
175    os << (m_flags.test(alu_update_exec) ? 'E' : ' ');
176    os << (m_flags.test(alu_update_pred) ? 'P' : ' ');
177    os << "}";
178 
179    os <<  " BS:" << m_bank_swizzle;
180    os <<  " CF:" << m_cf_type;
181 }
182 
183 }
184