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