OLD | NEW |
(Empty) | |
| 1 //===- subzero/src/IceInst.cpp - High-level instruction implementation ----===// |
| 2 // |
| 3 // The Subzero Code Generator |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // This file implements the IceInst class, primarily the various |
| 11 // subclass constructors and dump routines. |
| 12 // |
| 13 //===----------------------------------------------------------------------===// |
| 14 |
| 15 #include "IceCfg.h" |
| 16 #include "IceCfgNode.h" |
| 17 #include "IceInst.h" |
| 18 #include "IceOperand.h" |
| 19 |
| 20 IceInst::IceInst(IceCfg *Cfg, InstKind Kind, uint32_t MaxSrcs, |
| 21 IceVariable *Dest) |
| 22 : Kind(Kind), Deleted(false), HasSideEffects(false), Dest(Dest), |
| 23 MaxSrcs(MaxSrcs), NumSrcs(0) { |
| 24 Number = Cfg->newInstNumber(); |
| 25 Srcs = Cfg->allocateArrayOf<IceOperand *>(MaxSrcs); |
| 26 } |
| 27 |
| 28 void IceInst::updateVars(IceCfgNode *Node) { |
| 29 if (Dest) |
| 30 Dest->setDefinition(this, Node); |
| 31 for (uint32_t I = 0; I < getSrcSize(); ++I) { |
| 32 getSrc(I)->setUse(this, Node); |
| 33 } |
| 34 } |
| 35 |
| 36 IceInstAlloca::IceInstAlloca(IceCfg *Cfg, IceOperand *ByteCount, uint32_t Align, |
| 37 IceVariable *Dest) |
| 38 : IceInst(Cfg, IceInst::Alloca, 1, Dest), Align(Align) { |
| 39 addSource(ByteCount); |
| 40 } |
| 41 |
| 42 IceInstArithmetic::IceInstArithmetic(IceCfg *Cfg, OpKind Op, IceVariable *Dest, |
| 43 IceOperand *Source1, IceOperand *Source2) |
| 44 : IceInst(Cfg, IceInst::Arithmetic, 2, Dest), Op(Op) { |
| 45 addSource(Source1); |
| 46 addSource(Source2); |
| 47 } |
| 48 |
| 49 bool IceInstArithmetic::isCommutative() const { |
| 50 switch (getOp()) { |
| 51 case Add: |
| 52 case Fadd: |
| 53 case Mul: |
| 54 case Fmul: |
| 55 case And: |
| 56 case Or: |
| 57 case Xor: |
| 58 return true; |
| 59 default: |
| 60 return false; |
| 61 } |
| 62 } |
| 63 |
| 64 IceInstAssign::IceInstAssign(IceCfg *Cfg, IceVariable *Dest, IceOperand *Source) |
| 65 : IceInst(Cfg, IceInst::Assign, 1, Dest) { |
| 66 addSource(Source); |
| 67 } |
| 68 |
| 69 // If TargetTrue==TargetFalse, we turn it into an unconditional |
| 70 // branch. This ensures that, along with the 'switch' instruction |
| 71 // semantics, there is at most one edge from one node to another. |
| 72 IceInstBr::IceInstBr(IceCfg *Cfg, IceOperand *Source, IceCfgNode *TargetTrue, |
| 73 IceCfgNode *TargetFalse) |
| 74 : IceInst(Cfg, IceInst::Br, 1, NULL), TargetFalse(TargetFalse), |
| 75 TargetTrue(TargetTrue) { |
| 76 if (TargetTrue == TargetFalse) { |
| 77 TargetTrue = NULL; // turn into unconditional version |
| 78 } else { |
| 79 addSource(Source); |
| 80 } |
| 81 } |
| 82 |
| 83 IceInstBr::IceInstBr(IceCfg *Cfg, IceCfgNode *Target) |
| 84 : IceInst(Cfg, IceInst::Br, 0, NULL), TargetFalse(Target), |
| 85 TargetTrue(NULL) {} |
| 86 |
| 87 IceNodeList IceInstBr::getTerminatorEdges() const { |
| 88 IceNodeList OutEdges; |
| 89 OutEdges.push_back(TargetFalse); |
| 90 if (TargetTrue) |
| 91 OutEdges.push_back(TargetTrue); |
| 92 return OutEdges; |
| 93 } |
| 94 |
| 95 IceInstCast::IceInstCast(IceCfg *Cfg, OpKind CastKind, IceVariable *Dest, |
| 96 IceOperand *Source) |
| 97 : IceInst(Cfg, IceInst::Cast, 1, Dest), CastKind(CastKind) { |
| 98 addSource(Source); |
| 99 } |
| 100 |
| 101 IceInstFcmp::IceInstFcmp(IceCfg *Cfg, FCond Condition, IceVariable *Dest, |
| 102 IceOperand *Source1, IceOperand *Source2) |
| 103 : IceInst(Cfg, IceInst::Fcmp, 2, Dest), Condition(Condition) { |
| 104 addSource(Source1); |
| 105 addSource(Source2); |
| 106 } |
| 107 |
| 108 IceInstIcmp::IceInstIcmp(IceCfg *Cfg, ICond Condition, IceVariable *Dest, |
| 109 IceOperand *Source1, IceOperand *Source2) |
| 110 : IceInst(Cfg, IceInst::Icmp, 2, Dest), Condition(Condition) { |
| 111 addSource(Source1); |
| 112 addSource(Source2); |
| 113 } |
| 114 |
| 115 IceInstLoad::IceInstLoad(IceCfg *Cfg, IceVariable *Dest, IceOperand *SourceAddr) |
| 116 : IceInst(Cfg, IceInst::Load, 1, Dest) { |
| 117 addSource(SourceAddr); |
| 118 } |
| 119 |
| 120 IceInstPhi::IceInstPhi(IceCfg *Cfg, uint32_t MaxSrcs, IceVariable *Dest) |
| 121 : IceInst(Cfg, Phi, MaxSrcs, Dest) { |
| 122 Labels = Cfg->allocateArrayOf<IceCfgNode *>(MaxSrcs); |
| 123 } |
| 124 |
| 125 // TODO: A Switch instruction (and maybe others) can add duplicate |
| 126 // edges. We may want to de-dup Phis and validate consistency (i.e., |
| 127 // the source operands are the same for duplicate edges), though it |
| 128 // seems the current lowering code is OK with this situation. |
| 129 void IceInstPhi::addArgument(IceOperand *Source, IceCfgNode *Label) { |
| 130 Labels[getSrcSize()] = Label; |
| 131 addSource(Source); |
| 132 } |
| 133 |
| 134 IceInstRet::IceInstRet(IceCfg *Cfg, IceOperand *Source) |
| 135 : IceInst(Cfg, Ret, Source ? 1 : 0, NULL) { |
| 136 if (Source) |
| 137 addSource(Source); |
| 138 } |
| 139 |
| 140 IceInstSelect::IceInstSelect(IceCfg *Cfg, IceVariable *Dest, |
| 141 IceOperand *Condition, IceOperand *SourceTrue, |
| 142 IceOperand *SourceFalse) |
| 143 : IceInst(Cfg, IceInst::Select, 3, Dest) { |
| 144 assert(Condition->getType() == IceType_i1); |
| 145 addSource(Condition); |
| 146 addSource(SourceTrue); |
| 147 addSource(SourceFalse); |
| 148 } |
| 149 |
| 150 IceInstStore::IceInstStore(IceCfg *Cfg, IceOperand *Data, IceOperand *Addr) |
| 151 : IceInst(Cfg, IceInst::Store, 2, NULL) { |
| 152 addSource(Data); |
| 153 addSource(Addr); |
| 154 } |
| 155 |
| 156 IceInstSwitch::IceInstSwitch(IceCfg *Cfg, uint32_t NumCases, IceOperand *Source, |
| 157 IceCfgNode *LabelDefault) |
| 158 : IceInst(Cfg, IceInst::Switch, 1, NULL), LabelDefault(LabelDefault), |
| 159 NumCases(NumCases) { |
| 160 addSource(Source); |
| 161 Values = Cfg->allocateArrayOf<uint64_t>(NumCases); |
| 162 Labels = Cfg->allocateArrayOf<IceCfgNode *>(NumCases); |
| 163 // Initialize in case buggy code doesn't set all entries |
| 164 for (uint32_t I = 0; I < NumCases; ++I) { |
| 165 Values[I] = 0; |
| 166 Labels[I] = NULL; |
| 167 } |
| 168 } |
| 169 |
| 170 void IceInstSwitch::addBranch(uint32_t CaseIndex, uint64_t Value, |
| 171 IceCfgNode *Label) { |
| 172 assert(CaseIndex < NumCases); |
| 173 Values[CaseIndex] = Value; |
| 174 Labels[CaseIndex] = Label; |
| 175 } |
| 176 |
| 177 IceNodeList IceInstSwitch::getTerminatorEdges() const { |
| 178 IceNodeList OutEdges; |
| 179 OutEdges.push_back(LabelDefault); |
| 180 for (uint32_t I = 0; I < NumCases; ++I) { |
| 181 OutEdges.push_back(Labels[I]); |
| 182 } |
| 183 return OutEdges; |
| 184 } |
| 185 |
| 186 IceInstUnreachable::IceInstUnreachable(IceCfg *Cfg) |
| 187 : IceInst(Cfg, IceInst::Unreachable, 0, NULL) {} |
| 188 |
| 189 // ======================== Dump routines ======================== // |
| 190 |
| 191 IceOstream &operator<<(IceOstream &Str, const IceInst *I) { |
| 192 if (!Str.isVerbose(IceV_Deleted) && (I->isDeleted())) |
| 193 return Str; |
| 194 if (Str.isVerbose(IceV_InstNumbers)) { |
| 195 char buf[30]; |
| 196 int32_t Number = I->getNumber(); |
| 197 if (Number < 0) |
| 198 sprintf(buf, "[XXX]"); |
| 199 else |
| 200 sprintf(buf, "[%3d]", I->getNumber()); |
| 201 Str << buf; |
| 202 } |
| 203 Str << " "; |
| 204 if (I->isDeleted()) |
| 205 Str << " //"; |
| 206 I->dump(Str); |
| 207 Str << "\n"; |
| 208 return Str; |
| 209 } |
| 210 |
| 211 void IceInst::dump(IceOstream &Str) const { |
| 212 dumpDest(Str); |
| 213 Str << " =~ "; |
| 214 dumpSources(Str); |
| 215 } |
| 216 |
| 217 void IceInst::dumpSources(IceOstream &Str) const { |
| 218 for (uint32_t I = 0; I < getSrcSize(); ++I) { |
| 219 if (I > 0) |
| 220 Str << ", "; |
| 221 Str << getSrc(I); |
| 222 } |
| 223 } |
| 224 |
| 225 void IceInst::dumpDest(IceOstream &Str) const { |
| 226 if (getDest()) |
| 227 Str << getDest(); |
| 228 } |
| 229 |
| 230 void IceInstAlloca::dump(IceOstream &Str) const { |
| 231 dumpDest(Str); |
| 232 Str << " = alloca i8, i32 "; |
| 233 Str << getSrc(0) << ", align " << Align; |
| 234 } |
| 235 |
| 236 void IceInstArithmetic::dump(IceOstream &Str) const { |
| 237 dumpDest(Str); |
| 238 Str << " = "; |
| 239 switch (getOp()) { |
| 240 case Add: |
| 241 Str << "add"; |
| 242 break; |
| 243 case Fadd: |
| 244 Str << "fadd"; |
| 245 break; |
| 246 case Sub: |
| 247 Str << "sub"; |
| 248 break; |
| 249 case Fsub: |
| 250 Str << "fsub"; |
| 251 break; |
| 252 case Mul: |
| 253 Str << "mul"; |
| 254 break; |
| 255 case Fmul: |
| 256 Str << "fmul"; |
| 257 break; |
| 258 case Udiv: |
| 259 Str << "udiv"; |
| 260 break; |
| 261 case Sdiv: |
| 262 Str << "sdiv"; |
| 263 break; |
| 264 case Fdiv: |
| 265 Str << "fdiv"; |
| 266 break; |
| 267 case Urem: |
| 268 Str << "urem"; |
| 269 break; |
| 270 case Srem: |
| 271 Str << "srem"; |
| 272 break; |
| 273 case Frem: |
| 274 Str << "frem"; |
| 275 break; |
| 276 case Shl: |
| 277 Str << "shl"; |
| 278 break; |
| 279 case Lshr: |
| 280 Str << "lshr"; |
| 281 break; |
| 282 case Ashr: |
| 283 Str << "ashr"; |
| 284 break; |
| 285 case And: |
| 286 Str << "and"; |
| 287 break; |
| 288 case Or: |
| 289 Str << "or"; |
| 290 break; |
| 291 case Xor: |
| 292 Str << "xor"; |
| 293 break; |
| 294 } |
| 295 Str << " " << getDest()->getType() << " "; |
| 296 dumpSources(Str); |
| 297 } |
| 298 |
| 299 void IceInstAssign::dump(IceOstream &Str) const { |
| 300 dumpDest(Str); |
| 301 Str << " = " << getDest()->getType() << " "; |
| 302 dumpSources(Str); |
| 303 } |
| 304 |
| 305 void IceInstBr::dump(IceOstream &Str) const { |
| 306 dumpDest(Str); |
| 307 Str << "br "; |
| 308 if (!isUnconditional()) { |
| 309 Str << "i1 " << getSrc(0) << ", label %" << getTargetTrue()->getName() |
| 310 << ", "; |
| 311 } |
| 312 Str << "label %" << getTargetFalse()->getName(); |
| 313 } |
| 314 |
| 315 void IceInstCall::dump(IceOstream &Str) const { |
| 316 if (getDest()) { |
| 317 dumpDest(Str); |
| 318 Str << " = "; |
| 319 } |
| 320 if (Tail) |
| 321 Str << "tail "; |
| 322 Str << "call "; |
| 323 if (getDest()) |
| 324 Str << getDest()->getType(); |
| 325 else |
| 326 Str << "void"; |
| 327 Str << " " << getCallTarget() << "("; |
| 328 for (uint32_t I = 0; I < getNumArgs(); ++I) { |
| 329 if (I > 0) |
| 330 Str << ", "; |
| 331 Str << getArg(I)->getType() << " " << getArg(I); |
| 332 } |
| 333 Str << ")"; |
| 334 } |
| 335 |
| 336 void IceInstCast::dump(IceOstream &Str) const { |
| 337 dumpDest(Str); |
| 338 Str << " = "; |
| 339 switch (getCastKind()) { |
| 340 default: |
| 341 Str << "UNKNOWN"; |
| 342 assert(0); |
| 343 break; |
| 344 case Trunc: |
| 345 Str << "trunc"; |
| 346 break; |
| 347 case Zext: |
| 348 Str << "zext"; |
| 349 break; |
| 350 case Sext: |
| 351 Str << "sext"; |
| 352 break; |
| 353 case Fptrunc: |
| 354 Str << "fptrunc"; |
| 355 break; |
| 356 case Fpext: |
| 357 Str << "fpext"; |
| 358 break; |
| 359 case Fptoui: |
| 360 Str << "fptoui"; |
| 361 break; |
| 362 case Fptosi: |
| 363 Str << "fptosi"; |
| 364 break; |
| 365 case Uitofp: |
| 366 Str << "uitofp"; |
| 367 break; |
| 368 case Sitofp: |
| 369 Str << "sitofp"; |
| 370 break; |
| 371 case Bitcast: |
| 372 Str << "bitcast"; |
| 373 break; |
| 374 } |
| 375 Str << " " << getSrc(0)->getType() << " "; |
| 376 dumpSources(Str); |
| 377 Str << " to " << getDest()->getType(); |
| 378 } |
| 379 |
| 380 void IceInstIcmp::dump(IceOstream &Str) const { |
| 381 dumpDest(Str); |
| 382 Str << " = icmp "; |
| 383 switch (getCondition()) { |
| 384 case Eq: |
| 385 Str << "eq"; |
| 386 break; |
| 387 case Ne: |
| 388 Str << "ne"; |
| 389 break; |
| 390 case Ugt: |
| 391 Str << "ugt"; |
| 392 break; |
| 393 case Uge: |
| 394 Str << "uge"; |
| 395 break; |
| 396 case Ult: |
| 397 Str << "ult"; |
| 398 break; |
| 399 case Ule: |
| 400 Str << "ule"; |
| 401 break; |
| 402 case Sgt: |
| 403 Str << "sgt"; |
| 404 break; |
| 405 case Sge: |
| 406 Str << "sge"; |
| 407 break; |
| 408 case Slt: |
| 409 Str << "slt"; |
| 410 break; |
| 411 case Sle: |
| 412 Str << "sle"; |
| 413 break; |
| 414 } |
| 415 Str << " " << getSrc(0)->getType() << " "; |
| 416 dumpSources(Str); |
| 417 } |
| 418 |
| 419 void IceInstFcmp::dump(IceOstream &Str) const { |
| 420 dumpDest(Str); |
| 421 Str << " = fcmp "; |
| 422 |
| 423 switch (getCondition()) { |
| 424 case False: |
| 425 Str << "false"; |
| 426 break; |
| 427 case Oeq: |
| 428 Str << "oeq"; |
| 429 break; |
| 430 case Ogt: |
| 431 Str << "ogt"; |
| 432 break; |
| 433 case Oge: |
| 434 Str << "oge"; |
| 435 break; |
| 436 case Olt: |
| 437 Str << "olt"; |
| 438 break; |
| 439 case Ole: |
| 440 Str << "ole"; |
| 441 break; |
| 442 case One: |
| 443 Str << "one"; |
| 444 break; |
| 445 case Ord: |
| 446 Str << "ord"; |
| 447 break; |
| 448 case Ueq: |
| 449 Str << "ueq"; |
| 450 break; |
| 451 case Ugt: |
| 452 Str << "ugt"; |
| 453 break; |
| 454 case Uge: |
| 455 Str << "uge"; |
| 456 break; |
| 457 case Ult: |
| 458 Str << "ult"; |
| 459 break; |
| 460 case Ule: |
| 461 Str << "ule"; |
| 462 break; |
| 463 case Une: |
| 464 Str << "une"; |
| 465 break; |
| 466 case Uno: |
| 467 Str << "uno"; |
| 468 break; |
| 469 case True: |
| 470 Str << "true"; |
| 471 break; |
| 472 } |
| 473 Str << " " << getSrc(0)->getType() << " "; |
| 474 dumpSources(Str); |
| 475 } |
| 476 |
| 477 void IceInstLoad::dump(IceOstream &Str) const { |
| 478 dumpDest(Str); |
| 479 IceType Type = getDest()->getType(); |
| 480 Str << " = load " << Type << "* "; |
| 481 dumpSources(Str); |
| 482 switch (Type) { |
| 483 case IceType_f32: |
| 484 Str << ", align 4"; |
| 485 break; |
| 486 case IceType_f64: |
| 487 Str << ", align 8"; |
| 488 break; |
| 489 default: |
| 490 Str << ", align 1"; |
| 491 break; |
| 492 } |
| 493 } |
| 494 |
| 495 void IceInstStore::dump(IceOstream &Str) const { |
| 496 IceType Type = getData()->getType(); |
| 497 Str << "store " << Type << " " << getData() << ", " << Type << "* " |
| 498 << getAddr() << ", align "; |
| 499 switch (Type) { |
| 500 case IceType_f32: |
| 501 Str << "4"; |
| 502 break; |
| 503 case IceType_f64: |
| 504 Str << "8"; |
| 505 break; |
| 506 default: |
| 507 Str << "1"; |
| 508 break; |
| 509 } |
| 510 } |
| 511 |
| 512 void IceInstSwitch::dump(IceOstream &Str) const { |
| 513 IceType Type = getSrc(0)->getType(); |
| 514 Str << "switch " << Type << " " << getSrc(0) << ", label %" |
| 515 << getLabelDefault()->getName() << " [\n"; |
| 516 for (uint32_t I = 0; I < getNumCases(); ++I) { |
| 517 Str << " " << Type << " " << getValue(I) << ", label %" |
| 518 << getLabel(I)->getName() << "\n"; |
| 519 } |
| 520 Str << " ]"; |
| 521 } |
| 522 |
| 523 void IceInstPhi::dump(IceOstream &Str) const { |
| 524 dumpDest(Str); |
| 525 Str << " = phi " << getDest()->getType() << " "; |
| 526 for (uint32_t I = 0; I < getSrcSize(); ++I) { |
| 527 if (I > 0) |
| 528 Str << ", "; |
| 529 Str << "[ " << getSrc(I) << ", %" << Labels[I]->getName() << " ]"; |
| 530 } |
| 531 } |
| 532 |
| 533 void IceInstRet::dump(IceOstream &Str) const { |
| 534 IceType Type = getSrcSize() == 0 ? IceType_void : getSrc(0)->getType(); |
| 535 Str << "ret " << Type; |
| 536 if (getSrcSize()) { |
| 537 Str << " "; |
| 538 dumpSources(Str); |
| 539 } |
| 540 } |
| 541 |
| 542 void IceInstSelect::dump(IceOstream &Str) const { |
| 543 dumpDest(Str); |
| 544 IceOperand *Condition = getCondition(); |
| 545 IceOperand *TrueOp = getTrueOperand(); |
| 546 IceOperand *FalseOp = getFalseOperand(); |
| 547 Str << " = select " << Condition->getType() << " " << Condition << ", " |
| 548 << TrueOp->getType() << " " << TrueOp << ", " << FalseOp->getType() << " " |
| 549 << FalseOp; |
| 550 } |
| 551 |
| 552 void IceInstUnreachable::dump(IceOstream &Str) const { Str << "unreachable"; } |
OLD | NEW |