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. #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(uint32_t);
  94.    ImmediateValue *mkImm(uint64_t);
  95.  
  96.    ImmediateValue *mkImm(int i) { return mkImm((uint32_t)i); }
  97.  
  98.    Value *loadImm(Value *dst, float);
  99.    Value *loadImm(Value *dst, uint32_t);
  100.    Value *loadImm(Value *dst, uint64_t);
  101.  
  102.    Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
  103.  
  104.    // returns high part of the operation
  105.    static Instruction *split64BitOpPostRA(Function *, Instruction *,
  106.                                           Value *zero, Value *carry);
  107.  
  108.    struct Location
  109.    {
  110.       Location(unsigned array, unsigned arrayIdx, unsigned i, unsigned c)
  111.          : array(array), arrayIdx(arrayIdx), i(i), c(c) { }
  112.       Location(const Location &l)
  113.          : array(l.array), arrayIdx(l.arrayIdx), i(l.i), c(l.c) { }
  114.  
  115.       bool operator==(const Location &l) const
  116.       {
  117.          return
  118.             array == l.array && arrayIdx == l.arrayIdx && i == l.i && c == l.c;
  119.       }
  120.  
  121.       bool operator<(const Location &l) const
  122.       {
  123.          return array != l.array ? array < l.array :
  124.             arrayIdx != l.arrayIdx ? arrayIdx < l.arrayIdx :
  125.             i != l.i ? i < l.i :
  126.             c != l.c ? c < l.c :
  127.             false;
  128.       }
  129.  
  130.       unsigned array, arrayIdx, i, c;
  131.    };
  132.  
  133.    typedef bimap<Location, Value *> ValueMap;
  134.  
  135.    class DataArray
  136.    {
  137.    public:
  138.       DataArray(BuildUtil *bld) : up(bld) { }
  139.  
  140.       void setup(unsigned array, unsigned arrayIdx,
  141.                  uint32_t base, int len, int vecDim, int eltSize,
  142.                  DataFile file, int8_t fileIdx);
  143.  
  144.       inline bool exists(ValueMap&, unsigned int i, unsigned int c);
  145.  
  146.       Value *load(ValueMap&, int i, int c, Value *ptr);
  147.       void store(ValueMap&, int i, int c, Value *ptr, Value *value);
  148.       Value *acquire(ValueMap&, int i, int c);
  149.  
  150.    private:
  151.       inline Value *lookup(ValueMap&, unsigned i, unsigned c);
  152.       inline Value *insert(ValueMap&, unsigned i, unsigned c, Value *v);
  153.  
  154.       Symbol *mkSymbol(int i, int c);
  155.  
  156.    private:
  157.       BuildUtil *up;
  158.       unsigned array, arrayIdx;
  159.  
  160.       uint32_t baseAddr;
  161.       uint32_t arrayLen;
  162.       Symbol *baseSym;
  163.  
  164.       uint8_t vecDim;
  165.       uint8_t eltSize; // in bytes
  166.  
  167.       DataFile file;
  168.       bool regOnly;
  169.    };
  170.  
  171.    Symbol *mkSymbol(DataFile file, int8_t fileIndex,
  172.                     DataType ty, uint32_t baseAddress);
  173.  
  174.    Symbol *mkSysVal(SVSemantic svName, uint32_t svIndex);
  175.  
  176. private:
  177.    void init(Program *);
  178.    void addImmediate(ImmediateValue *);
  179.    inline unsigned int u32Hash(uint32_t);
  180.  
  181. protected:
  182.    Program *prog;
  183.    Function *func;
  184.    Instruction *pos;
  185.    BasicBlock *bb;
  186.    bool tail;
  187.  
  188. #define NV50_IR_BUILD_IMM_HT_SIZE 256
  189.  
  190.    ImmediateValue *imms[NV50_IR_BUILD_IMM_HT_SIZE];
  191.    unsigned int immCount;
  192. };
  193.  
  194. unsigned int BuildUtil::u32Hash(uint32_t u)
  195. {
  196.    return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE;
  197. }
  198.  
  199. void BuildUtil::setProgram(Program *program)
  200. {
  201.    prog = program;
  202. }
  203.  
  204. void
  205. BuildUtil::setPosition(BasicBlock *block, bool atTail)
  206. {
  207.    bb = block;
  208.    prog = bb->getProgram();
  209.    func = bb->getFunction();
  210.    pos = NULL;
  211.    tail = atTail;
  212. }
  213.  
  214. void
  215. BuildUtil::setPosition(Instruction *i, bool after)
  216. {
  217.    bb = i->bb;
  218.    prog = bb->getProgram();
  219.    func = bb->getFunction();
  220.    pos = i;
  221.    tail = after;
  222.    assert(bb);
  223. }
  224.  
  225. LValue *
  226. BuildUtil::getScratch(int size, DataFile f)
  227. {
  228.    LValue *lval = new_LValue(func, f);
  229.    lval->reg.size = size;
  230.    return lval;
  231. }
  232.  
  233. LValue *
  234. BuildUtil::getSSA(int size, DataFile f)
  235. {
  236.    LValue *lval = new_LValue(func, f);
  237.    lval->ssa = 1;
  238.    lval->reg.size = size;
  239.    return lval;
  240. }
  241.  
  242. void BuildUtil::insert(Instruction *i)
  243. {
  244.    if (!pos) {
  245.       tail ? bb->insertTail(i) : bb->insertHead(i);
  246.    } else {
  247.       if (tail) {
  248.          bb->insertAfter(pos, i);
  249.          pos = i;
  250.       } else {
  251.          bb->insertBefore(pos, i);
  252.       }
  253.    }
  254. }
  255.  
  256. Instruction *
  257. BuildUtil::mkOp(operation op, DataType ty, Value *dst)
  258. {
  259.    Instruction *insn = new_Instruction(func, op, ty);
  260.    insn->setDef(0, dst);
  261.    insert(insn);
  262.    if (op == OP_DISCARD || op == OP_EXIT ||
  263.        op == OP_JOIN ||
  264.        op == OP_QUADON || op == OP_QUADPOP ||
  265.        op == OP_EMIT || op == OP_RESTART)
  266.       insn->fixed = 1;
  267.    return insn;
  268. }
  269.  
  270. inline LValue *
  271. BuildUtil::mkOp1v(operation op, DataType ty, Value *dst, Value *src)
  272. {
  273.    mkOp1(op, ty, dst, src);
  274.    return dst->asLValue();
  275. }
  276.  
  277. inline LValue *
  278. BuildUtil::mkOp2v(operation op, DataType ty, Value *dst,
  279.                   Value *src0, Value *src1)
  280. {
  281.    mkOp2(op, ty, dst, src0, src1);
  282.    return dst->asLValue();
  283. }
  284.  
  285. inline LValue *
  286. BuildUtil::mkOp3v(operation op, DataType ty, Value *dst,
  287.                   Value *src0, Value *src1, Value *src2)
  288. {
  289.    mkOp3(op, ty, dst, src0, src1, src2);
  290.    return dst->asLValue();
  291. }
  292.  
  293. inline LValue *
  294. BuildUtil::mkLoadv(DataType ty, Symbol *mem, Value *ptr)
  295. {
  296.    LValue *dst = getScratch();
  297.    mkLoad(ty, dst, mem, ptr);
  298.    return dst;
  299. }
  300.  
  301. bool
  302. BuildUtil::DataArray::exists(ValueMap &m, unsigned int i, unsigned int c)
  303. {
  304.    assert(i < arrayLen && c < vecDim);
  305.    return !regOnly || m.r.count(Location(array, arrayIdx, i, c));
  306. }
  307.  
  308. Value *
  309. BuildUtil::DataArray::lookup(ValueMap &m, unsigned i, unsigned c)
  310. {
  311.    ValueMap::r_iterator it = m.r.find(Location(array, arrayIdx, i, c));
  312.    return it != m.r.end() ? it->second : NULL;
  313. }
  314.  
  315. Value *
  316. BuildUtil::DataArray::insert(ValueMap &m, unsigned i, unsigned c, Value *v)
  317. {
  318.    m.insert(Location(array, arrayIdx, i, c), v);
  319.    return v;
  320. }
  321.  
  322. } // namespace nv50_ir
  323.  
  324. #endif // __NV50_IR_BUILD_UTIL_H__
  325.