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_INLINES_H__
     24 #define __NV50_IR_INLINES_H__
     25 
     26 static inline CondCode reverseCondCode(CondCode cc)
     27 {
     28    static const uint8_t ccRev[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
     29 
     30    return static_cast<CondCode>(ccRev[cc & 7] | (cc & ~7));
     31 }
     32 
     33 static inline CondCode inverseCondCode(CondCode cc)
     34 {
     35    return static_cast<CondCode>(cc ^ 7);
     36 }
     37 
     38 static inline bool isMemoryFile(DataFile f)
     39 {
     40    return (f >= FILE_MEMORY_CONST && f <= FILE_MEMORY_LOCAL);
     41 }
     42 
     43 // contrary to asTex(), this will never include SULD/SUST
     44 static inline bool isTextureOp(operation op)
     45 {
     46    return (op >= OP_TEX && op <= OP_TEXPREP);
     47 }
     48 
     49 static inline bool isSurfaceOp(operation op)
     50 {
     51    return (op >= OP_SULDB && op <= OP_SULEA) || (op == OP_SUQ);
     52 }
     53 
     54 static inline unsigned int typeSizeof(DataType ty)
     55 {
     56    switch (ty) {
     57    case TYPE_U8:
     58    case TYPE_S8:
     59       return 1;
     60    case TYPE_F16:
     61    case TYPE_U16:
     62    case TYPE_S16:
     63       return 2;
     64    case TYPE_F32:
     65    case TYPE_U32:
     66    case TYPE_S32:
     67       return 4;
     68    case TYPE_F64:
     69    case TYPE_U64:
     70    case TYPE_S64:
     71       return 8;
     72    case TYPE_B96:
     73       return 12;
     74    case TYPE_B128:
     75       return 16;
     76    default:
     77       return 0;
     78    }
     79 }
     80 
     81 static inline unsigned int typeSizeofLog2(DataType ty)
     82 {
     83    switch (ty) {
     84    case TYPE_F16:
     85    case TYPE_U16:
     86    case TYPE_S16:
     87       return 1;
     88    case TYPE_F32:
     89    case TYPE_U32:
     90    case TYPE_S32:
     91       return 2;
     92    case TYPE_F64:
     93    case TYPE_U64:
     94    case TYPE_S64:
     95       return 3;
     96    case TYPE_B96:
     97    case TYPE_B128:
     98       return 4;
     99    case TYPE_U8:
    100    case TYPE_S8:
    101    default:
    102       return 0;
    103    }
    104 }
    105 
    106 static inline DataType typeOfSize(unsigned int size,
    107                                   bool flt = false, bool sgn = false)
    108 {
    109    switch (size) {
    110    case 1: return sgn ? TYPE_S8 : TYPE_U8;
    111    case 2: return flt ? TYPE_F16 : (sgn ? TYPE_S16 : TYPE_U16);
    112    case 8: return flt ? TYPE_F64 : (sgn ? TYPE_S64 : TYPE_U64);
    113    case 12: return TYPE_B96;
    114    case 16: return TYPE_B128;
    115    case 4:
    116       return flt ? TYPE_F32 : (sgn ? TYPE_S32 : TYPE_U32);
    117    default:
    118       return TYPE_NONE;
    119    }
    120 }
    121 
    122 static inline bool isFloatType(DataType ty)
    123 {
    124    return (ty >= TYPE_F16 && ty <= TYPE_F64);
    125 }
    126 
    127 static inline bool isSignedIntType(DataType ty)
    128 {
    129    return (ty == TYPE_S8 || ty == TYPE_S16 || ty == TYPE_S32 || ty == TYPE_S64);
    130 }
    131 
    132 static inline bool isSignedType(DataType ty)
    133 {
    134    switch (ty) {
    135    case TYPE_NONE:
    136    case TYPE_U8:
    137    case TYPE_U16:
    138    case TYPE_U32:
    139    case TYPE_U64:
    140    case TYPE_B96:
    141    case TYPE_B128:
    142       return false;
    143    default:
    144       return true;
    145    }
    146 }
    147 
    148 static inline DataType intTypeToSigned(DataType ty)
    149 {
    150    switch (ty) {
    151    case TYPE_U64: return TYPE_S64;
    152    case TYPE_U32: return TYPE_S32;
    153    case TYPE_U16: return TYPE_S16;
    154    case TYPE_U8: return TYPE_S8;
    155    default:
    156       return ty;
    157    }
    158 }
    159 
    160 const ValueRef *ValueRef::getIndirect(int dim) const
    161 {
    162    return isIndirect(dim) ? &insn->src(indirect[dim]) : NULL;
    163 }
    164 
    165 DataFile ValueRef::getFile() const
    166 {
    167    return value ? value->reg.file : FILE_NULL;
    168 }
    169 
    170 unsigned int ValueRef::getSize() const
    171 {
    172    return value ? value->reg.size : 0;
    173 }
    174 
    175 Value *ValueRef::rep() const
    176 {
    177    assert(value);
    178    return value->join;
    179 }
    180 
    181 Value *ValueDef::rep() const
    182 {
    183    assert(value);
    184    return value->join;
    185 }
    186 
    187 DataFile ValueDef::getFile() const
    188 {
    189    return value ? value->reg.file : FILE_NULL;
    190 }
    191 
    192 unsigned int ValueDef::getSize() const
    193 {
    194    return value ? value->reg.size : 0;
    195 }
    196 
    197 void ValueDef::setSSA(LValue *lval)
    198 {
    199    origin = value->asLValue();
    200    set(lval);
    201 }
    202 
    203 const LValue *ValueDef::preSSA() const
    204 {
    205    return origin;
    206 }
    207 
    208 Instruction *Value::getInsn() const
    209 {
    210    return defs.empty() ? NULL : defs.front()->getInsn();
    211 }
    212 
    213 Instruction *Value::getUniqueInsn() const
    214 {
    215    if (defs.empty())
    216       return NULL;
    217 
    218    // after regalloc, the definitions of coalesced values are linked
    219    if (join != this) {
    220       for (DefCIterator it = defs.begin(); it != defs.end(); ++it)
    221          if ((*it)->get() == this)
    222             return (*it)->getInsn();
    223       // should be unreachable and trigger assertion at the end
    224    }
    225 #ifdef DEBUG
    226    if (reg.data.id < 0) {
    227       int n = 0;
    228       for (DefCIterator it = defs.begin(); n < 2 && it != defs.end(); ++it)
    229          if ((*it)->get() == this) // don't count joined values
    230             ++n;
    231       if (n > 1)
    232          WARN("value %%%i not uniquely defined\n", id); // return NULL ?
    233    }
    234 #endif
    235    assert(defs.front()->get() == this);
    236    return defs.front()->getInsn();
    237 }
    238 
    239 inline bool Instruction::constrainedDefs() const
    240 {
    241    return defExists(1) || op == OP_UNION;
    242 }
    243 
    244 Value *Instruction::getIndirect(int s, int dim) const
    245 {
    246    return srcs[s].isIndirect(dim) ? getSrc(srcs[s].indirect[dim]) : NULL;
    247 }
    248 
    249 Value *Instruction::getPredicate() const
    250 {
    251    return (predSrc >= 0) ? getSrc(predSrc) : NULL;
    252 }
    253 
    254 void Instruction::setFlagsDef(int d, Value *val)
    255 {
    256    if (val) {
    257       if (flagsDef < 0)
    258          flagsDef = d;
    259       setDef(flagsDef, val);
    260    } else {
    261       if (flagsDef >= 0) {
    262          setDef(flagsDef, NULL);
    263          flagsDef = -1;
    264       }
    265    }
    266 }
    267 
    268 void Instruction::setFlagsSrc(int s, Value *val)
    269 {
    270    flagsSrc = s;
    271    setSrc(flagsSrc, val);
    272 }
    273 
    274 Value *TexInstruction::getIndirectR() const
    275 {
    276    return tex.rIndirectSrc >= 0 ? getSrc(tex.rIndirectSrc) : NULL;
    277 }
    278 
    279 Value *TexInstruction::getIndirectS() const
    280 {
    281    return tex.rIndirectSrc >= 0 ? getSrc(tex.rIndirectSrc) : NULL;
    282 }
    283 
    284 CmpInstruction *Instruction::asCmp()
    285 {
    286    if (op >= OP_SET_AND && op <= OP_SLCT && op != OP_SELP)
    287       return static_cast<CmpInstruction *>(this);
    288    return NULL;
    289 }
    290 
    291 const CmpInstruction *Instruction::asCmp() const
    292 {
    293    if (op >= OP_SET_AND && op <= OP_SLCT && op != OP_SELP)
    294       return static_cast<const CmpInstruction *>(this);
    295    return NULL;
    296 }
    297 
    298 FlowInstruction *Instruction::asFlow()
    299 {
    300    if (op >= OP_BRA && op <= OP_JOIN)
    301       return static_cast<FlowInstruction *>(this);
    302    return NULL;
    303 }
    304 
    305 const FlowInstruction *Instruction::asFlow() const
    306 {
    307    if (op >= OP_BRA && op <= OP_JOIN)
    308       return static_cast<const FlowInstruction *>(this);
    309    return NULL;
    310 }
    311 
    312 TexInstruction *Instruction::asTex()
    313 {
    314    if ((op >= OP_TEX && op <= OP_SULEA) || op == OP_SUQ)
    315       return static_cast<TexInstruction *>(this);
    316    return NULL;
    317 }
    318 
    319 const TexInstruction *Instruction::asTex() const
    320 {
    321    if ((op >= OP_TEX && op <= OP_SULEA) || op == OP_SUQ)
    322       return static_cast<const TexInstruction *>(this);
    323    return NULL;
    324 }
    325 
    326 static inline Instruction *cloneForward(Function *ctx, Instruction *obj)
    327 {
    328    DeepClonePolicy<Function> pol(ctx);
    329 
    330    for (int i = 0; obj->srcExists(i); ++i)
    331       pol.set(obj->getSrc(i), obj->getSrc(i));
    332 
    333    return obj->clone(pol);
    334 }
    335 
    336 // XXX: use a virtual function so we're really really safe ?
    337 LValue *Value::asLValue()
    338 {
    339    if (reg.file >= FILE_GPR && reg.file <= FILE_ADDRESS)
    340       return static_cast<LValue *>(this);
    341    return NULL;
    342 }
    343 
    344 Symbol *Value::asSym()
    345 {
    346    if (reg.file >= FILE_MEMORY_CONST)
    347       return static_cast<Symbol *>(this);
    348    return NULL;
    349 }
    350 
    351 const Symbol *Value::asSym() const
    352 {
    353    if (reg.file >= FILE_MEMORY_CONST)
    354       return static_cast<const Symbol *>(this);
    355    return NULL;
    356 }
    357 
    358 void Symbol::setOffset(int32_t offset)
    359 {
    360    reg.data.offset = offset;
    361 }
    362 
    363 void Symbol::setAddress(Symbol *base, int32_t offset)
    364 {
    365    baseSym = base;
    366    reg.data.offset = offset;
    367 }
    368 
    369 void Symbol::setSV(SVSemantic sv, uint32_t index)
    370 {
    371    reg.data.sv.sv = sv;
    372    reg.data.sv.index = index;
    373 }
    374 
    375 ImmediateValue *Value::asImm()
    376 {
    377    if (reg.file == FILE_IMMEDIATE)
    378       return static_cast<ImmediateValue *>(this);
    379    return NULL;
    380 }
    381 
    382 const ImmediateValue *Value::asImm() const
    383 {
    384    if (reg.file == FILE_IMMEDIATE)
    385       return static_cast<const ImmediateValue *>(this);
    386    return NULL;
    387 }
    388 
    389 Value *Value::get(Iterator &it)
    390 {
    391    return reinterpret_cast<Value *>(it.get());
    392 }
    393 
    394 bool BasicBlock::reachableBy(const BasicBlock *by, const BasicBlock *term)
    395 {
    396    return cfg.reachableBy(&by->cfg, &term->cfg);
    397 }
    398 
    399 BasicBlock *BasicBlock::get(Iterator &iter)
    400 {
    401    return reinterpret_cast<BasicBlock *>(iter.get());
    402 }
    403 
    404 BasicBlock *BasicBlock::get(Graph::Node *node)
    405 {
    406    assert(node);
    407    return reinterpret_cast<BasicBlock *>(node->data);
    408 }
    409 
    410 Function *Function::get(Graph::Node *node)
    411 {
    412    assert(node);
    413    return reinterpret_cast<Function *>(node->data);
    414 }
    415 
    416 LValue *Function::getLValue(int id)
    417 {
    418    assert((unsigned int)id < (unsigned int)allLValues.getSize());
    419    return reinterpret_cast<LValue *>(allLValues.get(id));
    420 }
    421 
    422 #endif // __NV50_IR_INLINES_H__
    423