Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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. #include "nv50_ir.h"
  24. #include "nv50_ir_build_util.h"
  25.  
  26. namespace nv50_ir {
  27.  
  28. BuildUtil::BuildUtil()
  29. {
  30.    init(NULL);
  31. }
  32.  
  33. BuildUtil::BuildUtil(Program *prog)
  34. {
  35.    init(prog);
  36. }
  37.  
  38. void
  39. BuildUtil::init(Program *prog)
  40. {
  41.    this->prog = prog;
  42.  
  43.    func = NULL;
  44.    bb = NULL;
  45.    pos = NULL;
  46.  
  47.    memset(imms, 0, sizeof(imms));
  48.    immCount = 0;
  49. }
  50.  
  51. void
  52. BuildUtil::addImmediate(ImmediateValue *imm)
  53. {
  54.    if (immCount > (NV50_IR_BUILD_IMM_HT_SIZE * 3) / 4)
  55.       return;
  56.  
  57.    unsigned int pos = u32Hash(imm->reg.data.u32);
  58.  
  59.    while (imms[pos])
  60.       pos = (pos + 1) % NV50_IR_BUILD_IMM_HT_SIZE;
  61.    imms[pos] = imm;
  62.    immCount++;
  63. }
  64.  
  65. Instruction *
  66. BuildUtil::mkOp1(operation op, DataType ty, Value *dst, Value *src)
  67. {
  68.    Instruction *insn = new_Instruction(func, op, ty);
  69.  
  70.    insn->setDef(0, dst);
  71.    insn->setSrc(0, src);
  72.  
  73.    insert(insn);
  74.    return insn;
  75. }
  76.  
  77. Instruction *
  78. BuildUtil::mkOp2(operation op, DataType ty, Value *dst,
  79.                  Value *src0, Value *src1)
  80. {
  81.    Instruction *insn = new_Instruction(func, op, ty);
  82.  
  83.    insn->setDef(0, dst);
  84.    insn->setSrc(0, src0);
  85.    insn->setSrc(1, src1);
  86.  
  87.    insert(insn);
  88.    return insn;
  89. }
  90.  
  91. Instruction *
  92. BuildUtil::mkOp3(operation op, DataType ty, Value *dst,
  93.                  Value *src0, Value *src1, Value *src2)
  94. {
  95.    Instruction *insn = new_Instruction(func, op, ty);
  96.  
  97.    insn->setDef(0, dst);
  98.    insn->setSrc(0, src0);
  99.    insn->setSrc(1, src1);
  100.    insn->setSrc(2, src2);
  101.  
  102.    insert(insn);
  103.    return insn;
  104. }
  105.  
  106. Instruction *
  107. BuildUtil::mkLoad(DataType ty, Value *dst, Symbol *mem, Value *ptr)
  108. {
  109.    Instruction *insn = new_Instruction(func, OP_LOAD, ty);
  110.  
  111.    insn->setDef(0, dst);
  112.    insn->setSrc(0, mem);
  113.    if (ptr)
  114.       insn->setIndirect(0, 0, ptr);
  115.  
  116.    insert(insn);
  117.    return insn;
  118. }
  119.  
  120. Instruction *
  121. BuildUtil::mkStore(operation op, DataType ty, Symbol *mem, Value *ptr,
  122.                    Value *stVal)
  123. {
  124.    Instruction *insn = new_Instruction(func, op, ty);
  125.  
  126.    insn->setSrc(0, mem);
  127.    insn->setSrc(1, stVal);
  128.    if (ptr)
  129.       insn->setIndirect(0, 0, ptr);
  130.  
  131.    insert(insn);
  132.    return insn;
  133. }
  134.  
  135. Instruction *
  136. BuildUtil::mkFetch(Value *dst, DataType ty, DataFile file, int32_t offset,
  137.                    Value *attrRel, Value *primRel)
  138. {
  139.    Symbol *sym = mkSymbol(file, 0, ty, offset);
  140.  
  141.    Instruction *insn = mkOp1(OP_VFETCH, ty, dst, sym);
  142.  
  143.    insn->setIndirect(0, 0, attrRel);
  144.    insn->setIndirect(0, 1, primRel);
  145.  
  146.    // already inserted
  147.    return insn;
  148. }
  149.  
  150. Instruction *
  151. BuildUtil::mkInterp(unsigned mode, Value *dst, int32_t offset, Value *rel)
  152. {
  153.    operation op = OP_LINTERP;
  154.    DataType ty = TYPE_F32;
  155.  
  156.    if ((mode & NV50_IR_INTERP_MODE_MASK) == NV50_IR_INTERP_FLAT)
  157.       ty = TYPE_U32;
  158.    else
  159.    if ((mode & NV50_IR_INTERP_MODE_MASK) == NV50_IR_INTERP_PERSPECTIVE)
  160.       op = OP_PINTERP;
  161.  
  162.    Symbol *sym = mkSymbol(FILE_SHADER_INPUT, 0, ty, offset);
  163.  
  164.    Instruction *insn = mkOp1(op, ty, dst, sym);
  165.    insn->setIndirect(0, 0, rel);
  166.    return insn;
  167. }
  168.  
  169. Instruction *
  170. BuildUtil::mkMov(Value *dst, Value *src, DataType ty)
  171. {
  172.    Instruction *insn = new_Instruction(func, OP_MOV, ty);
  173.  
  174.    insn->setDef(0, dst);
  175.    insn->setSrc(0, src);
  176.  
  177.    insert(insn);
  178.    return insn;
  179. }
  180.  
  181. Instruction *
  182. BuildUtil::mkMovToReg(int id, Value *src)
  183. {
  184.    Instruction *insn = new_Instruction(func, OP_MOV, typeOfSize(src->reg.size));
  185.  
  186.    insn->setDef(0, new_LValue(func, FILE_GPR));
  187.    insn->getDef(0)->reg.data.id = id;
  188.    insn->setSrc(0, src);
  189.  
  190.    insert(insn);
  191.    return insn;
  192. }
  193.  
  194. Instruction *
  195. BuildUtil::mkMovFromReg(Value *dst, int id)
  196. {
  197.    Instruction *insn = new_Instruction(func, OP_MOV, typeOfSize(dst->reg.size));
  198.  
  199.    insn->setDef(0, dst);
  200.    insn->setSrc(0, new_LValue(func, FILE_GPR));
  201.    insn->getSrc(0)->reg.data.id = id;
  202.  
  203.    insert(insn);
  204.    return insn;
  205. }
  206.  
  207. Instruction *
  208. BuildUtil::mkCvt(operation op,
  209.                  DataType dstTy, Value *dst, DataType srcTy, Value *src)
  210. {
  211.    Instruction *insn = new_Instruction(func, op, dstTy);
  212.  
  213.    insn->setType(dstTy, srcTy);
  214.    insn->setDef(0, dst);
  215.    insn->setSrc(0, src);
  216.  
  217.    insert(insn);
  218.    return insn;
  219. }
  220.  
  221. CmpInstruction *
  222. BuildUtil::mkCmp(operation op, CondCode cc, DataType ty, Value *dst,
  223.                  Value *src0, Value *src1, Value *src2)
  224. {
  225.    CmpInstruction *insn = new_CmpInstruction(func, op);
  226.  
  227.    insn->setType((dst->reg.file == FILE_PREDICATE ||
  228.                   dst->reg.file == FILE_FLAGS) ? TYPE_U8 : ty, ty);
  229.    insn->setCondition(cc);
  230.    insn->setDef(0, dst);
  231.    insn->setSrc(0, src0);
  232.    insn->setSrc(1, src1);
  233.    if (src2)
  234.       insn->setSrc(2, src2);
  235.  
  236.    if (dst->reg.file == FILE_FLAGS)
  237.       insn->flagsDef = 0;
  238.  
  239.    insert(insn);
  240.    return insn;
  241. }
  242.  
  243. TexInstruction *
  244. BuildUtil::mkTex(operation op, TexTarget targ,
  245.                  uint16_t tic, uint16_t tsc,
  246.                  const std::vector<Value *> &def,
  247.                  const std::vector<Value *> &src)
  248. {
  249.    TexInstruction *tex = new_TexInstruction(func, op);
  250.  
  251.    for (size_t d = 0; d < def.size() && def[d]; ++d)
  252.       tex->setDef(d, def[d]);
  253.    for (size_t s = 0; s < src.size() && src[s]; ++s)
  254.       tex->setSrc(s, src[s]);
  255.  
  256.    tex->setTexture(targ, tic, tsc);
  257.  
  258.    insert(tex);
  259.    return tex;
  260. }
  261.  
  262. Instruction *
  263. BuildUtil::mkQuadop(uint8_t q, Value *def, uint8_t l, Value *src0, Value *src1)
  264. {
  265.    Instruction *quadop = mkOp2(OP_QUADOP, TYPE_F32, def, src0, src1);
  266.    quadop->subOp = q;
  267.    quadop->lanes = l;
  268.    return quadop;
  269. }
  270.  
  271. Instruction *
  272. BuildUtil::mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc)
  273. {
  274.    LValue *def0 = getSSA();
  275.    LValue *def1 = getSSA();
  276.  
  277.    mkMov(def0, trSrc)->setPredicate(CC_P, pred);
  278.    mkMov(def1, flSrc)->setPredicate(CC_NOT_P, pred);
  279.  
  280.    return mkOp2(OP_UNION, typeOfSize(dst->reg.size), dst, def0, def1);
  281. }
  282.  
  283. Instruction *
  284. BuildUtil::mkSplit(Value *h[2], uint8_t halfSize, Value *val)
  285. {
  286.    Instruction *insn = NULL;
  287.  
  288.    const DataType fTy = typeOfSize(halfSize * 2);
  289.  
  290.    if (val->reg.file == FILE_IMMEDIATE)
  291.       val = mkMov(getSSA(halfSize * 2), val, fTy)->getDef(0);
  292.  
  293.    if (isMemoryFile(val->reg.file)) {
  294.       h[0] = cloneShallow(getFunction(), val);
  295.       h[1] = cloneShallow(getFunction(), val);
  296.       h[0]->reg.size = halfSize;
  297.       h[1]->reg.size = halfSize;
  298.       h[1]->reg.data.offset += halfSize;
  299.    } else {
  300.       h[0] = getSSA(halfSize, val->reg.file);
  301.       h[1] = getSSA(halfSize, val->reg.file);
  302.       insn = mkOp1(OP_SPLIT, fTy, h[0], val);
  303.       insn->setDef(1, h[1]);
  304.    }
  305.    return insn;
  306. }
  307.  
  308. FlowInstruction *
  309. BuildUtil::mkFlow(operation op, void *targ, CondCode cc, Value *pred)
  310. {
  311.    FlowInstruction *insn = new_FlowInstruction(func, op, targ);
  312.  
  313.    if (pred)
  314.       insn->setPredicate(cc, pred);
  315.  
  316.    insert(insn);
  317.    return insn;
  318. }
  319.  
  320. void
  321. BuildUtil::mkClobber(DataFile f, uint32_t rMask, int unit)
  322. {
  323.    static const uint16_t baseSize2[16] =
  324.    {
  325.       0x0000, 0x0010, 0x0011, 0x0020, 0x0012, 0x1210, 0x1211, 0x1220,
  326.       0x0013, 0x1310, 0x1311, 0x1320, 0x0022, 0x2210, 0x2211, 0x0040,
  327.    };
  328.  
  329.    int base = 0;
  330.  
  331.    for (; rMask; rMask >>= 4, base += 4) {
  332.       const uint32_t mask = rMask & 0xf;
  333.       if (!mask)
  334.          continue;
  335.       int base1 = (baseSize2[mask] >>  0) & 0xf;
  336.       int size1 = (baseSize2[mask] >>  4) & 0xf;
  337.       int base2 = (baseSize2[mask] >>  8) & 0xf;
  338.       int size2 = (baseSize2[mask] >> 12) & 0xf;
  339.       Instruction *insn = mkOp(OP_NOP, TYPE_NONE, NULL);
  340.       if (1) { // size1 can't be 0
  341.          LValue *reg = new_LValue(func, f);
  342.          reg->reg.size = size1 << unit;
  343.          reg->reg.data.id = base + base1;
  344.          insn->setDef(0, reg);
  345.       }
  346.       if (size2) {
  347.          LValue *reg = new_LValue(func, f);
  348.          reg->reg.size = size2 << unit;
  349.          reg->reg.data.id = base + base2;
  350.          insn->setDef(1, reg);
  351.       }
  352.    }
  353. }
  354.  
  355. ImmediateValue *
  356. BuildUtil::mkImm(uint32_t u)
  357. {
  358.    unsigned int pos = u32Hash(u);
  359.  
  360.    while (imms[pos] && imms[pos]->reg.data.u32 != u)
  361.       pos = (pos + 1) % NV50_IR_BUILD_IMM_HT_SIZE;
  362.  
  363.    ImmediateValue *imm = imms[pos];
  364.    if (!imm) {
  365.       imm = new_ImmediateValue(prog, u);
  366.       addImmediate(imm);
  367.    }
  368.    return imm;
  369. }
  370.  
  371. ImmediateValue *
  372. BuildUtil::mkImm(uint64_t u)
  373. {
  374.    ImmediateValue *imm = new_ImmediateValue(prog, (uint32_t)0);
  375.  
  376.    imm->reg.size = 8;
  377.    imm->reg.type = TYPE_U64;
  378.    imm->reg.data.u64 = u;
  379.  
  380.    return imm;
  381. }
  382.  
  383. ImmediateValue *
  384. BuildUtil::mkImm(float f)
  385. {
  386.    union {
  387.       float f32;
  388.       uint32_t u32;
  389.    } u;
  390.    u.f32 = f;
  391.    return mkImm(u.u32);
  392. }
  393.  
  394. Value *
  395. BuildUtil::loadImm(Value *dst, float f)
  396. {
  397.    return mkOp1v(OP_MOV, TYPE_F32, dst ? dst : getScratch(), mkImm(f));
  398. }
  399.  
  400. Value *
  401. BuildUtil::loadImm(Value *dst, uint32_t u)
  402. {
  403.    return mkOp1v(OP_MOV, TYPE_U32, dst ? dst : getScratch(), mkImm(u));
  404. }
  405.  
  406. Value *
  407. BuildUtil::loadImm(Value *dst, uint64_t u)
  408. {
  409.    return mkOp1v(OP_MOV, TYPE_U64, dst ? dst : getScratch(8), mkImm(u));
  410. }
  411.  
  412. Symbol *
  413. BuildUtil::mkSymbol(DataFile file, int8_t fileIndex, DataType ty,
  414.                     uint32_t baseAddr)
  415. {
  416.    Symbol *sym = new_Symbol(prog, file, fileIndex);
  417.  
  418.    sym->setOffset(baseAddr);
  419.    sym->reg.type = ty;
  420.    sym->reg.size = typeSizeof(ty);
  421.  
  422.    return sym;
  423. }
  424.  
  425. Symbol *
  426. BuildUtil::mkSysVal(SVSemantic svName, uint32_t svIndex)
  427. {
  428.    Symbol *sym = new_Symbol(prog, FILE_SYSTEM_VALUE, 0);
  429.  
  430.    assert(svIndex < 4 ||
  431.           (svName == SV_CLIP_DISTANCE || svName == SV_TESS_FACTOR));
  432.  
  433.    switch (svName) {
  434.    case SV_POSITION:
  435.    case SV_FACE:
  436.    case SV_YDIR:
  437.    case SV_POINT_SIZE:
  438.    case SV_POINT_COORD:
  439.    case SV_CLIP_DISTANCE:
  440.    case SV_TESS_FACTOR:
  441.       sym->reg.type = TYPE_F32;
  442.       break;
  443.    default:
  444.       sym->reg.type = TYPE_U32;
  445.       break;
  446.    }
  447.    sym->reg.size = typeSizeof(sym->reg.type);
  448.  
  449.    sym->reg.data.sv.sv = svName;
  450.    sym->reg.data.sv.index = svIndex;
  451.  
  452.    return sym;
  453. }
  454.  
  455. void
  456. BuildUtil::DataArray::setup(unsigned array, unsigned arrayIdx,
  457.                             uint32_t base, int len, int vecDim, int eltSize,
  458.                             DataFile file, int8_t fileIdx)
  459. {
  460.    this->array = array;
  461.    this->arrayIdx = arrayIdx;
  462.    this->baseAddr = base;
  463.    this->arrayLen = len;
  464.    this->vecDim = vecDim;
  465.    this->eltSize = eltSize;
  466.    this->file = file;
  467.    this->regOnly = !isMemoryFile(file);
  468.  
  469.    if (!regOnly) {
  470.       baseSym = new_Symbol(up->getProgram(), file, fileIdx);
  471.       baseSym->setOffset(baseAddr);
  472.       baseSym->reg.size = eltSize;
  473.    } else {
  474.       baseSym = NULL;
  475.    }
  476. }
  477.  
  478. Value *
  479. BuildUtil::DataArray::acquire(ValueMap &m, int i, int c)
  480. {
  481.    if (regOnly) {
  482.       Value *v = lookup(m, i, c);
  483.       if (!v)
  484.          v = insert(m, i, c, new_LValue(up->getFunction(), file));
  485.  
  486.       return v;
  487.    } else {
  488.       return up->getScratch();
  489.    }
  490. }
  491.  
  492. Value *
  493. BuildUtil::DataArray::load(ValueMap &m, int i, int c, Value *ptr)
  494. {
  495.    if (regOnly) {
  496.       Value *v = lookup(m, i, c);
  497.       if (!v)
  498.          v = insert(m, i, c, new_LValue(up->getFunction(), file));
  499.  
  500.       return v;
  501.    } else {
  502.       Value *sym = lookup(m, i, c);
  503.       if (!sym)
  504.          sym = insert(m, i, c, mkSymbol(i, c));
  505.  
  506.       return up->mkLoadv(typeOfSize(eltSize), static_cast<Symbol *>(sym), ptr);
  507.    }
  508. }
  509.  
  510. void
  511. BuildUtil::DataArray::store(ValueMap &m, int i, int c, Value *ptr, Value *value)
  512. {
  513.    if (regOnly) {
  514.       assert(!ptr);
  515.       if (!lookup(m, i, c))
  516.          insert(m, i, c, value);
  517.  
  518.       assert(lookup(m, i, c) == value);
  519.    } else {
  520.       Value *sym = lookup(m, i, c);
  521.       if (!sym)
  522.          sym = insert(m, i, c, mkSymbol(i, c));
  523.  
  524.       const DataType stTy = typeOfSize(value->reg.size);
  525.  
  526.       up->mkStore(OP_STORE, stTy, static_cast<Symbol *>(sym), ptr, value);
  527.    }
  528. }
  529.  
  530. Symbol *
  531. BuildUtil::DataArray::mkSymbol(int i, int c)
  532. {
  533.    const unsigned int idx = i * vecDim + c;
  534.    Symbol *sym = new_Symbol(up->getProgram(), file, 0);
  535.  
  536.    assert(baseSym || (idx < arrayLen && c < vecDim));
  537.  
  538.    sym->reg.size = eltSize;
  539.    sym->reg.type = typeOfSize(eltSize);
  540.    sym->setAddress(baseSym, baseAddr + idx * eltSize);
  541.    return sym;
  542. }
  543.  
  544.  
  545. Instruction *
  546. BuildUtil::split64BitOpPostRA(Function *fn, Instruction *i,
  547.                               Value *zero,
  548.                               Value *carry)
  549. {
  550.    DataType hTy;
  551.    int srcNr;
  552.  
  553.    switch (i->dType) {
  554.    case TYPE_U64: hTy = TYPE_U32; break;
  555.    case TYPE_S64: hTy = TYPE_S32; break;
  556.    default:
  557.       return NULL;
  558.    }
  559.  
  560.    switch (i->op) {
  561.    case OP_MOV: srcNr = 1; break;
  562.    case OP_ADD:
  563.    case OP_SUB:
  564.       if (!carry)
  565.          return NULL;
  566.       srcNr = 2;
  567.       break;
  568.    default:
  569.       // TODO when needed
  570.       return NULL;
  571.    }
  572.  
  573.    i->setType(hTy);
  574.    i->setDef(0, cloneShallow(fn, i->getDef(0)));
  575.    i->getDef(0)->reg.size = 4;
  576.    Instruction *lo = i;
  577.    Instruction *hi = cloneForward(fn, i);
  578.    lo->bb->insertAfter(lo, hi);
  579.  
  580.    hi->getDef(0)->reg.data.id++;
  581.  
  582.    for (int s = 0; s < srcNr; ++s) {
  583.       if (lo->getSrc(s)->reg.size < 8) {
  584.          hi->setSrc(s, zero);
  585.       } else {
  586.          if (lo->getSrc(s)->refCount() > 1)
  587.             lo->setSrc(s, cloneShallow(fn, lo->getSrc(s)));
  588.          lo->getSrc(s)->reg.size /= 2;
  589.          hi->setSrc(s, cloneShallow(fn, lo->getSrc(s)));
  590.  
  591.          switch (hi->src(s).getFile()) {
  592.          case FILE_IMMEDIATE:
  593.             hi->getSrc(s)->reg.data.u64 >>= 32;
  594.             break;
  595.          case FILE_MEMORY_CONST:
  596.          case FILE_MEMORY_SHARED:
  597.          case FILE_SHADER_INPUT:
  598.             hi->getSrc(s)->reg.data.offset += 4;
  599.             break;
  600.          default:
  601.             assert(hi->src(s).getFile() == FILE_GPR);
  602.             hi->getSrc(s)->reg.data.id++;
  603.             break;
  604.          }
  605.       }
  606.    }
  607.    if (srcNr == 2) {
  608.       lo->setDef(1, carry);
  609.       hi->setFlagsSrc(hi->srcCount(), carry);
  610.    }
  611.    return hi;
  612. }
  613.  
  614. } // namespace nv50_ir
  615.