nv50/ir/tgsi: Replace the inlining logic with proper function calls.
[mesa.git] / src / gallium / drivers / nv50 / codegen / nv50_ir_build_util.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_BUILD_UTIL__
24 #define __NV50_IR_BUILD_UTIL__
25
26 namespace nv50_ir {
27
28 class BuildUtil
29 {
30 public:
31 BuildUtil();
32 BuildUtil(Program *);
33
34 inline void setProgram(Program *);
35 inline Program *getProgram() const { return prog; }
36 inline Function *getFunction() const { return func; }
37
38 // keeps inserting at head/tail of block
39 inline void setPosition(BasicBlock *, bool tail);
40 // position advances only if @after is true
41 inline void setPosition(Instruction *, bool after);
42
43 inline BasicBlock *getBB() { return bb; }
44
45 inline void insert(Instruction *);
46 inline void remove(Instruction *i) { assert(i->bb == bb); bb->remove(i); }
47
48 inline LValue *getScratch(int size = 4, DataFile = FILE_GPR);
49 inline LValue *getSSA(int size = 4); // scratch value for a single assignment
50
51 inline Instruction *mkOp(operation, DataType, Value *);
52 Instruction *mkOp1(operation, DataType, Value *, Value *);
53 Instruction *mkOp2(operation, DataType, Value *, Value *, Value *);
54 Instruction *mkOp3(operation, DataType, Value *, Value *, Value *, Value *);
55
56 LValue *mkOp1v(operation, DataType, Value *, Value *);
57 LValue *mkOp2v(operation, DataType, Value *, Value *, Value *);
58 LValue *mkOp3v(operation, DataType, Value *, Value *, Value *, Value *);
59
60 LValue *mkLoad(DataType, Symbol *, Value *ptr);
61 Instruction *mkStore(operation, DataType, Symbol *, Value *ptr, Value *val);
62
63 Instruction *mkMov(Value *, Value *, DataType = TYPE_U32);
64 Instruction *mkMovToReg(int id, Value *);
65 Instruction *mkMovFromReg(Value *, int id);
66
67 Instruction *mkInterp(unsigned mode, Value *, int32_t offset, Value *rel);
68 Instruction *mkFetch(Value *, DataType, DataFile, int32_t offset,
69 Value *attrRel, Value *primRel);
70
71 Instruction *mkCvt(operation, DataType, Value *, DataType, Value *);
72 CmpInstruction *mkCmp(operation, CondCode, DataType,
73 Value *,
74 Value *, Value *, Value * = NULL);
75 Instruction *mkTex(operation, TexTarget, uint8_t tic, uint8_t tsc,
76 Value **def, Value **src);
77 Instruction *mkQuadop(uint8_t qop, Value *, uint8_t l, Value *, Value *);
78
79 FlowInstruction *mkFlow(operation, void *target, CondCode, Value *pred);
80
81 Instruction *mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc);
82
83 void mkClobber(DataFile file, uint32_t regMask, int regUnitLog2);
84
85 ImmediateValue *mkImm(float);
86 ImmediateValue *mkImm(uint32_t);
87 ImmediateValue *mkImm(uint64_t);
88
89 ImmediateValue *mkImm(int i) { return mkImm((uint32_t)i); }
90
91 Value *loadImm(Value *dst, float);
92 Value *loadImm(Value *dst, uint32_t);
93 Value *loadImm(Value *dst, uint64_t);
94
95 Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
96
97 struct Location
98 {
99 Location(unsigned array, unsigned arrayIdx, unsigned i, unsigned c)
100 : array(array), arrayIdx(arrayIdx), i(i), c(c) { }
101 Location(const Location &l)
102 : array(l.array), arrayIdx(l.arrayIdx), i(l.i), c(l.c) { }
103
104 bool operator==(const Location &l) const
105 {
106 return
107 array == l.array && arrayIdx == l.arrayIdx && i == l.i && c == l.c;
108 }
109
110 bool operator<(const Location &l) const
111 {
112 return array != l.array ? array < l.array :
113 arrayIdx != l.arrayIdx ? arrayIdx < l.arrayIdx :
114 i != l.i ? i < l.i :
115 c != l.c ? c < l.c :
116 false;
117 }
118
119 unsigned array, arrayIdx, i, c;
120 };
121
122 typedef bimap<Location, Value *> ValueMap;
123
124 class DataArray
125 {
126 public:
127 DataArray(BuildUtil *bld) : up(bld) { }
128
129 void setup(unsigned array, unsigned arrayIdx,
130 uint32_t base, int len, int vecDim, int eltSize,
131 DataFile file, int8_t fileIdx);
132
133 inline bool exists(ValueMap&, unsigned int i, unsigned int c);
134
135 Value *load(ValueMap&, int i, int c, Value *ptr);
136 void store(ValueMap&, int i, int c, Value *ptr, Value *value);
137 Value *acquire(ValueMap&, int i, int c);
138
139 private:
140 inline Value *lookup(ValueMap&, unsigned i, unsigned c);
141 inline Value *insert(ValueMap&, unsigned i, unsigned c, Value *v);
142
143 Symbol *mkSymbol(int i, int c);
144
145 private:
146 BuildUtil *up;
147 unsigned array, arrayIdx;
148
149 uint32_t baseAddr;
150 uint32_t arrayLen;
151 Symbol *baseSym;
152
153 uint8_t vecDim;
154 uint8_t eltSize; // in bytes
155
156 DataFile file;
157 bool regOnly;
158 };
159
160 Symbol *mkSymbol(DataFile file, int8_t fileIndex,
161 DataType ty, uint32_t baseAddress);
162
163 Symbol *mkSysVal(SVSemantic svName, uint32_t svIndex);
164
165 private:
166 void init(Program *);
167 void addImmediate(ImmediateValue *);
168 inline unsigned int u32Hash(uint32_t);
169
170 protected:
171 Program *prog;
172 Function *func;
173 Instruction *pos;
174 BasicBlock *bb;
175 bool tail;
176
177 #define NV50_IR_BUILD_IMM_HT_SIZE 256
178
179 ImmediateValue *imms[NV50_IR_BUILD_IMM_HT_SIZE];
180 unsigned int immCount;
181 };
182
183 unsigned int BuildUtil::u32Hash(uint32_t u)
184 {
185 return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE;
186 }
187
188 void BuildUtil::setProgram(Program *program)
189 {
190 prog = program;
191 }
192
193 void
194 BuildUtil::setPosition(BasicBlock *block, bool atTail)
195 {
196 bb = block;
197 prog = bb->getProgram();
198 func = bb->getFunction();
199 pos = NULL;
200 tail = atTail;
201 }
202
203 void
204 BuildUtil::setPosition(Instruction *i, bool after)
205 {
206 bb = i->bb;
207 prog = bb->getProgram();
208 func = bb->getFunction();
209 pos = i;
210 tail = after;
211 assert(bb);
212 }
213
214 LValue *
215 BuildUtil::getScratch(int size, DataFile f)
216 {
217 LValue *lval = new_LValue(func, f);
218 if (size != 4)
219 lval->reg.size = size;
220 return lval;
221 }
222
223 LValue *
224 BuildUtil::getSSA(int size)
225 {
226 LValue *lval = new_LValue(func, FILE_GPR);
227 lval->ssa = 1;
228 if (size != 4)
229 lval->reg.size = size;
230 return lval;
231 }
232
233 void BuildUtil::insert(Instruction *i)
234 {
235 if (!pos) {
236 tail ? bb->insertTail(i) : bb->insertHead(i);
237 } else {
238 if (tail) {
239 bb->insertAfter(pos, i);
240 pos = i;
241 } else {
242 bb->insertBefore(pos, i);
243 }
244 }
245 }
246
247 Instruction *
248 BuildUtil::mkOp(operation op, DataType ty, Value *dst)
249 {
250 Instruction *insn = new_Instruction(func, op, ty);
251 insn->setDef(0, dst);
252 insert(insn);
253 if (op == OP_DISCARD || op == OP_EXIT ||
254 op == OP_JOIN ||
255 op == OP_QUADON || op == OP_QUADPOP ||
256 op == OP_EMIT || op == OP_RESTART)
257 insn->fixed = 1;
258 return insn;
259 }
260
261 inline LValue *
262 BuildUtil::mkOp1v(operation op, DataType ty, Value *dst, Value *src)
263 {
264 mkOp1(op, ty, dst, src);
265 return dst->asLValue();
266 }
267
268 inline LValue *
269 BuildUtil::mkOp2v(operation op, DataType ty, Value *dst,
270 Value *src0, Value *src1)
271 {
272 mkOp2(op, ty, dst, src0, src1);
273 return dst->asLValue();
274 }
275
276 inline LValue *
277 BuildUtil::mkOp3v(operation op, DataType ty, Value *dst,
278 Value *src0, Value *src1, Value *src2)
279 {
280 mkOp3(op, ty, dst, src0, src1, src2);
281 return dst->asLValue();
282 }
283
284 bool
285 BuildUtil::DataArray::exists(ValueMap &m, unsigned int i, unsigned int c)
286 {
287 assert(i < arrayLen && c < vecDim);
288 return !regOnly || m.r.count(Location(array, arrayIdx, i, c));
289 }
290
291 Value *
292 BuildUtil::DataArray::lookup(ValueMap &m, unsigned i, unsigned c)
293 {
294 ValueMap::r_iterator it = m.r.find(Location(array, arrayIdx, i, c));
295 return it != m.r.end() ? it->second : NULL;
296 }
297
298 Value *
299 BuildUtil::DataArray::insert(ValueMap &m, unsigned i, unsigned c, Value *v)
300 {
301 m.insert(Location(array, arrayIdx, i, c), v);
302 return v;
303 }
304
305 } // namespace nv50_ir
306
307 #endif // __NV50_IR_BUILD_UTIL_H__