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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE 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 *);
getProgram()35 inline Program *getProgram() const { return prog; }
getFunction()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
getBB()43 inline BasicBlock *getBB() { return bb; }
44
45 inline void insert(Instruction *);
remove(Instruction * i)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 Instruction *mkLoad(DataType, Value *dst, Symbol *, Value *ptr);
62 Instruction *mkStore(operation, DataType, Symbol *, Value *ptr, Value *val);
63
64 LValue *mkLoadv(DataType, Symbol *, Value *ptr);
65
66 Instruction *mkMov(Value *, Value *, DataType = TYPE_U32);
67 Instruction *mkMovToReg(int id, Value *);
68 Instruction *mkMovFromReg(Value *, int id);
69 inline Instruction *mkBMov(Value *, Value *);
70
71 Instruction *mkInterp(unsigned mode, Value *, int32_t offset, Value *rel);
72 Instruction *mkFetch(Value *, DataType, DataFile, int32_t offset,
73 Value *attrRel, Value *primRel);
74
75 Instruction *mkCvt(operation, DataType, Value *, DataType, Value *);
76 CmpInstruction *mkCmp(operation, CondCode, DataType,
77 Value *,
78 DataType, Value *, Value *, Value * = NULL);
79 TexInstruction *mkTex(operation, TexTarget,
80 uint16_t tic, uint16_t tsc,
81 const std::vector<Value *> &def,
82 const std::vector<Value *> &src);
83 Instruction *mkQuadop(uint8_t qop, Value *, uint8_t l, Value *, Value *);
84
85 FlowInstruction *mkFlow(operation, void *target, CondCode, Value *pred);
86
87 Instruction *mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc);
88
89 Instruction *mkSplit(Value *half[2], uint8_t halfSize, Value *);
90
91 void mkClobber(DataFile file, uint32_t regMask, int regUnitLog2);
92
93 ImmediateValue *mkImm(float);
94 ImmediateValue *mkImm(double);
95 ImmediateValue *mkImm(uint16_t);
96 ImmediateValue *mkImm(uint32_t);
97 ImmediateValue *mkImm(uint64_t);
98
mkImm(int i)99 ImmediateValue *mkImm(int i) { return mkImm((uint32_t)i); }
100
101 Value *loadImm(Value *dst, float);
102 Value *loadImm(Value *dst, double);
103 Value *loadImm(Value *dst, uint16_t);
104 Value *loadImm(Value *dst, uint32_t);
105 Value *loadImm(Value *dst, uint64_t);
106
loadImm(Value * dst,int i)107 Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
108
109 // returns high part of the operation
110 static Instruction *split64BitOpPostRA(Function *, Instruction *,
111 Value *zero, Value *carry);
112
113 struct Location
114 {
LocationLocation115 Location(unsigned array, unsigned arrayIdx, unsigned i, unsigned c)
116 : array(array), arrayIdx(arrayIdx), i(i), c(c) { }
LocationLocation117 Location(const Location &l)
118 : array(l.array), arrayIdx(l.arrayIdx), i(l.i), c(l.c) { }
119
120 bool operator==(const Location &l) const
121 {
122 return
123 array == l.array && arrayIdx == l.arrayIdx && i == l.i && c == l.c;
124 }
125
126 bool operator<(const Location &l) const
127 {
128 return array != l.array ? array < l.array :
129 arrayIdx != l.arrayIdx ? arrayIdx < l.arrayIdx :
130 i != l.i ? i < l.i :
131 c != l.c ? c < l.c :
132 false;
133 }
134
135 unsigned array, arrayIdx, i, c;
136 };
137
138 typedef bimap<Location, Value *> ValueMap;
139
140 class DataArray
141 {
142 public:
DataArray(BuildUtil * bld)143 DataArray(BuildUtil *bld) : up(bld), array(0), arrayIdx(0), baseAddr(0),
144 arrayLen(0), baseSym(NULL), vecDim(0), eltSize(0), file(FILE_NULL),
145 regOnly(false) { }
146
147 void setup(unsigned array, unsigned arrayIdx,
148 uint32_t base, int len, int vecDim, int eltSize,
149 DataFile file, int8_t fileIdx);
150
151 inline bool exists(ValueMap&, unsigned int i, unsigned int c);
152
153 Value *load(ValueMap&, int i, int c, Value *ptr);
154 void store(ValueMap&, int i, int c, Value *ptr, Value *value);
155 Value *acquire(ValueMap&, int i, int c);
156
157 private:
158 inline Value *lookup(ValueMap&, unsigned i, unsigned c);
159 inline Value *insert(ValueMap&, unsigned i, unsigned c, Value *v);
160
161 Symbol *mkSymbol(int i, int c);
162
163 private:
164 BuildUtil *up;
165 unsigned array, arrayIdx;
166
167 uint32_t baseAddr;
168 uint32_t arrayLen;
169 Symbol *baseSym;
170
171 uint8_t vecDim;
172 uint8_t eltSize; // in bytes
173
174 DataFile file;
175 bool regOnly;
176 };
177
178 Symbol *mkSymbol(DataFile file, int8_t fileIndex,
179 DataType ty, uint32_t baseAddress);
180
181 Symbol *mkSysVal(SVSemantic svName, uint32_t svIndex);
182 Symbol *mkTSVal(TSSemantic tsName);
183
184 private:
185 void init(Program *);
186 void addImmediate(ImmediateValue *);
187 inline unsigned int u32Hash(uint32_t);
188
189 protected:
190 Program *prog;
191 Function *func;
192 Instruction *pos;
193 BasicBlock *bb;
194 bool tail;
195
196 #define NV50_IR_BUILD_IMM_HT_SIZE 256
197
198 ImmediateValue *imms[NV50_IR_BUILD_IMM_HT_SIZE];
199 unsigned int immCount;
200 };
201
u32Hash(uint32_t u)202 unsigned int BuildUtil::u32Hash(uint32_t u)
203 {
204 return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE;
205 }
206
setProgram(Program * program)207 void BuildUtil::setProgram(Program *program)
208 {
209 prog = program;
210 }
211
212 void
setPosition(BasicBlock * block,bool atTail)213 BuildUtil::setPosition(BasicBlock *block, bool atTail)
214 {
215 bb = block;
216 prog = bb->getProgram();
217 func = bb->getFunction();
218 pos = NULL;
219 tail = atTail;
220 }
221
222 void
setPosition(Instruction * i,bool after)223 BuildUtil::setPosition(Instruction *i, bool after)
224 {
225 bb = i->bb;
226 prog = bb->getProgram();
227 func = bb->getFunction();
228 pos = i;
229 tail = after;
230 assert(bb);
231 }
232
233 LValue *
getScratch(int size,DataFile f)234 BuildUtil::getScratch(int size, DataFile f)
235 {
236 LValue *lval = new_LValue(func, f);
237 lval->reg.size = size;
238 return lval;
239 }
240
241 LValue *
getSSA(int size,DataFile f)242 BuildUtil::getSSA(int size, DataFile f)
243 {
244 LValue *lval = new_LValue(func, f);
245 lval->ssa = 1;
246 lval->reg.size = size;
247 return lval;
248 }
249
insert(Instruction * i)250 void BuildUtil::insert(Instruction *i)
251 {
252 if (!pos) {
253 tail ? bb->insertTail(i) : bb->insertHead(i);
254 } else {
255 if (tail) {
256 bb->insertAfter(pos, i);
257 pos = i;
258 } else {
259 bb->insertBefore(pos, i);
260 }
261 }
262 }
263
264 Instruction *
mkOp(operation op,DataType ty,Value * dst)265 BuildUtil::mkOp(operation op, DataType ty, Value *dst)
266 {
267 Instruction *insn = new_Instruction(func, op, ty);
268 insn->setDef(0, dst);
269 insert(insn);
270 if (op == OP_DISCARD || op == OP_EXIT ||
271 op == OP_JOIN ||
272 op == OP_QUADON || op == OP_QUADPOP ||
273 op == OP_EMIT || op == OP_RESTART)
274 insn->fixed = 1;
275 return insn;
276 }
277
278 inline LValue *
mkOp1v(operation op,DataType ty,Value * dst,Value * src)279 BuildUtil::mkOp1v(operation op, DataType ty, Value *dst, Value *src)
280 {
281 mkOp1(op, ty, dst, src);
282 return dst->asLValue();
283 }
284
285 inline LValue *
mkOp2v(operation op,DataType ty,Value * dst,Value * src0,Value * src1)286 BuildUtil::mkOp2v(operation op, DataType ty, Value *dst,
287 Value *src0, Value *src1)
288 {
289 mkOp2(op, ty, dst, src0, src1);
290 return dst->asLValue();
291 }
292
293 inline LValue *
mkOp3v(operation op,DataType ty,Value * dst,Value * src0,Value * src1,Value * src2)294 BuildUtil::mkOp3v(operation op, DataType ty, Value *dst,
295 Value *src0, Value *src1, Value *src2)
296 {
297 mkOp3(op, ty, dst, src0, src1, src2);
298 return dst->asLValue();
299 }
300
301 inline LValue *
mkLoadv(DataType ty,Symbol * mem,Value * ptr)302 BuildUtil::mkLoadv(DataType ty, Symbol *mem, Value *ptr)
303 {
304 LValue *dst = getScratch(typeSizeof(ty));
305 mkLoad(ty, dst, mem, ptr);
306 return dst;
307 }
308
309 inline Instruction *
mkBMov(Value * dst,Value * src)310 BuildUtil::mkBMov(Value *dst, Value *src)
311 {
312 return mkCvt(OP_CVT, TYPE_U32, dst, TYPE_U32, src);
313 }
314
315 bool
exists(ValueMap & m,unsigned int i,unsigned int c)316 BuildUtil::DataArray::exists(ValueMap &m, unsigned int i, unsigned int c)
317 {
318 assert(i < arrayLen && c < vecDim);
319 return !regOnly || m.r.count(Location(array, arrayIdx, i, c));
320 }
321
322 Value *
lookup(ValueMap & m,unsigned i,unsigned c)323 BuildUtil::DataArray::lookup(ValueMap &m, unsigned i, unsigned c)
324 {
325 ValueMap::r_iterator it = m.r.find(Location(array, arrayIdx, i, c));
326 return it != m.r.end() ? it->second : NULL;
327 }
328
329 Value *
insert(ValueMap & m,unsigned i,unsigned c,Value * v)330 BuildUtil::DataArray::insert(ValueMap &m, unsigned i, unsigned c, Value *v)
331 {
332 m.insert(Location(array, arrayIdx, i, c), v);
333 return v;
334 }
335
336 } // namespace nv50_ir
337
338 #endif // __NV50_IR_BUILD_UTIL_H__
339