1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2011 Christoph Bumiller
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
12bf215546Sopenharmony_ci * all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#ifndef __NV50_IR_BUILD_UTIL__
24bf215546Sopenharmony_ci#define __NV50_IR_BUILD_UTIL__
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_cinamespace nv50_ir {
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ciclass BuildUtil
29bf215546Sopenharmony_ci{
30bf215546Sopenharmony_cipublic:
31bf215546Sopenharmony_ci   BuildUtil();
32bf215546Sopenharmony_ci   BuildUtil(Program *);
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci   inline void setProgram(Program *);
35bf215546Sopenharmony_ci   inline Program *getProgram() const { return prog; }
36bf215546Sopenharmony_ci   inline Function *getFunction() const { return func; }
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci   // keeps inserting at head/tail of block
39bf215546Sopenharmony_ci   inline void setPosition(BasicBlock *, bool tail);
40bf215546Sopenharmony_ci   // position advances only if @after is true
41bf215546Sopenharmony_ci   inline void setPosition(Instruction *, bool after);
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci   inline BasicBlock *getBB() { return bb; }
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci   inline void insert(Instruction *);
46bf215546Sopenharmony_ci   inline void remove(Instruction *i) { assert(i->bb == bb); bb->remove(i); }
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci   inline LValue *getScratch(int size = 4, DataFile = FILE_GPR);
49bf215546Sopenharmony_ci   // scratch value for a single assignment:
50bf215546Sopenharmony_ci   inline LValue *getSSA(int size = 4, DataFile = FILE_GPR);
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   inline Instruction *mkOp(operation, DataType, Value *);
53bf215546Sopenharmony_ci   Instruction *mkOp1(operation, DataType, Value *, Value *);
54bf215546Sopenharmony_ci   Instruction *mkOp2(operation, DataType, Value *, Value *, Value *);
55bf215546Sopenharmony_ci   Instruction *mkOp3(operation, DataType, Value *, Value *, Value *, Value *);
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci   LValue *mkOp1v(operation, DataType, Value *, Value *);
58bf215546Sopenharmony_ci   LValue *mkOp2v(operation, DataType, Value *, Value *, Value *);
59bf215546Sopenharmony_ci   LValue *mkOp3v(operation, DataType, Value *, Value *, Value *, Value *);
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci   Instruction *mkLoad(DataType, Value *dst, Symbol *, Value *ptr);
62bf215546Sopenharmony_ci   Instruction *mkStore(operation, DataType, Symbol *, Value *ptr, Value *val);
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   LValue *mkLoadv(DataType, Symbol *, Value *ptr);
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   Instruction *mkMov(Value *, Value *, DataType = TYPE_U32);
67bf215546Sopenharmony_ci   Instruction *mkMovToReg(int id, Value *);
68bf215546Sopenharmony_ci   Instruction *mkMovFromReg(Value *, int id);
69bf215546Sopenharmony_ci   inline Instruction *mkBMov(Value *, Value *);
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci   Instruction *mkInterp(unsigned mode, Value *, int32_t offset, Value *rel);
72bf215546Sopenharmony_ci   Instruction *mkFetch(Value *, DataType, DataFile, int32_t offset,
73bf215546Sopenharmony_ci                        Value *attrRel, Value *primRel);
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   Instruction *mkCvt(operation, DataType, Value *, DataType, Value *);
76bf215546Sopenharmony_ci   CmpInstruction *mkCmp(operation, CondCode, DataType,
77bf215546Sopenharmony_ci                         Value *,
78bf215546Sopenharmony_ci                         DataType, Value *, Value *, Value * = NULL);
79bf215546Sopenharmony_ci   TexInstruction *mkTex(operation, TexTarget,
80bf215546Sopenharmony_ci                         uint16_t tic, uint16_t tsc,
81bf215546Sopenharmony_ci                         const std::vector<Value *> &def,
82bf215546Sopenharmony_ci                         const std::vector<Value *> &src);
83bf215546Sopenharmony_ci   Instruction *mkQuadop(uint8_t qop, Value *, uint8_t l, Value *, Value *);
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci   FlowInstruction *mkFlow(operation, void *target, CondCode, Value *pred);
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   Instruction *mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc);
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   Instruction *mkSplit(Value *half[2], uint8_t halfSize, Value *);
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   void mkClobber(DataFile file, uint32_t regMask, int regUnitLog2);
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   ImmediateValue *mkImm(float);
94bf215546Sopenharmony_ci   ImmediateValue *mkImm(double);
95bf215546Sopenharmony_ci   ImmediateValue *mkImm(uint16_t);
96bf215546Sopenharmony_ci   ImmediateValue *mkImm(uint32_t);
97bf215546Sopenharmony_ci   ImmediateValue *mkImm(uint64_t);
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   ImmediateValue *mkImm(int i) { return mkImm((uint32_t)i); }
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   Value *loadImm(Value *dst, float);
102bf215546Sopenharmony_ci   Value *loadImm(Value *dst, double);
103bf215546Sopenharmony_ci   Value *loadImm(Value *dst, uint16_t);
104bf215546Sopenharmony_ci   Value *loadImm(Value *dst, uint32_t);
105bf215546Sopenharmony_ci   Value *loadImm(Value *dst, uint64_t);
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   // returns high part of the operation
110bf215546Sopenharmony_ci   static Instruction *split64BitOpPostRA(Function *, Instruction *,
111bf215546Sopenharmony_ci                                          Value *zero, Value *carry);
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   struct Location
114bf215546Sopenharmony_ci   {
115bf215546Sopenharmony_ci      Location(unsigned array, unsigned arrayIdx, unsigned i, unsigned c)
116bf215546Sopenharmony_ci         : array(array), arrayIdx(arrayIdx), i(i), c(c) { }
117bf215546Sopenharmony_ci      Location(const Location &l)
118bf215546Sopenharmony_ci         : array(l.array), arrayIdx(l.arrayIdx), i(l.i), c(l.c) { }
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci      bool operator==(const Location &l) const
121bf215546Sopenharmony_ci      {
122bf215546Sopenharmony_ci         return
123bf215546Sopenharmony_ci            array == l.array && arrayIdx == l.arrayIdx && i == l.i && c == l.c;
124bf215546Sopenharmony_ci      }
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci      bool operator<(const Location &l) const
127bf215546Sopenharmony_ci      {
128bf215546Sopenharmony_ci         return array != l.array ? array < l.array :
129bf215546Sopenharmony_ci            arrayIdx != l.arrayIdx ? arrayIdx < l.arrayIdx :
130bf215546Sopenharmony_ci            i != l.i ? i < l.i :
131bf215546Sopenharmony_ci            c != l.c ? c < l.c :
132bf215546Sopenharmony_ci            false;
133bf215546Sopenharmony_ci      }
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci      unsigned array, arrayIdx, i, c;
136bf215546Sopenharmony_ci   };
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   typedef bimap<Location, Value *> ValueMap;
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci   class DataArray
141bf215546Sopenharmony_ci   {
142bf215546Sopenharmony_ci   public:
143bf215546Sopenharmony_ci      DataArray(BuildUtil *bld) : up(bld), array(0), arrayIdx(0), baseAddr(0),
144bf215546Sopenharmony_ci         arrayLen(0), baseSym(NULL), vecDim(0), eltSize(0), file(FILE_NULL),
145bf215546Sopenharmony_ci         regOnly(false) { }
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci      void setup(unsigned array, unsigned arrayIdx,
148bf215546Sopenharmony_ci                 uint32_t base, int len, int vecDim, int eltSize,
149bf215546Sopenharmony_ci                 DataFile file, int8_t fileIdx);
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci      inline bool exists(ValueMap&, unsigned int i, unsigned int c);
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci      Value *load(ValueMap&, int i, int c, Value *ptr);
154bf215546Sopenharmony_ci      void store(ValueMap&, int i, int c, Value *ptr, Value *value);
155bf215546Sopenharmony_ci      Value *acquire(ValueMap&, int i, int c);
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   private:
158bf215546Sopenharmony_ci      inline Value *lookup(ValueMap&, unsigned i, unsigned c);
159bf215546Sopenharmony_ci      inline Value *insert(ValueMap&, unsigned i, unsigned c, Value *v);
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci      Symbol *mkSymbol(int i, int c);
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci   private:
164bf215546Sopenharmony_ci      BuildUtil *up;
165bf215546Sopenharmony_ci      unsigned array, arrayIdx;
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci      uint32_t baseAddr;
168bf215546Sopenharmony_ci      uint32_t arrayLen;
169bf215546Sopenharmony_ci      Symbol *baseSym;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci      uint8_t vecDim;
172bf215546Sopenharmony_ci      uint8_t eltSize; // in bytes
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci      DataFile file;
175bf215546Sopenharmony_ci      bool regOnly;
176bf215546Sopenharmony_ci   };
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   Symbol *mkSymbol(DataFile file, int8_t fileIndex,
179bf215546Sopenharmony_ci                    DataType ty, uint32_t baseAddress);
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci   Symbol *mkSysVal(SVSemantic svName, uint32_t svIndex);
182bf215546Sopenharmony_ci   Symbol *mkTSVal(TSSemantic tsName);
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ciprivate:
185bf215546Sopenharmony_ci   void init(Program *);
186bf215546Sopenharmony_ci   void addImmediate(ImmediateValue *);
187bf215546Sopenharmony_ci   inline unsigned int u32Hash(uint32_t);
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ciprotected:
190bf215546Sopenharmony_ci   Program *prog;
191bf215546Sopenharmony_ci   Function *func;
192bf215546Sopenharmony_ci   Instruction *pos;
193bf215546Sopenharmony_ci   BasicBlock *bb;
194bf215546Sopenharmony_ci   bool tail;
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci#define NV50_IR_BUILD_IMM_HT_SIZE 256
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci   ImmediateValue *imms[NV50_IR_BUILD_IMM_HT_SIZE];
199bf215546Sopenharmony_ci   unsigned int immCount;
200bf215546Sopenharmony_ci};
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ciunsigned int BuildUtil::u32Hash(uint32_t u)
203bf215546Sopenharmony_ci{
204bf215546Sopenharmony_ci   return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE;
205bf215546Sopenharmony_ci}
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_civoid BuildUtil::setProgram(Program *program)
208bf215546Sopenharmony_ci{
209bf215546Sopenharmony_ci   prog = program;
210bf215546Sopenharmony_ci}
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_civoid
213bf215546Sopenharmony_ciBuildUtil::setPosition(BasicBlock *block, bool atTail)
214bf215546Sopenharmony_ci{
215bf215546Sopenharmony_ci   bb = block;
216bf215546Sopenharmony_ci   prog = bb->getProgram();
217bf215546Sopenharmony_ci   func = bb->getFunction();
218bf215546Sopenharmony_ci   pos = NULL;
219bf215546Sopenharmony_ci   tail = atTail;
220bf215546Sopenharmony_ci}
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_civoid
223bf215546Sopenharmony_ciBuildUtil::setPosition(Instruction *i, bool after)
224bf215546Sopenharmony_ci{
225bf215546Sopenharmony_ci   bb = i->bb;
226bf215546Sopenharmony_ci   prog = bb->getProgram();
227bf215546Sopenharmony_ci   func = bb->getFunction();
228bf215546Sopenharmony_ci   pos = i;
229bf215546Sopenharmony_ci   tail = after;
230bf215546Sopenharmony_ci   assert(bb);
231bf215546Sopenharmony_ci}
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ciLValue *
234bf215546Sopenharmony_ciBuildUtil::getScratch(int size, DataFile f)
235bf215546Sopenharmony_ci{
236bf215546Sopenharmony_ci   LValue *lval = new_LValue(func, f);
237bf215546Sopenharmony_ci   lval->reg.size = size;
238bf215546Sopenharmony_ci   return lval;
239bf215546Sopenharmony_ci}
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ciLValue *
242bf215546Sopenharmony_ciBuildUtil::getSSA(int size, DataFile f)
243bf215546Sopenharmony_ci{
244bf215546Sopenharmony_ci   LValue *lval = new_LValue(func, f);
245bf215546Sopenharmony_ci   lval->ssa = 1;
246bf215546Sopenharmony_ci   lval->reg.size = size;
247bf215546Sopenharmony_ci   return lval;
248bf215546Sopenharmony_ci}
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_civoid BuildUtil::insert(Instruction *i)
251bf215546Sopenharmony_ci{
252bf215546Sopenharmony_ci   if (!pos) {
253bf215546Sopenharmony_ci      tail ? bb->insertTail(i) : bb->insertHead(i);
254bf215546Sopenharmony_ci   } else {
255bf215546Sopenharmony_ci      if (tail) {
256bf215546Sopenharmony_ci         bb->insertAfter(pos, i);
257bf215546Sopenharmony_ci         pos = i;
258bf215546Sopenharmony_ci      } else {
259bf215546Sopenharmony_ci         bb->insertBefore(pos, i);
260bf215546Sopenharmony_ci      }
261bf215546Sopenharmony_ci   }
262bf215546Sopenharmony_ci}
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ciInstruction *
265bf215546Sopenharmony_ciBuildUtil::mkOp(operation op, DataType ty, Value *dst)
266bf215546Sopenharmony_ci{
267bf215546Sopenharmony_ci   Instruction *insn = new_Instruction(func, op, ty);
268bf215546Sopenharmony_ci   insn->setDef(0, dst);
269bf215546Sopenharmony_ci   insert(insn);
270bf215546Sopenharmony_ci   if (op == OP_DISCARD || op == OP_EXIT ||
271bf215546Sopenharmony_ci       op == OP_JOIN ||
272bf215546Sopenharmony_ci       op == OP_QUADON || op == OP_QUADPOP ||
273bf215546Sopenharmony_ci       op == OP_EMIT || op == OP_RESTART)
274bf215546Sopenharmony_ci      insn->fixed = 1;
275bf215546Sopenharmony_ci   return insn;
276bf215546Sopenharmony_ci}
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ciinline LValue *
279bf215546Sopenharmony_ciBuildUtil::mkOp1v(operation op, DataType ty, Value *dst, Value *src)
280bf215546Sopenharmony_ci{
281bf215546Sopenharmony_ci   mkOp1(op, ty, dst, src);
282bf215546Sopenharmony_ci   return dst->asLValue();
283bf215546Sopenharmony_ci}
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ciinline LValue *
286bf215546Sopenharmony_ciBuildUtil::mkOp2v(operation op, DataType ty, Value *dst,
287bf215546Sopenharmony_ci                  Value *src0, Value *src1)
288bf215546Sopenharmony_ci{
289bf215546Sopenharmony_ci   mkOp2(op, ty, dst, src0, src1);
290bf215546Sopenharmony_ci   return dst->asLValue();
291bf215546Sopenharmony_ci}
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ciinline LValue *
294bf215546Sopenharmony_ciBuildUtil::mkOp3v(operation op, DataType ty, Value *dst,
295bf215546Sopenharmony_ci                  Value *src0, Value *src1, Value *src2)
296bf215546Sopenharmony_ci{
297bf215546Sopenharmony_ci   mkOp3(op, ty, dst, src0, src1, src2);
298bf215546Sopenharmony_ci   return dst->asLValue();
299bf215546Sopenharmony_ci}
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ciinline LValue *
302bf215546Sopenharmony_ciBuildUtil::mkLoadv(DataType ty, Symbol *mem, Value *ptr)
303bf215546Sopenharmony_ci{
304bf215546Sopenharmony_ci   LValue *dst = getScratch(typeSizeof(ty));
305bf215546Sopenharmony_ci   mkLoad(ty, dst, mem, ptr);
306bf215546Sopenharmony_ci   return dst;
307bf215546Sopenharmony_ci}
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ciinline Instruction *
310bf215546Sopenharmony_ciBuildUtil::mkBMov(Value *dst, Value *src)
311bf215546Sopenharmony_ci{
312bf215546Sopenharmony_ci   return mkCvt(OP_CVT, TYPE_U32, dst, TYPE_U32, src);
313bf215546Sopenharmony_ci}
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_cibool
316bf215546Sopenharmony_ciBuildUtil::DataArray::exists(ValueMap &m, unsigned int i, unsigned int c)
317bf215546Sopenharmony_ci{
318bf215546Sopenharmony_ci   assert(i < arrayLen && c < vecDim);
319bf215546Sopenharmony_ci   return !regOnly || m.r.count(Location(array, arrayIdx, i, c));
320bf215546Sopenharmony_ci}
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ciValue *
323bf215546Sopenharmony_ciBuildUtil::DataArray::lookup(ValueMap &m, unsigned i, unsigned c)
324bf215546Sopenharmony_ci{
325bf215546Sopenharmony_ci   ValueMap::r_iterator it = m.r.find(Location(array, arrayIdx, i, c));
326bf215546Sopenharmony_ci   return it != m.r.end() ? it->second : NULL;
327bf215546Sopenharmony_ci}
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ciValue *
330bf215546Sopenharmony_ciBuildUtil::DataArray::insert(ValueMap &m, unsigned i, unsigned c, Value *v)
331bf215546Sopenharmony_ci{
332bf215546Sopenharmony_ci   m.insert(Location(array, arrayIdx, i, c), v);
333bf215546Sopenharmony_ci   return v;
334bf215546Sopenharmony_ci}
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci} // namespace nv50_ir
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci#endif // __NV50_IR_BUILD_UTIL_H__
339