nv50/ir: make Instruction::src/def container private
[mesa.git] / src / gallium / drivers / nv50 / codegen / nv50_ir_inlines.h
1 /*
2 * Copyright 2011 Christoph Bumiller
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #ifndef __NV50_IR_INLINES_H__
24 #define __NV50_IR_INLINES_H__
25
26 static inline CondCode reverseCondCode(CondCode cc)
27 {
28 static const uint8_t ccRev[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
29
30 return static_cast<CondCode>(ccRev[cc & 7] | (cc & ~7));
31 }
32
33 static inline CondCode inverseCondCode(CondCode cc)
34 {
35 return static_cast<CondCode>(cc ^ 7);
36 }
37
38 static inline bool isMemoryFile(DataFile f)
39 {
40 return (f >= FILE_MEMORY_CONST && f <= FILE_MEMORY_LOCAL);
41 }
42
43 static inline bool isTextureOp(operation op)
44 {
45 return (op >= OP_TEX && op <= OP_TEXCSAA);
46 }
47
48 static inline unsigned int typeSizeof(DataType ty)
49 {
50 switch (ty) {
51 case TYPE_U8:
52 case TYPE_S8:
53 return 1;
54 case TYPE_F16:
55 case TYPE_U16:
56 case TYPE_S16:
57 return 2;
58 case TYPE_F32:
59 case TYPE_U32:
60 case TYPE_S32:
61 return 4;
62 case TYPE_F64:
63 case TYPE_U64:
64 case TYPE_S64:
65 return 8;
66 case TYPE_B96:
67 return 12;
68 case TYPE_B128:
69 return 16;
70 default:
71 return 0;
72 }
73 }
74
75 static inline DataType typeOfSize(unsigned int size,
76 bool flt = false, bool sgn = false)
77 {
78 switch (size) {
79 case 1: return sgn ? TYPE_S8 : TYPE_U8;
80 case 2: return flt ? TYPE_F16 : (sgn ? TYPE_S16 : TYPE_U16);
81 case 8: return flt ? TYPE_F64 : (sgn ? TYPE_S64 : TYPE_U64);
82 case 12: return TYPE_B96;
83 case 16: return TYPE_B128;
84 case 4:
85 return flt ? TYPE_F32 : (sgn ? TYPE_S32 : TYPE_U32);
86 default:
87 return TYPE_NONE;
88 }
89 }
90
91 static inline bool isFloatType(DataType ty)
92 {
93 return (ty >= TYPE_F16 && ty <= TYPE_F64);
94 }
95
96 static inline bool isSignedIntType(DataType ty)
97 {
98 return (ty == TYPE_S8 || ty == TYPE_S16 || ty == TYPE_S32);
99 }
100
101 static inline bool isSignedType(DataType ty)
102 {
103 switch (ty) {
104 case TYPE_NONE:
105 case TYPE_U8:
106 case TYPE_U16:
107 case TYPE_U32:
108 case TYPE_B96:
109 case TYPE_B128:
110 return false;
111 default:
112 return true;
113 }
114 }
115
116 const ValueRef *ValueRef::getIndirect(int dim) const
117 {
118 return isIndirect(dim) ? &insn->src(indirect[dim]) : NULL;
119 }
120
121 DataFile ValueRef::getFile() const
122 {
123 return value ? value->reg.file : FILE_NULL;
124 }
125
126 unsigned int ValueRef::getSize() const
127 {
128 return value ? value->reg.size : 0;
129 }
130
131 Value *ValueRef::rep() const
132 {
133 assert(value);
134 return value->join;
135 }
136
137 Value *ValueDef::rep() const
138 {
139 assert(value);
140 return value->join;
141 }
142
143 DataFile ValueDef::getFile() const
144 {
145 return value ? value->reg.file : FILE_NULL;
146 }
147
148 unsigned int ValueDef::getSize() const
149 {
150 return value ? value->reg.size : 0;
151 }
152
153 void ValueDef::setSSA(LValue *lval)
154 {
155 origin = value->asLValue();
156 set(lval);
157 }
158
159 const LValue *ValueDef::preSSA() const
160 {
161 return origin;
162 }
163
164 Instruction *Value::getInsn() const
165 {
166 return defs.empty() ? NULL : defs.front()->getInsn();
167 }
168
169 Instruction *Value::getUniqueInsn() const
170 {
171 if (defs.empty())
172 return NULL;
173
174 // after regalloc, the definitions of coalesced values are linked
175 if (join != this) {
176 for (DefCIterator it = defs.begin(); it != defs.end(); ++it)
177 if ((*it)->get() == this)
178 return (*it)->getInsn();
179 // should be unreachable and trigger assertion at the end
180 }
181 #ifdef DEBUG
182 if (reg.data.id < 0) {
183 int n = 0;
184 for (DefCIterator it = defs.begin(); n < 2 && it != defs.end(); ++it)
185 if ((*it)->get() == this) // don't count joined values
186 ++n;
187 if (n > 1)
188 WARN("value %%%i not uniquely defined\n", id); // return NULL ?
189 }
190 #endif
191 assert(defs.front()->get() == this);
192 return defs.front()->getInsn();
193 }
194
195 Value *Instruction::getIndirect(int s, int dim) const
196 {
197 return srcs[s].isIndirect(dim) ? getSrc(srcs[s].indirect[dim]) : NULL;
198 }
199
200 Value *Instruction::getPredicate() const
201 {
202 return (predSrc >= 0) ? getSrc(predSrc) : NULL;
203 }
204
205 void Instruction::setFlagsDef(int d, Value *val)
206 {
207 if (val) {
208 if (flagsDef < 0)
209 flagsDef = d;
210 setDef(flagsDef, val);
211 } else {
212 if (flagsDef >= 0) {
213 setDef(flagsDef, NULL);
214 flagsDef = -1;
215 }
216 }
217 }
218
219 void Instruction::setFlagsSrc(int s, Value *val)
220 {
221 flagsSrc = s;
222 setSrc(flagsSrc, val);
223 }
224
225 Value *TexInstruction::getIndirectR() const
226 {
227 return tex.rIndirectSrc >= 0 ? getSrc(tex.rIndirectSrc) : NULL;
228 }
229
230 Value *TexInstruction::getIndirectS() const
231 {
232 return tex.rIndirectSrc >= 0 ? getSrc(tex.rIndirectSrc) : NULL;
233 }
234
235 CmpInstruction *Instruction::asCmp()
236 {
237 if (op >= OP_SET_AND && op <= OP_SLCT && op != OP_SELP)
238 return static_cast<CmpInstruction *>(this);
239 return NULL;
240 }
241
242 const CmpInstruction *Instruction::asCmp() const
243 {
244 if (op >= OP_SET_AND && op <= OP_SLCT && op != OP_SELP)
245 return static_cast<const CmpInstruction *>(this);
246 return NULL;
247 }
248
249 FlowInstruction *Instruction::asFlow()
250 {
251 if (op >= OP_BRA && op <= OP_JOIN)
252 return static_cast<FlowInstruction *>(this);
253 return NULL;
254 }
255
256 const FlowInstruction *Instruction::asFlow() const
257 {
258 if (op >= OP_BRA && op <= OP_JOINAT)
259 return static_cast<const FlowInstruction *>(this);
260 return NULL;
261 }
262
263 TexInstruction *Instruction::asTex()
264 {
265 if (op >= OP_TEX && op <= OP_TEXCSAA)
266 return static_cast<TexInstruction *>(this);
267 return NULL;
268 }
269
270 const TexInstruction *Instruction::asTex() const
271 {
272 if (op >= OP_TEX && op <= OP_TEXCSAA)
273 return static_cast<const TexInstruction *>(this);
274 return NULL;
275 }
276
277 // XXX: use a virtual function so we're really really safe ?
278 LValue *Value::asLValue()
279 {
280 if (reg.file >= FILE_GPR && reg.file <= FILE_ADDRESS)
281 return static_cast<LValue *>(this);
282 return NULL;
283 }
284
285 Symbol *Value::asSym()
286 {
287 if (reg.file >= FILE_MEMORY_CONST)
288 return static_cast<Symbol *>(this);
289 return NULL;
290 }
291
292 const Symbol *Value::asSym() const
293 {
294 if (reg.file >= FILE_MEMORY_CONST)
295 return static_cast<const Symbol *>(this);
296 return NULL;
297 }
298
299 void Symbol::setOffset(int32_t offset)
300 {
301 reg.data.offset = offset;
302 }
303
304 void Symbol::setAddress(Symbol *base, int32_t offset)
305 {
306 baseSym = base;
307 reg.data.offset = offset;
308 }
309
310 void Symbol::setSV(SVSemantic sv, uint32_t index)
311 {
312 reg.data.sv.sv = sv;
313 reg.data.sv.index = index;
314 }
315
316 ImmediateValue *Value::asImm()
317 {
318 if (reg.file == FILE_IMMEDIATE)
319 return static_cast<ImmediateValue *>(this);
320 return NULL;
321 }
322
323 const ImmediateValue *Value::asImm() const
324 {
325 if (reg.file == FILE_IMMEDIATE)
326 return static_cast<const ImmediateValue *>(this);
327 return NULL;
328 }
329
330 Value *Value::get(Iterator &it)
331 {
332 return reinterpret_cast<Value *>(it.get());
333 }
334
335 bool BasicBlock::reachableBy(BasicBlock *by, BasicBlock *term)
336 {
337 return cfg.reachableBy(&by->cfg, &term->cfg);
338 }
339
340 BasicBlock *BasicBlock::get(Iterator &iter)
341 {
342 return reinterpret_cast<BasicBlock *>(iter.get());
343 }
344
345 BasicBlock *BasicBlock::get(Graph::Node *node)
346 {
347 assert(node);
348 return reinterpret_cast<BasicBlock *>(node->data);
349 }
350
351 LValue *Function::getLValue(int id)
352 {
353 assert((unsigned int)id < (unsigned int)allLValues.getSize());
354 return reinterpret_cast<LValue *>(allLValues.get(id));
355 }
356
357 #endif // __NV50_IR_INLINES_H__