691588615338e88c2ed6eae4e794846899523307
[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, BasicBlock *target,
80 CondCode, Value *pred);
81
82 Instruction *mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc);
83
84 void mkClobber(DataFile file, uint32_t regMask, int regUnitLog2);
85
86 ImmediateValue *mkImm(float);
87 ImmediateValue *mkImm(uint32_t);
88 ImmediateValue *mkImm(uint64_t);
89
90 ImmediateValue *mkImm(int i) { return mkImm((uint32_t)i); }
91
92 Value *loadImm(Value *dst, float);
93 Value *loadImm(Value *dst, uint32_t);
94 Value *loadImm(Value *dst, uint64_t);
95
96 Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
97
98 struct Location
99 {
100 Location(unsigned array, unsigned arrayIdx, unsigned i, unsigned c)
101 : array(array), arrayIdx(arrayIdx), i(i), c(c) { }
102 Location(const Location &l)
103 : array(l.array), arrayIdx(l.arrayIdx), i(l.i), c(l.c) { }
104
105 bool operator==(const Location &l) const
106 {
107 return
108 array == l.array && arrayIdx == l.arrayIdx && i == l.i && c == l.c;
109 }
110
111 bool operator<(const Location &l) const
112 {
113 return array != l.array ? array < l.array :
114 arrayIdx != l.arrayIdx ? arrayIdx < l.arrayIdx :
115 i != l.i ? i < l.i :
116 c != l.c ? c < l.c :
117 false;
118 }
119
120 unsigned array, arrayIdx, i, c;
121 };
122
123 typedef bimap<Location, Value *> ValueMap;
124
125 class DataArray
126 {
127 public:
128 DataArray(BuildUtil *bld) : up(bld) { }
129
130 void setup(unsigned array, unsigned arrayIdx,
131 uint32_t base, int len, int vecDim, int eltSize,
132 DataFile file, int8_t fileIdx);
133
134 inline bool exists(ValueMap&, unsigned int i, unsigned int c);
135
136 Value *load(ValueMap&, int i, int c, Value *ptr);
137 void store(ValueMap&, int i, int c, Value *ptr, Value *value);
138 Value *acquire(ValueMap&, int i, int c);
139
140 private:
141 inline Value *lookup(ValueMap&, unsigned i, unsigned c);
142 inline Value *insert(ValueMap&, unsigned i, unsigned c, Value *v);
143
144 Symbol *mkSymbol(int i, int c);
145
146 private:
147 BuildUtil *up;
148 unsigned array, arrayIdx;
149
150 uint32_t baseAddr;
151 uint32_t arrayLen;
152 Symbol *baseSym;
153
154 uint8_t vecDim;
155 uint8_t eltSize; // in bytes
156
157 DataFile file;
158 bool regOnly;
159 };
160
161 Symbol *mkSymbol(DataFile file, int8_t fileIndex,
162 DataType ty, uint32_t baseAddress);
163
164 Symbol *mkSysVal(SVSemantic svName, uint32_t svIndex);
165
166 private:
167 void init(Program *);
168 void addImmediate(ImmediateValue *);
169 inline unsigned int u32Hash(uint32_t);
170
171 protected:
172 Program *prog;
173 Function *func;
174 Instruction *pos;
175 BasicBlock *bb;
176 bool tail;
177
178 #define NV50_IR_BUILD_IMM_HT_SIZE 256
179
180 ImmediateValue *imms[NV50_IR_BUILD_IMM_HT_SIZE];
181 unsigned int immCount;
182 };
183
184 unsigned int BuildUtil::u32Hash(uint32_t u)
185 {
186 return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE;
187 }
188
189 void BuildUtil::setProgram(Program *program)
190 {
191 prog = program;
192 }
193
194 void
195 BuildUtil::setPosition(BasicBlock *block, bool atTail)
196 {
197 bb = block;
198 prog = bb->getProgram();
199 func = bb->getFunction();
200 pos = NULL;
201 tail = atTail;
202 }
203
204 void
205 BuildUtil::setPosition(Instruction *i, bool after)
206 {
207 bb = i->bb;
208 prog = bb->getProgram();
209 func = bb->getFunction();
210 pos = i;
211 tail = after;
212 assert(bb);
213 }
214
215 LValue *
216 BuildUtil::getScratch(int size, DataFile f)
217 {
218 LValue *lval = new_LValue(func, f);
219 if (size != 4)
220 lval->reg.size = size;
221 return lval;
222 }
223
224 LValue *
225 BuildUtil::getSSA(int size)
226 {
227 LValue *lval = new_LValue(func, FILE_GPR);
228 lval->ssa = 1;
229 if (size != 4)
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__