Chromium Code Reviews| 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 Inst 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 namespace Ice { | |
| 21 | |
| 22 Inst::Inst(IceCfg *Cfg, InstKind Kind, IceSize_t MaxSrcs, Variable *Dest) | |
| 23 : Kind(Kind), Number(Cfg->newInstNumber()), Deleted(false), | |
| 24 HasSideEffects(false), Dest(Dest), MaxSrcs(MaxSrcs), NumSrcs(0), | |
| 25 Srcs(Cfg->allocateArrayOf<Operand *>(MaxSrcs)) {} | |
| 26 | |
| 27 Inst::~Inst() { | |
| 28 #ifdef ICE_NO_ARENAS | |
| 29 for (IceSize_t i = 0; i < getSrcSize(); ++i) { | |
| 30 Operand *Src = getSrc(i); | |
| 31 if (Src && !Src->isPooled()) { | |
| 32 delete Src; | |
| 33 } | |
| 34 } | |
| 35 delete[] Srcs; | |
| 36 if (getDest() && !getDest()->isPooled()) { | |
| 37 delete getDest(); | |
| 38 } | |
|
JF
2014/04/23 03:51:28
Same thing on deletion, though it kind of seems li
Jim Stichnoth
2014/04/26 15:02:11
Done. And you're right, it was just wrong for the
| |
| 39 #endif // ICE_NO_ARENAS | |
| 40 } | |
| 41 | |
| 42 void Inst::updateVars(CfgNode *Node) { | |
| 43 if (Dest) | |
| 44 Dest->setDefinition(this, Node); | |
| 45 | |
| 46 IceSize_t VarIndex = 0; | |
| 47 for (IceSize_t I = 0; I < getSrcSize(); ++I) { | |
| 48 Operand *Src = getSrc(I); | |
| 49 IceSize_t NumVars = Src->getNumVars(); | |
| 50 for (IceSize_t J = 0; J < NumVars; ++J, ++VarIndex) { | |
| 51 Variable *Var = Src->getVar(J); | |
| 52 Var->setUse(this, Node); | |
| 53 } | |
| 54 } | |
| 55 } | |
| 56 | |
| 57 InstAlloca::InstAlloca(IceCfg *Cfg, Operand *ByteCount, uint32_t Align, | |
| 58 Variable *Dest) | |
| 59 : Inst(Cfg, Inst::Alloca, 1, Dest), Align(Align) { | |
| 60 addSource(ByteCount); | |
| 61 } | |
| 62 | |
| 63 InstArithmetic::InstArithmetic(IceCfg *Cfg, OpKind Op, Variable *Dest, | |
| 64 Operand *Source1, Operand *Source2) | |
| 65 : Inst(Cfg, Inst::Arithmetic, 2, Dest), Op(Op) { | |
| 66 addSource(Source1); | |
| 67 addSource(Source2); | |
| 68 } | |
| 69 | |
| 70 bool InstArithmetic::isCommutative() const { | |
| 71 #define X(tag, str, commutative) \ | |
| 72 case tag: \ | |
| 73 return commutative; | |
| 74 | |
| 75 switch (getOp()) { ICEINSTARITHMETIC_TABLE } | |
|
JF
2014/04/23 03:51:28
Load from a static const bool table instead: show
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
| 76 #undef X | |
| 77 | |
| 78 assert(0); // should be unreachable | |
|
JF
2014/04/23 03:51:28
llvm_unreachable
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
| 79 return false; | |
| 80 } | |
| 81 | |
| 82 InstAssign::InstAssign(IceCfg *Cfg, Variable *Dest, Operand *Source) | |
| 83 : Inst(Cfg, Inst::Assign, 1, Dest) { | |
| 84 addSource(Source); | |
| 85 } | |
| 86 | |
| 87 // If TargetTrue==TargetFalse, we turn it into an unconditional | |
| 88 // branch. This ensures that, along with the 'switch' instruction | |
| 89 // semantics, there is at most one edge from one node to another. | |
| 90 InstBr::InstBr(IceCfg *Cfg, Operand *Source, CfgNode *TargetTrue, | |
| 91 CfgNode *TargetFalse) | |
| 92 : Inst(Cfg, Inst::Br, 1, NULL), TargetFalse(TargetFalse), | |
| 93 TargetTrue(TargetTrue) { | |
| 94 if (TargetTrue == TargetFalse) { | |
| 95 TargetTrue = NULL; // turn into unconditional version | |
| 96 } else { | |
| 97 addSource(Source); | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 InstBr::InstBr(IceCfg *Cfg, CfgNode *Target) | |
| 102 : Inst(Cfg, Inst::Br, 0, NULL), TargetFalse(Target), TargetTrue(NULL) {} | |
| 103 | |
| 104 NodeList InstBr::getTerminatorEdges() const { | |
| 105 NodeList OutEdges; | |
| 106 OutEdges.push_back(TargetFalse); | |
| 107 if (TargetTrue) | |
| 108 OutEdges.push_back(TargetTrue); | |
| 109 return OutEdges; | |
| 110 } | |
| 111 | |
| 112 InstCast::InstCast(IceCfg *Cfg, OpKind CastKind, Variable *Dest, | |
| 113 Operand *Source) | |
| 114 : Inst(Cfg, Inst::Cast, 1, Dest), CastKind(CastKind) { | |
| 115 addSource(Source); | |
| 116 } | |
| 117 | |
| 118 InstFcmp::InstFcmp(IceCfg *Cfg, FCond Condition, Variable *Dest, | |
| 119 Operand *Source1, Operand *Source2) | |
| 120 : Inst(Cfg, Inst::Fcmp, 2, Dest), Condition(Condition) { | |
| 121 addSource(Source1); | |
| 122 addSource(Source2); | |
| 123 } | |
| 124 | |
| 125 InstIcmp::InstIcmp(IceCfg *Cfg, ICond Condition, Variable *Dest, | |
| 126 Operand *Source1, Operand *Source2) | |
| 127 : Inst(Cfg, Inst::Icmp, 2, Dest), Condition(Condition) { | |
| 128 addSource(Source1); | |
| 129 addSource(Source2); | |
| 130 } | |
| 131 | |
| 132 InstLoad::InstLoad(IceCfg *Cfg, Variable *Dest, Operand *SourceAddr) | |
| 133 : Inst(Cfg, Inst::Load, 1, Dest) { | |
| 134 addSource(SourceAddr); | |
| 135 } | |
| 136 | |
| 137 InstPhi::InstPhi(IceCfg *Cfg, IceSize_t MaxSrcs, Variable *Dest) | |
| 138 : Inst(Cfg, Phi, MaxSrcs, Dest) { | |
| 139 Labels = Cfg->allocateArrayOf<CfgNode *>(MaxSrcs); | |
| 140 } | |
| 141 | |
| 142 // TODO: A Switch instruction (and maybe others) can add duplicate | |
| 143 // edges. We may want to de-dup Phis and validate consistency (i.e., | |
| 144 // the source operands are the same for duplicate edges), though it | |
| 145 // seems the current lowering code is OK with this situation. | |
| 146 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { | |
| 147 Labels[getSrcSize()] = Label; | |
| 148 addSource(Source); | |
| 149 } | |
| 150 | |
| 151 InstRet::InstRet(IceCfg *Cfg, Operand *RetValue) | |
| 152 : Inst(Cfg, Ret, RetValue ? 1 : 0, NULL) { | |
| 153 if (RetValue) | |
| 154 addSource(RetValue); | |
| 155 } | |
| 156 | |
| 157 InstSelect::InstSelect(IceCfg *Cfg, Variable *Dest, Operand *Condition, | |
| 158 Operand *SourceTrue, Operand *SourceFalse) | |
| 159 : Inst(Cfg, Inst::Select, 3, Dest) { | |
| 160 assert(Condition->getType() == IceType_i1); | |
| 161 addSource(Condition); | |
| 162 addSource(SourceTrue); | |
| 163 addSource(SourceFalse); | |
| 164 } | |
| 165 | |
| 166 InstStore::InstStore(IceCfg *Cfg, Operand *Data, Operand *Addr) | |
| 167 : Inst(Cfg, Inst::Store, 2, NULL) { | |
| 168 addSource(Data); | |
| 169 addSource(Addr); | |
| 170 } | |
| 171 | |
| 172 InstSwitch::InstSwitch(IceCfg *Cfg, IceSize_t NumCases, Operand *Source, | |
| 173 CfgNode *LabelDefault) | |
| 174 : Inst(Cfg, Inst::Switch, 1, NULL), LabelDefault(LabelDefault), | |
| 175 NumCases(NumCases) { | |
| 176 addSource(Source); | |
| 177 Values = Cfg->allocateArrayOf<uint64_t>(NumCases); | |
| 178 Labels = Cfg->allocateArrayOf<CfgNode *>(NumCases); | |
| 179 // Initialize in case buggy code doesn't set all entries | |
| 180 for (IceSize_t I = 0; I < NumCases; ++I) { | |
| 181 Values[I] = 0; | |
| 182 Labels[I] = NULL; | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 void InstSwitch::addBranch(IceSize_t CaseIndex, uint64_t Value, | |
| 187 CfgNode *Label) { | |
| 188 assert(CaseIndex < NumCases); | |
| 189 Values[CaseIndex] = Value; | |
| 190 Labels[CaseIndex] = Label; | |
| 191 } | |
| 192 | |
| 193 NodeList InstSwitch::getTerminatorEdges() const { | |
| 194 NodeList OutEdges; | |
| 195 OutEdges.push_back(LabelDefault); | |
| 196 for (IceSize_t I = 0; I < NumCases; ++I) { | |
| 197 OutEdges.push_back(Labels[I]); | |
| 198 } | |
| 199 return OutEdges; | |
| 200 } | |
| 201 | |
| 202 InstUnreachable::InstUnreachable(IceCfg *Cfg) | |
| 203 : Inst(Cfg, Inst::Unreachable, 0, NULL) {} | |
| 204 | |
| 205 // ======================== Dump routines ======================== // | |
| 206 | |
| 207 void Inst::dumpDecorated(const IceCfg *Cfg) const { | |
| 208 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 209 if (!Cfg->getContext()->isVerbose(IceV_Deleted) && isDeleted()) | |
| 210 return; | |
| 211 if (Cfg->getContext()->isVerbose(IceV_InstNumbers)) { | |
| 212 const static size_t BufLen = 30; | |
| 213 char buf[BufLen]; | |
| 214 int32_t Number = getNumber(); | |
| 215 if (Number < 0) | |
| 216 snprintf(buf, BufLen, "[XXX]"); | |
| 217 else | |
| 218 snprintf(buf, BufLen, "[%3d]", Number); | |
| 219 Str << buf; | |
| 220 } | |
| 221 Str << " "; | |
| 222 if (isDeleted()) | |
| 223 Str << " //"; | |
| 224 dump(Cfg); | |
| 225 Str << "\n"; | |
| 226 } | |
| 227 | |
| 228 void Inst::dump(const IceCfg *Cfg) const { | |
| 229 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 230 dumpDest(Cfg); | |
| 231 Str << " =~ "; | |
| 232 dumpSources(Cfg); | |
| 233 } | |
| 234 | |
| 235 void Inst::dumpSources(const IceCfg *Cfg) const { | |
| 236 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 237 for (IceSize_t I = 0; I < getSrcSize(); ++I) { | |
| 238 if (I > 0) | |
| 239 Str << ", "; | |
| 240 getSrc(I)->dump(Cfg); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 void Inst::dumpDest(const IceCfg *Cfg) const { | |
| 245 if (getDest()) | |
| 246 getDest()->dump(Cfg); | |
| 247 } | |
| 248 | |
| 249 void InstAlloca::dump(const IceCfg *Cfg) const { | |
| 250 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 251 dumpDest(Cfg); | |
| 252 Str << " = alloca i8, i32 "; | |
| 253 getSizeInBytes()->dump(Cfg); | |
| 254 Str << ", align " << Align; | |
| 255 } | |
| 256 | |
| 257 void InstArithmetic::dump(const IceCfg *Cfg) const { | |
| 258 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 259 dumpDest(Cfg); | |
| 260 Str << " = "; | |
| 261 | |
| 262 #define X(tag, str, commutative) \ | |
| 263 case tag: \ | |
| 264 Str << str; \ | |
| 265 break; | |
| 266 | |
| 267 switch (getOp()) { ICEINSTARITHMETIC_TABLE } | |
|
JF
2014/04/23 03:51:28
Same thing on table lookup from static const char
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
| 268 #undef X | |
| 269 | |
| 270 Str << " " << getDest()->getType() << " "; | |
| 271 dumpSources(Cfg); | |
| 272 } | |
| 273 | |
| 274 void InstAssign::dump(const IceCfg *Cfg) const { | |
| 275 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 276 dumpDest(Cfg); | |
| 277 Str << " = " << getDest()->getType() << " "; | |
| 278 dumpSources(Cfg); | |
| 279 } | |
| 280 | |
| 281 void InstBr::dump(const IceCfg *Cfg) const { | |
| 282 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 283 dumpDest(Cfg); | |
| 284 Str << "br "; | |
| 285 if (!isUnconditional()) { | |
| 286 Str << "i1 "; | |
| 287 getCondition()->dump(Cfg); | |
| 288 Str << ", label %" << getTargetTrue()->getName() << ", "; | |
| 289 } | |
| 290 Str << "label %" << getTargetFalse()->getName(); | |
| 291 } | |
| 292 | |
| 293 void InstCall::dump(const IceCfg *Cfg) const { | |
| 294 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 295 if (getDest()) { | |
| 296 dumpDest(Cfg); | |
| 297 Str << " = "; | |
| 298 } | |
| 299 if (Tail) | |
| 300 Str << "tail "; | |
| 301 Str << "call "; | |
| 302 if (getDest()) | |
| 303 Str << getDest()->getType(); | |
| 304 else | |
| 305 Str << "void"; | |
| 306 Str << " "; | |
| 307 getCallTarget()->dump(Cfg); | |
| 308 Str << "("; | |
| 309 for (IceSize_t I = 0; I < getNumArgs(); ++I) { | |
| 310 if (I > 0) | |
| 311 Str << ", "; | |
| 312 Str << getArg(I)->getType() << " "; | |
| 313 getArg(I)->dump(Cfg); | |
| 314 } | |
| 315 Str << ")"; | |
| 316 } | |
| 317 | |
| 318 void InstCast::dump(const IceCfg *Cfg) const { | |
| 319 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 320 dumpDest(Cfg); | |
| 321 Str << " = "; | |
| 322 | |
| 323 #define X(tag, str) \ | |
| 324 case tag: \ | |
| 325 Str << str; \ | |
| 326 break; | |
| 327 | |
| 328 switch (getCastKind()) { | |
| 329 ICEINSTCAST_TABLE | |
|
JF
2014/04/23 03:51:28
Same.
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
| 330 default: | |
| 331 Str << "UNKNOWN"; | |
| 332 assert(0); | |
| 333 break; | |
| 334 } | |
| 335 #undef X | |
| 336 | |
| 337 Str << " " << getSrc(0)->getType() << " "; | |
| 338 dumpSources(Cfg); | |
| 339 Str << " to " << getDest()->getType(); | |
| 340 } | |
| 341 | |
| 342 void InstIcmp::dump(const IceCfg *Cfg) const { | |
| 343 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 344 dumpDest(Cfg); | |
| 345 Str << " = icmp "; | |
| 346 | |
| 347 #define X(tag, str) \ | |
| 348 case tag: \ | |
| 349 Str << str; \ | |
| 350 break; | |
| 351 | |
| 352 switch (getCondition()) { ICEINSTICMP_TABLE } | |
|
JF
2014/04/23 03:51:28
Same.
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
| 353 #undef X | |
| 354 Str << " " << getSrc(0)->getType() << " "; | |
| 355 dumpSources(Cfg); | |
| 356 } | |
| 357 | |
| 358 void InstFcmp::dump(const IceCfg *Cfg) const { | |
| 359 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 360 dumpDest(Cfg); | |
| 361 Str << " = fcmp "; | |
| 362 | |
| 363 #define X(tag, str) \ | |
| 364 case tag: \ | |
| 365 Str << str; \ | |
| 366 break; | |
| 367 | |
| 368 switch (getCondition()) { ICEINSTFCMP_TABLE } | |
|
JF
2014/04/23 03:51:28
Same.
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
| 369 #undef X | |
| 370 Str << " " << getSrc(0)->getType() << " "; | |
| 371 dumpSources(Cfg); | |
| 372 } | |
| 373 | |
| 374 void InstLoad::dump(const IceCfg *Cfg) const { | |
| 375 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 376 dumpDest(Cfg); | |
| 377 IceType Type = getDest()->getType(); | |
| 378 Str << " = load " << Type << "* "; | |
| 379 dumpSources(Cfg); | |
| 380 switch (Type) { | |
| 381 case IceType_f32: | |
| 382 Str << ", align 4"; | |
| 383 break; | |
| 384 case IceType_f64: | |
| 385 Str << ", align 8"; | |
| 386 break; | |
| 387 default: | |
| 388 Str << ", align 1"; | |
| 389 break; | |
| 390 } | |
| 391 } | |
| 392 | |
| 393 void InstStore::dump(const IceCfg *Cfg) const { | |
| 394 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 395 IceType Type = getData()->getType(); | |
| 396 Str << "store " << Type << " "; | |
| 397 getData()->dump(Cfg); | |
| 398 Str << ", " << Type << "* "; | |
| 399 getAddr()->dump(Cfg); | |
| 400 Str << ", align "; | |
| 401 switch (Type) { | |
| 402 case IceType_f32: | |
| 403 Str << "4"; | |
| 404 break; | |
| 405 case IceType_f64: | |
| 406 Str << "8"; | |
| 407 break; | |
| 408 default: | |
| 409 Str << "1"; | |
| 410 break; | |
| 411 } | |
| 412 } | |
| 413 | |
| 414 void InstSwitch::dump(const IceCfg *Cfg) const { | |
| 415 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 416 IceType Type = getComparison()->getType(); | |
| 417 Str << "switch " << Type << " "; | |
| 418 getSrc(0)->dump(Cfg); | |
| 419 Str << ", label %" << getLabelDefault()->getName() << " [\n"; | |
| 420 for (IceSize_t I = 0; I < getNumCases(); ++I) { | |
| 421 Str << " " << Type << " " << getValue(I) << ", label %" | |
| 422 << getLabel(I)->getName() << "\n"; | |
| 423 } | |
| 424 Str << " ]"; | |
| 425 } | |
| 426 | |
| 427 void InstPhi::dump(const IceCfg *Cfg) const { | |
| 428 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 429 dumpDest(Cfg); | |
| 430 Str << " = phi " << getDest()->getType() << " "; | |
| 431 for (IceSize_t I = 0; I < getSrcSize(); ++I) { | |
| 432 if (I > 0) | |
| 433 Str << ", "; | |
| 434 Str << "[ "; | |
| 435 getSrc(I)->dump(Cfg); | |
| 436 Str << ", %" << Labels[I]->getName() << " ]"; | |
| 437 } | |
| 438 } | |
| 439 | |
| 440 void InstRet::dump(const IceCfg *Cfg) const { | |
| 441 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 442 IceType Type = hasRetValue() ? getSrc(0)->getType() : IceType_void; | |
| 443 Str << "ret " << Type; | |
| 444 if (hasRetValue()) { | |
| 445 Str << " "; | |
| 446 dumpSources(Cfg); | |
| 447 } | |
| 448 } | |
| 449 | |
| 450 void InstSelect::dump(const IceCfg *Cfg) const { | |
| 451 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 452 dumpDest(Cfg); | |
| 453 Operand *Condition = getCondition(); | |
| 454 Operand *TrueOp = getTrueOperand(); | |
| 455 Operand *FalseOp = getFalseOperand(); | |
| 456 Str << " = select " << Condition->getType() << " "; | |
| 457 Condition->dump(Cfg); | |
| 458 Str << ", " << TrueOp->getType() << " "; | |
| 459 TrueOp->dump(Cfg); | |
| 460 Str << ", " << FalseOp->getType() << " "; | |
| 461 FalseOp->dump(Cfg); | |
| 462 } | |
| 463 | |
| 464 void InstUnreachable::dump(const IceCfg *Cfg) const { | |
| 465 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
| 466 Str << "unreachable"; | |
| 467 } | |
| 468 | |
| 469 } // end of namespace Ice | |
| OLD | NEW |