Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===// | 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===// |
| 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 defines aspects of the compilation that persist across | 10 // This file defines aspects of the compilation that persist across |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 #include "IceOperand.h" | 23 #include "IceOperand.h" |
| 24 #include "IceTargetLowering.h" | 24 #include "IceTargetLowering.h" |
| 25 #include "IceTimerTree.h" | 25 #include "IceTimerTree.h" |
| 26 #include "IceTypes.h" | 26 #include "IceTypes.h" |
| 27 #include "llvm/Support/Timer.h" | 27 #include "llvm/Support/Timer.h" |
| 28 | 28 |
| 29 #include <ctype.h> // isdigit(), isupper() | 29 #include <ctype.h> // isdigit(), isupper() |
| 30 #include <locale> // locale | 30 #include <locale> // locale |
| 31 #include <unordered_map> | 31 #include <unordered_map> |
| 32 | 32 |
| 33 | |
| 34 namespace std { | 33 namespace std { |
| 35 template <> struct hash<Ice::RelocatableTuple> { | 34 template <> struct hash<Ice::RelocatableTuple> { |
| 36 size_t operator()(const Ice::RelocatableTuple &Key) const { | 35 size_t operator()(const Ice::RelocatableTuple &Key) const { |
| 37 return hash<Ice::IceString>()(Key.Name) + | 36 return hash<Ice::IceString>()(Key.Name) + |
| 38 hash<Ice::RelocOffsetT>()(Key.Offset); | 37 hash<Ice::RelocOffsetT>()(Key.Offset); |
| 39 } | 38 } |
| 40 }; | 39 }; |
| 41 } // end of namespace std | 40 } // end of namespace std |
| 42 | 41 |
| 43 namespace Ice { | 42 namespace Ice { |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 388 OstreamLocker L(this); | 387 OstreamLocker L(this); |
| 389 Ostream &Stream = getStrDump(); | 388 Ostream &Stream = getStrDump(); |
| 390 for (const Ice::VariableDeclaration *Global : Globals) { | 389 for (const Ice::VariableDeclaration *Global : Globals) { |
| 391 Global->dump(this, Stream); | 390 Global->dump(this, Stream); |
| 392 } | 391 } |
| 393 } | 392 } |
| 394 if (Flags.getDisableTranslation()) | 393 if (Flags.getDisableTranslation()) |
| 395 return; | 394 return; |
| 396 | 395 |
| 397 addBlockInfoPtrs(Globals, ProfileBlockInfoVarDecl); | 396 addBlockInfoPtrs(Globals, ProfileBlockInfoVarDecl); |
| 397 // If we need to shuffle the layout of global variables, shuffle them now. | |
| 398 if (getFlags().shouldReorderGlobalVariables()) { | |
| 399 auto *RNGPtr = &RNG; | |
| 400 RandomShuffle(Globals.begin(), Globals.end(), | |
| 401 [RNGPtr](int N) { return (uint32_t)RNGPtr->next(N); }); | |
| 402 } | |
| 398 DataLowering->lowerGlobals(Globals, SectionSuffix); | 403 DataLowering->lowerGlobals(Globals, SectionSuffix); |
| 399 for (VariableDeclaration *Var : Globals) { | 404 for (VariableDeclaration *Var : Globals) { |
| 400 Var->discardInitializers(); | 405 Var->discardInitializers(); |
| 401 } | 406 } |
| 402 Globals.clear(); | 407 Globals.clear(); |
| 403 } | 408 } |
| 404 | 409 |
| 405 void GlobalContext::lowerProfileData() { | 410 void GlobalContext::lowerProfileData() { |
| 406 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only | 411 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only |
| 407 // ever be nullptr after this method completes. This assertion is a convoluted | 412 // ever be nullptr after this method completes. This assertion is a convoluted |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 421 void GlobalContext::emitItems() { | 426 void GlobalContext::emitItems() { |
| 422 const bool Threaded = !getFlags().isSequential(); | 427 const bool Threaded = !getFlags().isSequential(); |
| 423 // Pending is a vector containing the reassembled, ordered list of | 428 // Pending is a vector containing the reassembled, ordered list of |
| 424 // work items. When we're ready for the next item, we first check | 429 // work items. When we're ready for the next item, we first check |
| 425 // whether it's in the Pending list. If not, we take an item from | 430 // whether it's in the Pending list. If not, we take an item from |
| 426 // the work queue, and if it's not the item we're waiting for, we | 431 // the work queue, and if it's not the item we're waiting for, we |
| 427 // insert it into Pending and repeat. The work item is deleted | 432 // insert it into Pending and repeat. The work item is deleted |
| 428 // after it is processed. | 433 // after it is processed. |
| 429 std::vector<EmitterWorkItem *> Pending; | 434 std::vector<EmitterWorkItem *> Pending; |
| 430 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); | 435 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); |
| 431 while (true) { | 436 uint32_t ShuffleStartIndex = DesiredSequenceNumber; |
| 437 uint32_t ShuffleEndIndex = DesiredSequenceNumber; | |
| 438 bool EmitQueueEmpty = false; | |
| 439 const uint32_t ShuffleWindowSize = | |
| 440 std::max((uint32_t)1, getFlags().getReorderFunctionsWindowSize()); | |
|
Jim Stichnoth
2015/06/26 01:54:57
I think you can just use 1u instead of casting.
qining
2015/06/26 03:16:08
Done. This is much better.
| |
| 441 bool Shuffle = Threaded && getFlags().shouldReorderFunctions(); | |
| 442 while (!EmitQueueEmpty) { | |
| 432 resizePending(Pending, DesiredSequenceNumber); | 443 resizePending(Pending, DesiredSequenceNumber); |
| 433 // See if Pending contains DesiredSequenceNumber. | 444 // See if Pending contains DesiredSequenceNumber. |
| 434 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber]; | 445 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber]; |
| 435 if (RawItem == nullptr) | 446 if (RawItem == nullptr) { |
| 447 // We need to fetch an EmitterWorkItem from the queue. | |
| 436 RawItem = emitQueueBlockingPop(); | 448 RawItem = emitQueueBlockingPop(); |
| 437 if (RawItem == nullptr) | 449 if (RawItem == nullptr) { |
| 438 break; | 450 // This is the notifier for an empty queue. |
| 439 uint32_t ItemSeq = RawItem->getSequenceNumber(); | 451 EmitQueueEmpty = true; |
| 440 if (Threaded && ItemSeq != DesiredSequenceNumber) { | 452 } else { |
| 441 resizePending(Pending, ItemSeq); | 453 // We get an EmitterWorkItem, we need to add it to Pending. |
| 442 Pending[ItemSeq] = RawItem; | 454 uint32_t ItemSeq = RawItem->getSequenceNumber(); |
| 443 continue; | 455 if (Threaded && ItemSeq != DesiredSequenceNumber) { |
| 456 // Not the desired one, add it to Pending but do not increase | |
| 457 // DesiredSequenceNumber. Continue the loop, do not emit the item. | |
| 458 resizePending(Pending, ItemSeq); | |
| 459 Pending[ItemSeq] = RawItem; | |
| 460 continue; | |
| 461 } | |
| 462 // ItemSeq == DesiredSequenceNumber, we need to check if we should | |
| 463 // emit it or not. If !Threaded, we're OK with ItemSeq != | |
| 464 // DesiredSequenceNumber. | |
| 465 Pending[DesiredSequenceNumber] = RawItem; | |
| 466 } | |
| 467 } | |
| 468 // We have the desired EmitterWorkItem or nullptr as the end notifier. | |
| 469 // If the emitter queue is not empty, increase DesiredSequenceNumber and | |
| 470 // ShuffleEndIndex. | |
| 471 if (!EmitQueueEmpty) { | |
| 472 DesiredSequenceNumber++; | |
| 473 ShuffleEndIndex++; | |
| 444 } | 474 } |
| 445 | 475 |
| 446 std::unique_ptr<EmitterWorkItem> Item(RawItem); | 476 if (Shuffle) { |
| 447 ++DesiredSequenceNumber; | 477 // Continue fetching EmitterWorkItem if function reordering is turned on, |
| 448 switch (Item->getKind()) { | 478 // and emit queue is not empty, and the number of consecutive pending |
| 449 case EmitterWorkItem::WI_Nop: | 479 // items is smaller than the window size, and RawItem is not a |
| 450 break; | 480 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid |
| 451 case EmitterWorkItem::WI_GlobalInits: { | 481 // holding an arbitrarily large GlobalDeclarationList. |
| 452 accumulateGlobals(Item->getGlobalInits()); | 482 if (!EmitQueueEmpty && |
| 453 } break; | 483 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize && |
| 454 case EmitterWorkItem::WI_Asm: { | 484 RawItem->getKind() != EmitterWorkItem::WI_GlobalInits) |
| 455 lowerGlobalsIfNoCodeHasBeenSeen(); | 485 continue; |
| 456 accumulateGlobals(Item->getGlobalInits()); | |
| 457 | 486 |
| 458 std::unique_ptr<Assembler> Asm = Item->getAsm(); | 487 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to |
| 459 Asm->alignFunction(); | 488 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the |
| 460 IceString MangledName = mangleName(Asm->getFunctionName()); | 489 // pending items from Pending[ShuffleStartIndex] to |
| 461 switch (getFlags().getOutFileType()) { | 490 // Pending[ShuffleEndIndex]. |
| 462 case FT_Elf: | 491 RandomShuffle(Pending.begin() + ShuffleStartIndex, |
| 463 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(), | 492 Pending.begin() + ShuffleEndIndex, |
| 464 Asm.get()); | 493 [this](uint64_t N) { return (uint32_t)RNG.next(N); }); |
| 494 } | |
| 495 | |
| 496 // Emit the item from ShuffleStartIndex to ShuffleEndIndex. | |
| 497 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) { | |
| 498 std::unique_ptr<EmitterWorkItem> Item(Pending[I]); | |
| 499 | |
| 500 switch (Item->getKind()) { | |
| 501 case EmitterWorkItem::WI_Nop: | |
| 465 break; | 502 break; |
| 466 case FT_Iasm: { | 503 case EmitterWorkItem::WI_GlobalInits: { |
| 467 OstreamLocker L(this); | 504 accumulateGlobals(Item->getGlobalInits()); |
| 468 Cfg::emitTextHeader(MangledName, this, Asm.get()); | |
| 469 Asm->emitIASBytes(this); | |
| 470 } break; | 505 } break; |
| 471 case FT_Asm: | 506 case EmitterWorkItem::WI_Asm: { |
| 472 llvm::report_fatal_error("Unexpected FT_Asm"); | 507 lowerGlobalsIfNoCodeHasBeenSeen(); |
| 473 break; | 508 accumulateGlobals(Item->getGlobalInits()); |
| 509 | |
| 510 std::unique_ptr<Assembler> Asm = Item->getAsm(); | |
| 511 Asm->alignFunction(); | |
| 512 IceString MangledName = mangleName(Asm->getFunctionName()); | |
| 513 switch (getFlags().getOutFileType()) { | |
| 514 case FT_Elf: | |
| 515 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(), | |
| 516 Asm.get()); | |
| 517 break; | |
| 518 case FT_Iasm: { | |
| 519 OstreamLocker L(this); | |
| 520 Cfg::emitTextHeader(MangledName, this, Asm.get()); | |
| 521 Asm->emitIASBytes(this); | |
| 522 } break; | |
| 523 case FT_Asm: | |
| 524 llvm::report_fatal_error("Unexpected FT_Asm"); | |
| 525 break; | |
| 526 } | |
| 527 } break; | |
| 528 case EmitterWorkItem::WI_Cfg: { | |
| 529 if (!BuildDefs::dump()) | |
| 530 llvm::report_fatal_error("WI_Cfg work item created inappropriately"); | |
| 531 lowerGlobalsIfNoCodeHasBeenSeen(); | |
| 532 accumulateGlobals(Item->getGlobalInits()); | |
| 533 | |
| 534 assert(getFlags().getOutFileType() == FT_Asm); | |
| 535 std::unique_ptr<Cfg> Func = Item->getCfg(); | |
| 536 // Unfortunately, we have to temporarily install the Cfg in TLS | |
| 537 // because Variable::asType() uses the allocator to create the | |
| 538 // differently-typed copy. | |
| 539 Cfg::setCurrentCfg(Func.get()); | |
| 540 Func->emit(); | |
| 541 Cfg::setCurrentCfg(nullptr); | |
| 542 dumpStats(Func->getFunctionName()); | |
| 543 } break; | |
| 474 } | 544 } |
| 475 } break; | |
| 476 case EmitterWorkItem::WI_Cfg: { | |
| 477 if (!BuildDefs::dump()) | |
| 478 llvm::report_fatal_error("WI_Cfg work item created inappropriately"); | |
| 479 lowerGlobalsIfNoCodeHasBeenSeen(); | |
| 480 accumulateGlobals(Item->getGlobalInits()); | |
| 481 | |
| 482 assert(getFlags().getOutFileType() == FT_Asm); | |
| 483 std::unique_ptr<Cfg> Func = Item->getCfg(); | |
| 484 // Unfortunately, we have to temporarily install the Cfg in TLS | |
| 485 // because Variable::asType() uses the allocator to create the | |
| 486 // differently-typed copy. | |
| 487 Cfg::setCurrentCfg(Func.get()); | |
| 488 Func->emit(); | |
| 489 Cfg::setCurrentCfg(nullptr); | |
| 490 dumpStats(Func->getFunctionName()); | |
| 491 } break; | |
| 492 } | 545 } |
| 546 // Update the start index for next shuffling queue | |
| 547 ShuffleStartIndex = ShuffleEndIndex; | |
| 493 } | 548 } |
| 494 | 549 |
| 495 // In case there are no code to be generated, we invoke the conditional | 550 // In case there are no code to be generated, we invoke the conditional |
| 496 // lowerGlobals again -- this is a no-op if code has been emitted. | 551 // lowerGlobals again -- this is a no-op if code has been emitted. |
| 497 lowerGlobalsIfNoCodeHasBeenSeen(); | 552 lowerGlobalsIfNoCodeHasBeenSeen(); |
| 498 } | 553 } |
| 499 | 554 |
| 500 // Scan a string for S[0-9A-Z]*_ patterns and replace them with | 555 // Scan a string for S[0-9A-Z]*_ patterns and replace them with |
| 501 // S<num>_ where <num> is the next base-36 value. If a type name | 556 // S<num>_ where <num> is the next base-36 value. If a type name |
| 502 // legitimately contains that pattern, then the substitution will be | 557 // legitimately contains that pattern, then the substitution will be |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 922 Ctx = Func->getContext(); | 977 Ctx = Func->getContext(); |
| 923 Active = | 978 Active = |
| 924 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); | 979 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); |
| 925 if (Active) | 980 if (Active) |
| 926 Ctx->pushTimer(ID, StackID); | 981 Ctx->pushTimer(ID, StackID); |
| 927 } | 982 } |
| 928 | 983 |
| 929 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); | 984 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); |
| 930 | 985 |
| 931 } // end of namespace Ice | 986 } // end of namespace Ice |
| OLD | NEW |