nir/opt_vectorize: Add a callback for filtering of vectorizing.
[mesa.git] / src / gallium / drivers / r600 / sfn / sfn_instruction_alu.cpp
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
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
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
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
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
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
93 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
115 void AluInstruction::replace_values(const ValueSet& candiates, PValue new_value)
116 {
117 for (auto c: candiates) {
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
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
139 void AluInstruction::set_flag(AluModifiers flag)
140 {
141 m_flags.set(flag);
142 }
143
144 void AluInstruction::set_bank_swizzle(AluBankSwizzle bswz)
145 {
146 m_bank_swizzle = bswz;
147 }
148
149 unsigned AluInstruction::n_sources() const
150 {
151 return m_src.size();
152 }
153
154 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 }