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