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