Home | History | Annotate | Download | only in codegen
      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