• 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 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 *);
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    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 
mkImm(int i)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 
loadImm(Value * dst,int i)98    Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
99 
100    struct Location
101    {
LocationLocation102       Location(unsigned array, unsigned arrayIdx, unsigned i, unsigned c)
103          : array(array), arrayIdx(arrayIdx), i(i), c(c) { }
LocationLocation104       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:
DataArray(BuildUtil * bld)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 
u32Hash(uint32_t u)186 unsigned int BuildUtil::u32Hash(uint32_t u)
187 {
188    return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE;
189 }
190 
setProgram(Program * program)191 void BuildUtil::setProgram(Program *program)
192 {
193    prog = program;
194 }
195 
196 void
setPosition(BasicBlock * block,bool atTail)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
setPosition(Instruction * i,bool after)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 *
getScratch(int size,DataFile f)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 *
getSSA(int size,DataFile f)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 
insert(Instruction * i)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 *
mkOp(operation op,DataType ty,Value * dst)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 *
mkOp1v(operation op,DataType ty,Value * dst,Value * src)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 *
mkOp2v(operation op,DataType ty,Value * dst,Value * src0,Value * src1)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 *
mkOp3v(operation op,DataType ty,Value * dst,Value * src0,Value * src1,Value * src2)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
exists(ValueMap & m,unsigned int i,unsigned int c)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 *
lookup(ValueMap & m,unsigned i,unsigned c)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 *
insert(ValueMap & m,unsigned i,unsigned c,Value * v)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__
309