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 *); 35 inline Program *getProgram() const { return prog; } 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 43 inline BasicBlock *getBB() { return bb; } 44 45 inline void insert(Instruction *); 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 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 98 Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); } 99 100 struct Location 101 { 102 Location(unsigned array, unsigned arrayIdx, unsigned i, unsigned c) 103 : array(array), arrayIdx(arrayIdx), i(i), c(c) { } 104 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: 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 186 unsigned int BuildUtil::u32Hash(uint32_t u) 187 { 188 return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE; 189 } 190 191 void BuildUtil::setProgram(Program *program) 192 { 193 prog = program; 194 } 195 196 void 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 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 * 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 * 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 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 * 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 * 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 * 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 * 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 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 * 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 * 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