• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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