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