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