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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20  * OTHER DEALINGS IN THE 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    Instruction *mkLoad(DataType, Value *dst, Symbol *, Value *ptr);
     62    Instruction *mkStore(operation, DataType, Symbol *, Value *ptr, Value *val);
     63 
     64    LValue *mkLoadv(DataType, Symbol *, Value *ptr);
     65 
     66    Instruction *mkMov(Value *, Value *, DataType = TYPE_U32);
     67    Instruction *mkMovToReg(int id, Value *);
     68    Instruction *mkMovFromReg(Value *, int id);
     69 
     70    Instruction *mkInterp(unsigned mode, Value *, int32_t offset, Value *rel);
     71    Instruction *mkFetch(Value *, DataType, DataFile, int32_t offset,
     72                         Value *attrRel, Value *primRel);
     73 
     74    Instruction *mkCvt(operation, DataType, Value *, DataType, Value *);
     75    CmpInstruction *mkCmp(operation, CondCode, DataType,
     76                          Value *,
     77                          DataType, Value *, Value *, Value * = NULL);
     78    TexInstruction *mkTex(operation, TexTarget,
     79                          uint16_t tic, uint16_t tsc,
     80                          const std::vector<Value *> &def,
     81                          const std::vector<Value *> &src);
     82    Instruction *mkQuadop(uint8_t qop, Value *, uint8_t l, Value *, Value *);
     83 
     84    FlowInstruction *mkFlow(operation, void *target, CondCode, Value *pred);
     85 
     86    Instruction *mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc);
     87 
     88    Instruction *mkSplit(Value *half[2], uint8_t halfSize, Value *);
     89 
     90    void mkClobber(DataFile file, uint32_t regMask, int regUnitLog2);
     91 
     92    ImmediateValue *mkImm(float);
     93    ImmediateValue *mkImm(double);
     94    ImmediateValue *mkImm(uint32_t);
     95    ImmediateValue *mkImm(uint64_t);
     96 
     97    ImmediateValue *mkImm(int i) { return mkImm((uint32_t)i); }
     98 
     99    Value *loadImm(Value *dst, float);
    100    Value *loadImm(Value *dst, double);
    101    Value *loadImm(Value *dst, uint32_t);
    102    Value *loadImm(Value *dst, uint64_t);
    103 
    104    Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
    105 
    106    // returns high part of the operation
    107    static Instruction *split64BitOpPostRA(Function *, Instruction *,
    108                                           Value *zero, Value *carry);
    109 
    110    struct Location
    111    {
    112       Location(unsigned array, unsigned arrayIdx, unsigned i, unsigned c)
    113          : array(array), arrayIdx(arrayIdx), i(i), c(c) { }
    114       Location(const Location &l)
    115          : array(l.array), arrayIdx(l.arrayIdx), i(l.i), c(l.c) { }
    116 
    117       bool operator==(const Location &l) const
    118       {
    119          return
    120             array == l.array && arrayIdx == l.arrayIdx && i == l.i && c == l.c;
    121       }
    122 
    123       bool operator<(const Location &l) const
    124       {
    125          return array != l.array ? array < l.array :
    126             arrayIdx != l.arrayIdx ? arrayIdx < l.arrayIdx :
    127             i != l.i ? i < l.i :
    128             c != l.c ? c < l.c :
    129             false;
    130       }
    131 
    132       unsigned array, arrayIdx, i, c;
    133    };
    134 
    135    typedef bimap<Location, Value *> ValueMap;
    136 
    137    class DataArray
    138    {
    139    public:
    140       DataArray(BuildUtil *bld) : up(bld) { }
    141 
    142       void setup(unsigned array, unsigned arrayIdx,
    143                  uint32_t base, int len, int vecDim, int eltSize,
    144                  DataFile file, int8_t fileIdx);
    145 
    146       inline bool exists(ValueMap&, unsigned int i, unsigned int c);
    147 
    148       Value *load(ValueMap&, int i, int c, Value *ptr);
    149       void store(ValueMap&, int i, int c, Value *ptr, Value *value);
    150       Value *acquire(ValueMap&, int i, int c);
    151 
    152    private:
    153       inline Value *lookup(ValueMap&, unsigned i, unsigned c);
    154       inline Value *insert(ValueMap&, unsigned i, unsigned c, Value *v);
    155 
    156       Symbol *mkSymbol(int i, int c);
    157 
    158    private:
    159       BuildUtil *up;
    160       unsigned array, arrayIdx;
    161 
    162       uint32_t baseAddr;
    163       uint32_t arrayLen;
    164       Symbol *baseSym;
    165 
    166       uint8_t vecDim;
    167       uint8_t eltSize; // in bytes
    168 
    169       DataFile file;
    170       bool regOnly;
    171    };
    172 
    173    Symbol *mkSymbol(DataFile file, int8_t fileIndex,
    174                     DataType ty, uint32_t baseAddress);
    175 
    176    Symbol *mkSysVal(SVSemantic svName, uint32_t svIndex);
    177 
    178 private:
    179    void init(Program *);
    180    void addImmediate(ImmediateValue *);
    181    inline unsigned int u32Hash(uint32_t);
    182 
    183 protected:
    184    Program *prog;
    185    Function *func;
    186    Instruction *pos;
    187    BasicBlock *bb;
    188    bool tail;
    189 
    190 #define NV50_IR_BUILD_IMM_HT_SIZE 256
    191 
    192    ImmediateValue *imms[NV50_IR_BUILD_IMM_HT_SIZE];
    193    unsigned int immCount;
    194 };
    195 
    196 unsigned int BuildUtil::u32Hash(uint32_t u)
    197 {
    198    return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE;
    199 }
    200 
    201 void BuildUtil::setProgram(Program *program)
    202 {
    203    prog = program;
    204 }
    205 
    206 void
    207 BuildUtil::setPosition(BasicBlock *block, bool atTail)
    208 {
    209    bb = block;
    210    prog = bb->getProgram();
    211    func = bb->getFunction();
    212    pos = NULL;
    213    tail = atTail;
    214 }
    215 
    216 void
    217 BuildUtil::setPosition(Instruction *i, bool after)
    218 {
    219    bb = i->bb;
    220    prog = bb->getProgram();
    221    func = bb->getFunction();
    222    pos = i;
    223    tail = after;
    224    assert(bb);
    225 }
    226 
    227 LValue *
    228 BuildUtil::getScratch(int size, DataFile f)
    229 {
    230    LValue *lval = new_LValue(func, f);
    231    lval->reg.size = size;
    232    return lval;
    233 }
    234 
    235 LValue *
    236 BuildUtil::getSSA(int size, DataFile f)
    237 {
    238    LValue *lval = new_LValue(func, f);
    239    lval->ssa = 1;
    240    lval->reg.size = size;
    241    return lval;
    242 }
    243 
    244 void BuildUtil::insert(Instruction *i)
    245 {
    246    if (!pos) {
    247       tail ? bb->insertTail(i) : bb->insertHead(i);
    248    } else {
    249       if (tail) {
    250          bb->insertAfter(pos, i);
    251          pos = i;
    252       } else {
    253          bb->insertBefore(pos, i);
    254       }
    255    }
    256 }
    257 
    258 Instruction *
    259 BuildUtil::mkOp(operation op, DataType ty, Value *dst)
    260 {
    261    Instruction *insn = new_Instruction(func, op, ty);
    262    insn->setDef(0, dst);
    263    insert(insn);
    264    if (op == OP_DISCARD || op == OP_EXIT ||
    265        op == OP_JOIN ||
    266        op == OP_QUADON || op == OP_QUADPOP ||
    267        op == OP_EMIT || op == OP_RESTART)
    268       insn->fixed = 1;
    269    return insn;
    270 }
    271 
    272 inline LValue *
    273 BuildUtil::mkOp1v(operation op, DataType ty, Value *dst, Value *src)
    274 {
    275    mkOp1(op, ty, dst, src);
    276    return dst->asLValue();
    277 }
    278 
    279 inline LValue *
    280 BuildUtil::mkOp2v(operation op, DataType ty, Value *dst,
    281                   Value *src0, Value *src1)
    282 {
    283    mkOp2(op, ty, dst, src0, src1);
    284    return dst->asLValue();
    285 }
    286 
    287 inline LValue *
    288 BuildUtil::mkOp3v(operation op, DataType ty, Value *dst,
    289                   Value *src0, Value *src1, Value *src2)
    290 {
    291    mkOp3(op, ty, dst, src0, src1, src2);
    292    return dst->asLValue();
    293 }
    294 
    295 inline LValue *
    296 BuildUtil::mkLoadv(DataType ty, Symbol *mem, Value *ptr)
    297 {
    298    LValue *dst = getScratch(typeSizeof(ty));
    299    mkLoad(ty, dst, mem, ptr);
    300    return dst;
    301 }
    302 
    303 bool
    304 BuildUtil::DataArray::exists(ValueMap &m, unsigned int i, unsigned int c)
    305 {
    306    assert(i < arrayLen && c < vecDim);
    307    return !regOnly || m.r.count(Location(array, arrayIdx, i, c));
    308 }
    309 
    310 Value *
    311 BuildUtil::DataArray::lookup(ValueMap &m, unsigned i, unsigned c)
    312 {
    313    ValueMap::r_iterator it = m.r.find(Location(array, arrayIdx, i, c));
    314    return it != m.r.end() ? it->second : NULL;
    315 }
    316 
    317 Value *
    318 BuildUtil::DataArray::insert(ValueMap &m, unsigned i, unsigned c, Value *v)
    319 {
    320    m.insert(Location(array, arrayIdx, i, c), v);
    321    return v;
    322 }
    323 
    324 } // namespace nv50_ir
    325 
    326 #endif // __NV50_IR_BUILD_UTIL_H__
    327