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 // ======================== Dump routines ======================== // |
| 187 |
| 188 IceOstream &operator<<(IceOstream &Str, const IceInst *I) { |
| 189 if (!Str.isVerbose(IceV_Deleted) && (I->isDeleted())) |
| 190 return Str; |
| 191 if (Str.isVerbose(IceV_InstNumbers)) { |
| 192 char buf[30]; |
| 193 int32_t Number = I->getNumber(); |
| 194 if (Number < 0) |
| 195 sprintf(buf, "[XXX]"); |
| 196 else |
| 197 sprintf(buf, "[%3d]", I->getNumber()); |
| 198 Str << buf; |
| 199 } |
| 200 Str << " "; |
| 201 if (I->isDeleted()) |
| 202 Str << " //"; |
| 203 I->dump(Str); |
| 204 Str << "\n"; |
| 205 return Str; |
| 206 } |
| 207 |
| 208 void IceInst::dump(IceOstream &Str) const { |
| 209 dumpDest(Str); |
| 210 Str << " =~ "; |
| 211 dumpSources(Str); |
| 212 } |
| 213 |
| 214 void IceInst::dumpSources(IceOstream &Str) const { |
| 215 for (uint32_t I = 0; I < getSrcSize(); ++I) { |
| 216 if (I > 0) |
| 217 Str << ", "; |
| 218 Str << getSrc(I); |
| 219 } |
| 220 } |
| 221 |
| 222 void IceInst::dumpDest(IceOstream &Str) const { |
| 223 if (getDest()) |
| 224 Str << getDest(); |
| 225 } |
| 226 |
| 227 void IceInstAlloca::dump(IceOstream &Str) const { |
| 228 dumpDest(Str); |
| 229 Str << " = alloca i8, i32 "; |
| 230 Str << getSrc(0) << ", align " << Align; |
| 231 } |
| 232 |
| 233 void IceInstArithmetic::dump(IceOstream &Str) const { |
| 234 dumpDest(Str); |
| 235 Str << " = "; |
| 236 switch (getOp()) { |
| 237 case Add: |
| 238 Str << "add"; |
| 239 break; |
| 240 case Fadd: |
| 241 Str << "fadd"; |
| 242 break; |
| 243 case Sub: |
| 244 Str << "sub"; |
| 245 break; |
| 246 case Fsub: |
| 247 Str << "fsub"; |
| 248 break; |
| 249 case Mul: |
| 250 Str << "mul"; |
| 251 break; |
| 252 case Fmul: |
| 253 Str << "fmul"; |
| 254 break; |
| 255 case Udiv: |
| 256 Str << "udiv"; |
| 257 break; |
| 258 case Sdiv: |
| 259 Str << "sdiv"; |
| 260 break; |
| 261 case Fdiv: |
| 262 Str << "fdiv"; |
| 263 break; |
| 264 case Urem: |
| 265 Str << "urem"; |
| 266 break; |
| 267 case Srem: |
| 268 Str << "srem"; |
| 269 break; |
| 270 case Frem: |
| 271 Str << "frem"; |
| 272 break; |
| 273 case Shl: |
| 274 Str << "shl"; |
| 275 break; |
| 276 case Lshr: |
| 277 Str << "lshr"; |
| 278 break; |
| 279 case Ashr: |
| 280 Str << "ashr"; |
| 281 break; |
| 282 case And: |
| 283 Str << "and"; |
| 284 break; |
| 285 case Or: |
| 286 Str << "or"; |
| 287 break; |
| 288 case Xor: |
| 289 Str << "xor"; |
| 290 break; |
| 291 } |
| 292 Str << " " << getDest()->getType() << " "; |
| 293 dumpSources(Str); |
| 294 } |
| 295 |
| 296 void IceInstAssign::dump(IceOstream &Str) const { |
| 297 dumpDest(Str); |
| 298 Str << " = " << getDest()->getType() << " "; |
| 299 dumpSources(Str); |
| 300 } |
| 301 |
| 302 void IceInstBr::dump(IceOstream &Str) const { |
| 303 dumpDest(Str); |
| 304 Str << "br "; |
| 305 if (!isUnconditional()) { |
| 306 Str << "i1 " << getSrc(0) << ", label %" << getTargetTrue()->getName() |
| 307 << ", "; |
| 308 } |
| 309 Str << "label %" << getTargetFalse()->getName(); |
| 310 } |
| 311 |
| 312 void IceInstCall::dump(IceOstream &Str) const { |
| 313 if (getDest()) { |
| 314 dumpDest(Str); |
| 315 Str << " = "; |
| 316 } |
| 317 if (Tail) |
| 318 Str << "tail "; |
| 319 Str << "call "; |
| 320 if (getDest()) |
| 321 Str << getDest()->getType(); |
| 322 else |
| 323 Str << "void"; |
| 324 Str << " " << getCallTarget() << "("; |
| 325 for (uint32_t I = 0; I < getNumArgs(); ++I) { |
| 326 if (I > 0) |
| 327 Str << ", "; |
| 328 Str << getArg(I)->getType() << " " << getArg(I); |
| 329 } |
| 330 Str << ")"; |
| 331 } |
| 332 |
| 333 void IceInstCast::dump(IceOstream &Str) const { |
| 334 dumpDest(Str); |
| 335 Str << " = "; |
| 336 switch (getCastKind()) { |
| 337 default: |
| 338 Str << "UNKNOWN"; |
| 339 assert(0); |
| 340 break; |
| 341 case Trunc: |
| 342 Str << "trunc"; |
| 343 break; |
| 344 case Zext: |
| 345 Str << "zext"; |
| 346 break; |
| 347 case Sext: |
| 348 Str << "sext"; |
| 349 break; |
| 350 case Fptrunc: |
| 351 Str << "fptrunc"; |
| 352 break; |
| 353 case Fpext: |
| 354 Str << "fpext"; |
| 355 break; |
| 356 case Fptoui: |
| 357 Str << "fptoui"; |
| 358 break; |
| 359 case Fptosi: |
| 360 Str << "fptosi"; |
| 361 break; |
| 362 case Uitofp: |
| 363 Str << "uitofp"; |
| 364 break; |
| 365 case Sitofp: |
| 366 Str << "sitofp"; |
| 367 break; |
| 368 } |
| 369 Str << " " << getSrc(0)->getType() << " "; |
| 370 dumpSources(Str); |
| 371 Str << " to " << getDest()->getType(); |
| 372 } |
| 373 |
| 374 void IceInstIcmp::dump(IceOstream &Str) const { |
| 375 dumpDest(Str); |
| 376 Str << " = icmp "; |
| 377 switch (getCondition()) { |
| 378 case Eq: |
| 379 Str << "eq"; |
| 380 break; |
| 381 case Ne: |
| 382 Str << "ne"; |
| 383 break; |
| 384 case Ugt: |
| 385 Str << "ugt"; |
| 386 break; |
| 387 case Uge: |
| 388 Str << "uge"; |
| 389 break; |
| 390 case Ult: |
| 391 Str << "ult"; |
| 392 break; |
| 393 case Ule: |
| 394 Str << "ule"; |
| 395 break; |
| 396 case Sgt: |
| 397 Str << "sgt"; |
| 398 break; |
| 399 case Sge: |
| 400 Str << "sge"; |
| 401 break; |
| 402 case Slt: |
| 403 Str << "slt"; |
| 404 break; |
| 405 case Sle: |
| 406 Str << "sle"; |
| 407 break; |
| 408 } |
| 409 Str << " " << getSrc(0)->getType() << " "; |
| 410 dumpSources(Str); |
| 411 } |
| 412 |
| 413 void IceInstFcmp::dump(IceOstream &Str) const { |
| 414 dumpDest(Str); |
| 415 Str << " = fcmp "; |
| 416 |
| 417 switch (getCondition()) { |
| 418 case False: |
| 419 Str << "false"; |
| 420 break; |
| 421 case Oeq: |
| 422 Str << "oeq"; |
| 423 break; |
| 424 case Ogt: |
| 425 Str << "ogt"; |
| 426 break; |
| 427 case Oge: |
| 428 Str << "oge"; |
| 429 break; |
| 430 case Olt: |
| 431 Str << "olt"; |
| 432 break; |
| 433 case Ole: |
| 434 Str << "ole"; |
| 435 break; |
| 436 case One: |
| 437 Str << "one"; |
| 438 break; |
| 439 case Ord: |
| 440 Str << "ord"; |
| 441 break; |
| 442 case Ueq: |
| 443 Str << "ueq"; |
| 444 break; |
| 445 case Ugt: |
| 446 Str << "ugt"; |
| 447 break; |
| 448 case Uge: |
| 449 Str << "uge"; |
| 450 break; |
| 451 case Ult: |
| 452 Str << "ult"; |
| 453 break; |
| 454 case Ule: |
| 455 Str << "ule"; |
| 456 break; |
| 457 case Une: |
| 458 Str << "une"; |
| 459 break; |
| 460 case Uno: |
| 461 Str << "uno"; |
| 462 break; |
| 463 case True: |
| 464 Str << "true"; |
| 465 break; |
| 466 } |
| 467 Str << " " << getSrc(0)->getType() << " "; |
| 468 dumpSources(Str); |
| 469 } |
| 470 |
| 471 void IceInstLoad::dump(IceOstream &Str) const { |
| 472 dumpDest(Str); |
| 473 IceType Type = getDest()->getType(); |
| 474 Str << " = load " << Type << "* "; |
| 475 dumpSources(Str); |
| 476 switch (Type) { |
| 477 case IceType_f32: |
| 478 Str << ", align 4"; |
| 479 break; |
| 480 case IceType_f64: |
| 481 Str << ", align 8"; |
| 482 break; |
| 483 default: |
| 484 Str << ", align 1"; |
| 485 break; |
| 486 } |
| 487 } |
| 488 |
| 489 void IceInstStore::dump(IceOstream &Str) const { |
| 490 IceType Type = getData()->getType(); |
| 491 Str << "store " << Type << " " << getData() << ", " << Type << "* " |
| 492 << getAddr() << ", align "; |
| 493 switch (Type) { |
| 494 case IceType_f32: |
| 495 Str << "4"; |
| 496 break; |
| 497 case IceType_f64: |
| 498 Str << "8"; |
| 499 break; |
| 500 default: |
| 501 Str << "1"; |
| 502 break; |
| 503 } |
| 504 } |
| 505 |
| 506 void IceInstSwitch::dump(IceOstream &Str) const { |
| 507 IceType Type = getSrc(0)->getType(); |
| 508 Str << "switch " << Type << " " << getSrc(0) << ", label %" |
| 509 << getLabelDefault()->getName() << " [\n"; |
| 510 for (uint32_t I = 0; I < getNumCases(); ++I) { |
| 511 Str << " " << Type << " " << getValue(I) << ", label %" |
| 512 << getLabel(I)->getName() << "\n"; |
| 513 } |
| 514 Str << " ]"; |
| 515 } |
| 516 |
| 517 void IceInstPhi::dump(IceOstream &Str) const { |
| 518 dumpDest(Str); |
| 519 Str << " = phi " << getDest()->getType() << " "; |
| 520 for (uint32_t I = 0; I < getSrcSize(); ++I) { |
| 521 if (I > 0) |
| 522 Str << ", "; |
| 523 Str << "[ " << getSrc(I) << ", %" << Labels[I]->getName() << " ]"; |
| 524 } |
| 525 } |
| 526 |
| 527 void IceInstRet::dump(IceOstream &Str) const { |
| 528 IceType Type = getSrcSize() == 0 ? IceType_void : getSrc(0)->getType(); |
| 529 Str << "ret " << Type; |
| 530 if (getSrcSize()) { |
| 531 Str << " "; |
| 532 dumpSources(Str); |
| 533 } |
| 534 } |
| 535 |
| 536 void IceInstSelect::dump(IceOstream &Str) const { |
| 537 dumpDest(Str); |
| 538 IceOperand *Condition = getCondition(); |
| 539 IceOperand *TrueOp = getTrueOperand(); |
| 540 IceOperand *FalseOp = getFalseOperand(); |
| 541 Str << " = select " << Condition->getType() << " " << Condition << ", " |
| 542 << TrueOp->getType() << " " << TrueOp << ", " << FalseOp->getType() << " " |
| 543 << FalseOp; |
| 544 } |
OLD | NEW |