Subversion Repositories Kolibri OS

Rev

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