nv50/ir: use RDSV to fetch FrontFacing before lowering
[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
33 inline void setProgram(Program *);
34 inline Program *getProgram() const { return prog; }
35 inline Function *getFunction() const { return func; }
36
37 // keeps inserting at head/tail of block
38 inline void setPosition(BasicBlock *, bool tail);
39 // position advances only if @after is true
40 inline void setPosition(Instruction *, bool after);
41
42 inline BasicBlock *getBB() { return bb; }
43
44 inline void insert(Instruction *);
45 inline void remove(Instruction *i) { assert(i->bb == bb); bb->remove(i); }
46
47 inline LValue *getScratch(int size = 4);
48 inline LValue *getSSA(int size = 4); // scratch value for a single assignment
49
50 inline Instruction *mkOp(operation, DataType, Value *);
51 Instruction *mkOp1(operation, DataType, Value *, Value *);
52 Instruction *mkOp2(operation, DataType, Value *, Value *, Value *);
53 Instruction *mkOp3(operation, DataType, Value *, Value *, Value *, Value *);
54
55 LValue *mkOp1v(operation, DataType, Value *, Value *);
56 LValue *mkOp2v(operation, DataType, Value *, Value *, Value *);
57 LValue *mkOp3v(operation, DataType, Value *, Value *, Value *, Value *);
58
59 LValue *mkLoad(DataType, Symbol *, Value *ptr);
60 Instruction *mkStore(operation, DataType, Symbol *, Value *ptr, Value *val);
61
62 Instruction *mkMov(Value *, Value *, DataType = TYPE_U32);
63 Instruction *mkMovToReg(int id, Value *);
64 Instruction *mkMovFromReg(Value *, int id);
65
66 Instruction *mkInterp(unsigned mode, Value *, int32_t offset, Value *rel);
67 Instruction *mkFetch(Value *, DataType, DataFile, int32_t offset,
68 Value *attrRel, Value *primRel);
69
70 Instruction *mkCvt(operation, DataType, Value *, DataType, Value *);
71 Instruction *mkCmp(operation, CondCode, DataType,
72 Value *,
73 Value *, Value *, Value * = NULL);
74 Instruction *mkTex(operation, TexTarget, uint8_t tic, uint8_t tsc,
75 Value **def, Value **src);
76 Instruction *mkQuadop(uint8_t qop, Value *, uint8_t l, Value *, Value *);
77
78 FlowInstruction *mkFlow(operation, BasicBlock *target,
79 CondCode, Value *pred);
80
81 Instruction *mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc);
82
83 void mkClobber(DataFile file, uint32_t regMask, int regUnitLog2);
84
85 ImmediateValue *mkImm(float);
86 ImmediateValue *mkImm(uint32_t);
87 ImmediateValue *mkImm(uint64_t);
88
89 ImmediateValue *mkImm(int i) { return mkImm((uint32_t)i); }
90
91 Value *loadImm(Value *dst, float);
92 Value *loadImm(Value *dst, uint32_t);
93 Value *loadImm(Value *dst, uint64_t);
94
95 Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
96
97 class DataArray
98 {
99 public:
100 DataArray();
101 DataArray(BuildUtil *);
102 ~DataArray();
103
104 inline void setParent(BuildUtil *bld) { assert(!up); up = bld; }
105
106 void setup(uint32_t base, int len, int vecDim, int size,
107 DataFile, int8_t fileIndex = 0);
108
109 inline bool exists(unsigned int i, unsigned int c);
110
111 Value *load(int i, int c, Value *ptr);
112 void store(int i, int c, Value *ptr, Value *value);
113 Value *acquire(int i, int c);
114
115 private:
116 Symbol *mkSymbol(int i, int c, Symbol *base);
117
118 private:
119 Value **values;
120 uint32_t baseAddr;
121 uint32_t arrayLen;
122 Symbol *baseSym;
123
124 uint8_t vecDim;
125 uint8_t eltSize; // in bytes
126
127 DataFile file;
128 bool regOnly;
129
130 BuildUtil *up;
131
132 void init();
133 };
134
135 Symbol *mkSymbol(DataFile file, int8_t fileIndex,
136 DataType ty, uint32_t baseAddress);
137
138 Symbol *mkSysVal(SVSemantic svName, uint32_t svIndex);
139
140 private:
141 void addImmediate(ImmediateValue *);
142 inline unsigned int u32Hash(uint32_t);
143
144 protected:
145 Program *prog;
146 Function *func;
147 Instruction *pos;
148 BasicBlock *bb;
149 bool tail;
150
151 #define NV50_IR_BUILD_IMM_HT_SIZE 256
152
153 ImmediateValue *imms[NV50_IR_BUILD_IMM_HT_SIZE];
154 unsigned int immCount;
155 };
156
157 unsigned int BuildUtil::u32Hash(uint32_t u)
158 {
159 return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE;
160 }
161
162 void BuildUtil::setProgram(Program *program)
163 {
164 prog = program;
165 }
166
167 void
168 BuildUtil::setPosition(BasicBlock *block, bool atTail)
169 {
170 bb = block;
171 prog = bb->getProgram();
172 func = bb->getFunction();
173 pos = NULL;
174 tail = atTail;
175 }
176
177 void
178 BuildUtil::setPosition(Instruction *i, bool after)
179 {
180 bb = i->bb;
181 prog = bb->getProgram();
182 func = bb->getFunction();
183 pos = i;
184 tail = after;
185 assert(bb);
186 }
187
188 LValue *
189 BuildUtil::getScratch(int size)
190 {
191 LValue *lval = new_LValue(func, FILE_GPR);
192 if (size != 4)
193 lval->reg.size = size;
194 return lval;
195 }
196
197 LValue *
198 BuildUtil::getSSA(int size)
199 {
200 LValue *lval = new_LValue(func, FILE_GPR);
201 lval->ssa = 1;
202 if (size != 4)
203 lval->reg.size = size;
204 return lval;
205 }
206
207 void BuildUtil::insert(Instruction *i)
208 {
209 if (!pos) {
210 tail ? bb->insertTail(i) : bb->insertHead(i);
211 } else {
212 if (tail) {
213 bb->insertAfter(pos, i);
214 pos = i;
215 } else {
216 bb->insertBefore(pos, i);
217 }
218 }
219 }
220
221 Instruction *
222 BuildUtil::mkOp(operation op, DataType ty, Value *dst)
223 {
224 Instruction *insn = new_Instruction(func, op, ty);
225 insn->setDef(0, dst);
226 insert(insn);
227 if (op == OP_DISCARD || op == OP_EXIT ||
228 op == OP_JOIN ||
229 op == OP_QUADON || op == OP_QUADPOP ||
230 op == OP_EMIT || op == OP_RESTART)
231 insn->fixed = 1;
232 return insn;
233 }
234
235 inline LValue *
236 BuildUtil::mkOp1v(operation op, DataType ty, Value *dst, Value *src)
237 {
238 mkOp1(op, ty, dst, src);
239 return dst->asLValue();
240 }
241
242 inline LValue *
243 BuildUtil::mkOp2v(operation op, DataType ty, Value *dst,
244 Value *src0, Value *src1)
245 {
246 mkOp2(op, ty, dst, src0, src1);
247 return dst->asLValue();
248 }
249
250 inline LValue *
251 BuildUtil::mkOp3v(operation op, DataType ty, Value *dst,
252 Value *src0, Value *src1, Value *src2)
253 {
254 mkOp3(op, ty, dst, src0, src1, src2);
255 return dst->asLValue();
256 }
257
258 bool
259 BuildUtil::DataArray::exists(unsigned int i, unsigned int c)
260 {
261 assert(i < arrayLen && c < vecDim);
262 return !regOnly || values[i * vecDim + c];
263 }
264
265 } // namespace nv50_ir
266
267 #endif // __NV50_IR_BUILD_UTIL_H__