| OLD | NEW |
| 1 //===- subzero/src/IceInst.cpp - High-level instruction implementation ----===// | 1 //===- subzero/src/IceInst.cpp - High-level instruction implementation ----===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file implements the Inst class, primarily the various | 10 // This file implements the Inst class, primarily the various |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 LiveEnd[VarNum] = InstNumber; | 189 LiveEnd[VarNum] = InstNumber; |
| 190 } | 190 } |
| 191 } | 191 } |
| 192 } | 192 } |
| 193 } | 193 } |
| 194 } | 194 } |
| 195 } | 195 } |
| 196 | 196 |
| 197 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, | 197 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, |
| 198 Variable *Dest) | 198 Variable *Dest) |
| 199 : Inst(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) { | 199 : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) { |
| 200 // Verify AlignInBytes is 0 or a power of 2. | 200 // Verify AlignInBytes is 0 or a power of 2. |
| 201 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes)); | 201 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes)); |
| 202 addSource(ByteCount); | 202 addSource(ByteCount); |
| 203 } | 203 } |
| 204 | 204 |
| 205 InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, | 205 InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, |
| 206 Operand *Source1, Operand *Source2) | 206 Operand *Source1, Operand *Source2) |
| 207 : Inst(Func, Inst::Arithmetic, 2, Dest), Op(Op) { | 207 : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) { |
| 208 addSource(Source1); | 208 addSource(Source1); |
| 209 addSource(Source2); | 209 addSource(Source2); |
| 210 } | 210 } |
| 211 | 211 |
| 212 const char *InstArithmetic::getOpName(OpKind Op) { | 212 const char *InstArithmetic::getOpName(OpKind Op) { |
| 213 size_t OpIndex = static_cast<size_t>(Op); | 213 size_t OpIndex = static_cast<size_t>(Op); |
| 214 return OpIndex < InstArithmetic::_num | 214 return OpIndex < InstArithmetic::_num |
| 215 ? InstArithmeticAttributes[OpIndex].DisplayString | 215 ? InstArithmeticAttributes[OpIndex].DisplayString |
| 216 : "???"; | 216 : "???"; |
| 217 } | 217 } |
| 218 | 218 |
| 219 bool InstArithmetic::isCommutative() const { | 219 bool InstArithmetic::isCommutative() const { |
| 220 return InstArithmeticAttributes[getOp()].IsCommutative; | 220 return InstArithmeticAttributes[getOp()].IsCommutative; |
| 221 } | 221 } |
| 222 | 222 |
| 223 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source) | 223 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source) |
| 224 : Inst(Func, Inst::Assign, 1, Dest) { | 224 : InstHighLevel(Func, Inst::Assign, 1, Dest) { |
| 225 addSource(Source); | 225 addSource(Source); |
| 226 } | 226 } |
| 227 | 227 |
| 228 // If TargetTrue==TargetFalse, we turn it into an unconditional | 228 // If TargetTrue==TargetFalse, we turn it into an unconditional |
| 229 // branch. This ensures that, along with the 'switch' instruction | 229 // branch. This ensures that, along with the 'switch' instruction |
| 230 // semantics, there is at most one edge from one node to another. | 230 // semantics, there is at most one edge from one node to another. |
| 231 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, | 231 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, |
| 232 CfgNode *TargetFalse) | 232 CfgNode *TargetFalse) |
| 233 : Inst(Func, Inst::Br, 1, NULL), TargetFalse(TargetFalse), | 233 : InstHighLevel(Func, Inst::Br, 1, NULL), TargetFalse(TargetFalse), |
| 234 TargetTrue(TargetTrue) { | 234 TargetTrue(TargetTrue) { |
| 235 if (TargetTrue == TargetFalse) { | 235 if (TargetTrue == TargetFalse) { |
| 236 TargetTrue = NULL; // turn into unconditional version | 236 TargetTrue = NULL; // turn into unconditional version |
| 237 } else { | 237 } else { |
| 238 addSource(Source); | 238 addSource(Source); |
| 239 } | 239 } |
| 240 } | 240 } |
| 241 | 241 |
| 242 InstBr::InstBr(Cfg *Func, CfgNode *Target) | 242 InstBr::InstBr(Cfg *Func, CfgNode *Target) |
| 243 : Inst(Func, Inst::Br, 0, NULL), TargetFalse(Target), TargetTrue(NULL) {} | 243 : InstHighLevel(Func, Inst::Br, 0, NULL), TargetFalse(Target), |
| 244 TargetTrue(NULL) {} |
| 244 | 245 |
| 245 NodeList InstBr::getTerminatorEdges() const { | 246 NodeList InstBr::getTerminatorEdges() const { |
| 246 NodeList OutEdges; | 247 NodeList OutEdges; |
| 247 OutEdges.push_back(TargetFalse); | 248 OutEdges.push_back(TargetFalse); |
| 248 if (TargetTrue) | 249 if (TargetTrue) |
| 249 OutEdges.push_back(TargetTrue); | 250 OutEdges.push_back(TargetTrue); |
| 250 return OutEdges; | 251 return OutEdges; |
| 251 } | 252 } |
| 252 | 253 |
| 253 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source) | 254 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source) |
| 254 : Inst(Func, Inst::Cast, 1, Dest), CastKind(CastKind) { | 255 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) { |
| 255 addSource(Source); | 256 addSource(Source); |
| 256 } | 257 } |
| 257 | 258 |
| 258 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest, | 259 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest, |
| 259 Operand *Source1, Operand *Source2) | 260 Operand *Source1, Operand *Source2) |
| 260 : Inst(Func, Inst::ExtractElement, 2, Dest) { | 261 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) { |
| 261 addSource(Source1); | 262 addSource(Source1); |
| 262 addSource(Source2); | 263 addSource(Source2); |
| 263 } | 264 } |
| 264 | 265 |
| 265 InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 266 InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, |
| 266 Operand *Source2) | 267 Operand *Source2) |
| 267 : Inst(Func, Inst::Fcmp, 2, Dest), Condition(Condition) { | 268 : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) { |
| 268 addSource(Source1); | 269 addSource(Source1); |
| 269 addSource(Source2); | 270 addSource(Source2); |
| 270 } | 271 } |
| 271 | 272 |
| 272 InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, | 273 InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, |
| 273 Operand *Source2) | 274 Operand *Source2) |
| 274 : Inst(Func, Inst::Icmp, 2, Dest), Condition(Condition) { | 275 : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) { |
| 275 addSource(Source1); | 276 addSource(Source1); |
| 276 addSource(Source2); | 277 addSource(Source2); |
| 277 } | 278 } |
| 278 | 279 |
| 279 InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest, | 280 InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest, |
| 280 Operand *Source1, Operand *Source2, | 281 Operand *Source1, Operand *Source2, |
| 281 Operand *Source3) | 282 Operand *Source3) |
| 282 : Inst(Func, Inst::InsertElement, 3, Dest) { | 283 : InstHighLevel(Func, Inst::InsertElement, 3, Dest) { |
| 283 addSource(Source1); | 284 addSource(Source1); |
| 284 addSource(Source2); | 285 addSource(Source2); |
| 285 addSource(Source3); | 286 addSource(Source3); |
| 286 } | 287 } |
| 287 | 288 |
| 288 InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr) | 289 InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr) |
| 289 : Inst(Func, Inst::Load, 1, Dest) { | 290 : InstHighLevel(Func, Inst::Load, 1, Dest) { |
| 290 addSource(SourceAddr); | 291 addSource(SourceAddr); |
| 291 } | 292 } |
| 292 | 293 |
| 293 InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest) | 294 InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest) |
| 294 : Inst(Func, Phi, MaxSrcs, Dest) { | 295 : InstHighLevel(Func, Phi, MaxSrcs, Dest) { |
| 295 Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs); | 296 Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs); |
| 296 } | 297 } |
| 297 | 298 |
| 298 // TODO: A Switch instruction (and maybe others) can add duplicate | 299 // TODO: A Switch instruction (and maybe others) can add duplicate |
| 299 // edges. We may want to de-dup Phis and validate consistency (i.e., | 300 // edges. We may want to de-dup Phis and validate consistency (i.e., |
| 300 // the source operands are the same for duplicate edges), though it | 301 // the source operands are the same for duplicate edges), though it |
| 301 // seems the current lowering code is OK with this situation. | 302 // seems the current lowering code is OK with this situation. |
| 302 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { | 303 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { |
| 303 Labels[getSrcSize()] = Label; | 304 Labels[getSrcSize()] = Label; |
| 304 addSource(Source); | 305 addSource(Source); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 Inst *InstPhi::lower(Cfg *Func) { | 344 Inst *InstPhi::lower(Cfg *Func) { |
| 344 Variable *Dest = getDest(); | 345 Variable *Dest = getDest(); |
| 345 assert(Dest); | 346 assert(Dest); |
| 346 IceString PhiName = Dest->getName() + "_phi"; | 347 IceString PhiName = Dest->getName() + "_phi"; |
| 347 Variable *NewSrc = Func->makeVariable(Dest->getType(), PhiName); | 348 Variable *NewSrc = Func->makeVariable(Dest->getType(), PhiName); |
| 348 this->Dest = NewSrc; | 349 this->Dest = NewSrc; |
| 349 return InstAssign::create(Func, Dest, NewSrc); | 350 return InstAssign::create(Func, Dest, NewSrc); |
| 350 } | 351 } |
| 351 | 352 |
| 352 InstRet::InstRet(Cfg *Func, Operand *RetValue) | 353 InstRet::InstRet(Cfg *Func, Operand *RetValue) |
| 353 : Inst(Func, Ret, RetValue ? 1 : 0, NULL) { | 354 : InstHighLevel(Func, Ret, RetValue ? 1 : 0, NULL) { |
| 354 if (RetValue) | 355 if (RetValue) |
| 355 addSource(RetValue); | 356 addSource(RetValue); |
| 356 } | 357 } |
| 357 | 358 |
| 358 InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, | 359 InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, |
| 359 Operand *SourceTrue, Operand *SourceFalse) | 360 Operand *SourceTrue, Operand *SourceFalse) |
| 360 : Inst(Func, Inst::Select, 3, Dest) { | 361 : InstHighLevel(Func, Inst::Select, 3, Dest) { |
| 361 assert(typeElementType(Condition->getType()) == IceType_i1); | 362 assert(typeElementType(Condition->getType()) == IceType_i1); |
| 362 addSource(Condition); | 363 addSource(Condition); |
| 363 addSource(SourceTrue); | 364 addSource(SourceTrue); |
| 364 addSource(SourceFalse); | 365 addSource(SourceFalse); |
| 365 } | 366 } |
| 366 | 367 |
| 367 InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr) | 368 InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr) |
| 368 : Inst(Func, Inst::Store, 2, NULL) { | 369 : InstHighLevel(Func, Inst::Store, 2, NULL) { |
| 369 addSource(Data); | 370 addSource(Data); |
| 370 addSource(Addr); | 371 addSource(Addr); |
| 371 } | 372 } |
| 372 | 373 |
| 373 InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, | 374 InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, |
| 374 CfgNode *LabelDefault) | 375 CfgNode *LabelDefault) |
| 375 : Inst(Func, Inst::Switch, 1, NULL), LabelDefault(LabelDefault), | 376 : InstHighLevel(Func, Inst::Switch, 1, NULL), LabelDefault(LabelDefault), |
| 376 NumCases(NumCases) { | 377 NumCases(NumCases) { |
| 377 addSource(Source); | 378 addSource(Source); |
| 378 Values = Func->allocateArrayOf<uint64_t>(NumCases); | 379 Values = Func->allocateArrayOf<uint64_t>(NumCases); |
| 379 Labels = Func->allocateArrayOf<CfgNode *>(NumCases); | 380 Labels = Func->allocateArrayOf<CfgNode *>(NumCases); |
| 380 // Initialize in case buggy code doesn't set all entries | 381 // Initialize in case buggy code doesn't set all entries |
| 381 for (SizeT I = 0; I < NumCases; ++I) { | 382 for (SizeT I = 0; I < NumCases; ++I) { |
| 382 Values[I] = 0; | 383 Values[I] = 0; |
| 383 Labels[I] = NULL; | 384 Labels[I] = NULL; |
| 384 } | 385 } |
| 385 } | 386 } |
| 386 | 387 |
| 387 void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) { | 388 void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) { |
| 388 assert(CaseIndex < NumCases); | 389 assert(CaseIndex < NumCases); |
| 389 Values[CaseIndex] = Value; | 390 Values[CaseIndex] = Value; |
| 390 Labels[CaseIndex] = Label; | 391 Labels[CaseIndex] = Label; |
| 391 } | 392 } |
| 392 | 393 |
| 393 NodeList InstSwitch::getTerminatorEdges() const { | 394 NodeList InstSwitch::getTerminatorEdges() const { |
| 394 NodeList OutEdges; | 395 NodeList OutEdges; |
| 395 OutEdges.push_back(LabelDefault); | 396 OutEdges.push_back(LabelDefault); |
| 396 for (SizeT I = 0; I < NumCases; ++I) { | 397 for (SizeT I = 0; I < NumCases; ++I) { |
| 397 OutEdges.push_back(Labels[I]); | 398 OutEdges.push_back(Labels[I]); |
| 398 } | 399 } |
| 399 return OutEdges; | 400 return OutEdges; |
| 400 } | 401 } |
| 401 | 402 |
| 402 InstUnreachable::InstUnreachable(Cfg *Func) | 403 InstUnreachable::InstUnreachable(Cfg *Func) |
| 403 : Inst(Func, Inst::Unreachable, 0, NULL) {} | 404 : InstHighLevel(Func, Inst::Unreachable, 0, NULL) {} |
| 404 | 405 |
| 405 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) | 406 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) |
| 406 : Inst(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { | 407 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { |
| 407 assert(Dest); | 408 assert(Dest); |
| 408 if (Src) | 409 if (Src) |
| 409 addSource(Src); | 410 addSource(Src); |
| 410 } | 411 } |
| 411 | 412 |
| 412 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) | 413 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) |
| 413 : Inst(Func, Inst::FakeUse, 1, NULL) { | 414 : InstHighLevel(Func, Inst::FakeUse, 1, NULL) { |
| 414 assert(Src); | 415 assert(Src); |
| 415 addSource(Src); | 416 addSource(Src); |
| 416 } | 417 } |
| 417 | 418 |
| 418 InstFakeKill::InstFakeKill(Cfg *Func, const VarList &KilledRegs, | 419 InstFakeKill::InstFakeKill(Cfg *Func, const VarList &KilledRegs, |
| 419 const Inst *Linked) | 420 const Inst *Linked) |
| 420 : Inst(Func, Inst::FakeKill, KilledRegs.size(), NULL), Linked(Linked) { | 421 : InstHighLevel(Func, Inst::FakeKill, KilledRegs.size(), NULL), |
| 422 Linked(Linked) { |
| 421 for (VarList::const_iterator I = KilledRegs.begin(), E = KilledRegs.end(); | 423 for (VarList::const_iterator I = KilledRegs.begin(), E = KilledRegs.end(); |
| 422 I != E; ++I) { | 424 I != E; ++I) { |
| 423 Variable *Var = *I; | 425 Variable *Var = *I; |
| 424 addSource(Var); | 426 addSource(Var); |
| 425 } | 427 } |
| 426 } | 428 } |
| 427 | 429 |
| 428 // ======================== Dump routines ======================== // | 430 // ======================== Dump routines ======================== // |
| 429 | 431 |
| 430 void Inst::dumpDecorated(const Cfg *Func) const { | 432 void Inst::dumpDecorated(const Cfg *Func) const { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 442 Str << buf; | 444 Str << buf; |
| 443 } | 445 } |
| 444 Str << " "; | 446 Str << " "; |
| 445 if (isDeleted()) | 447 if (isDeleted()) |
| 446 Str << " //"; | 448 Str << " //"; |
| 447 dump(Func); | 449 dump(Func); |
| 448 dumpExtras(Func); | 450 dumpExtras(Func); |
| 449 Str << "\n"; | 451 Str << "\n"; |
| 450 } | 452 } |
| 451 | 453 |
| 452 void Inst::emit(const Cfg * /*Func*/) const { | |
| 453 llvm_unreachable("emit() called on a non-lowered instruction"); | |
| 454 } | |
| 455 | |
| 456 void Inst::emitIAS(const Cfg *Func) const { emit(Func); } | |
| 457 | |
| 458 void Inst::dump(const Cfg *Func) const { | 454 void Inst::dump(const Cfg *Func) const { |
| 459 Ostream &Str = Func->getContext()->getStrDump(); | 455 Ostream &Str = Func->getContext()->getStrDump(); |
| 460 dumpDest(Func); | 456 dumpDest(Func); |
| 461 Str << " =~ "; | 457 Str << " =~ "; |
| 462 dumpSources(Func); | 458 dumpSources(Func); |
| 463 } | 459 } |
| 464 | 460 |
| 465 void Inst::dumpExtras(const Cfg *Func) const { | 461 void Inst::dumpExtras(const Cfg *Func) const { |
| 466 Ostream &Str = Func->getContext()->getStrDump(); | 462 Ostream &Str = Func->getContext()->getStrDump(); |
| 467 bool First = true; | 463 bool First = true; |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 Str << "kill.pseudo "; | 743 Str << "kill.pseudo "; |
| 748 dumpSources(Func); | 744 dumpSources(Func); |
| 749 } | 745 } |
| 750 | 746 |
| 751 void InstTarget::dump(const Cfg *Func) const { | 747 void InstTarget::dump(const Cfg *Func) const { |
| 752 Ostream &Str = Func->getContext()->getStrDump(); | 748 Ostream &Str = Func->getContext()->getStrDump(); |
| 753 Str << "[TARGET] "; | 749 Str << "[TARGET] "; |
| 754 Inst::dump(Func); | 750 Inst::dump(Func); |
| 755 } | 751 } |
| 756 | 752 |
| 757 void InstTarget::dumpExtras(const Cfg *Func) const { Inst::dumpExtras(Func); } | |
| 758 | |
| 759 } // end of namespace Ice | 753 } // end of namespace Ice |
| OLD | NEW |