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 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 OstreamLocker L(this); | 387 OstreamLocker L(this); |
| 388 Ostream &Stream = getStrDump(); | 388 Ostream &Stream = getStrDump(); |
| 389 for (const Ice::VariableDeclaration *Global : Globals) { | 389 for (const Ice::VariableDeclaration *Global : Globals) { |
| 390 Global->dump(this, Stream); | 390 Global->dump(this, Stream); |
| 391 } | 391 } |
| 392 } | 392 } |
| 393 if (Flags.getDisableTranslation()) | 393 if (Flags.getDisableTranslation()) |
| 394 return; | 394 return; |
| 395 | 395 |
| 396 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 RandomShuffle(Globals.begin(), Globals.end(), | |
| 400 [this](int N) { return (uint32_t)RNG.next(N); }); | |
|
John
2015/06/24 00:24:00
[RNG], instead of [this]?
qining
2015/06/24 01:20:40
Done. But also add a declaration a pointer to RNG.
| |
| 401 } | |
| 397 DataLowering->lowerGlobals(Globals, SectionSuffix); | 402 DataLowering->lowerGlobals(Globals, SectionSuffix); |
| 398 for (VariableDeclaration *Var : Globals) { | 403 for (VariableDeclaration *Var : Globals) { |
| 399 Var->discardInitializers(); | 404 Var->discardInitializers(); |
| 400 } | 405 } |
| 401 Globals.clear(); | 406 Globals.clear(); |
| 402 } | 407 } |
| 403 | 408 |
| 404 void GlobalContext::lowerProfileData() { | 409 void GlobalContext::lowerProfileData() { |
| 405 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only | 410 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only |
| 406 // ever be nullptr after this method completes. This assertion is a convoluted | 411 // ever be nullptr after this method completes. This assertion is a convoluted |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 420 void GlobalContext::emitItems() { | 425 void GlobalContext::emitItems() { |
| 421 const bool Threaded = !getFlags().isSequential(); | 426 const bool Threaded = !getFlags().isSequential(); |
| 422 // Pending is a vector containing the reassembled, ordered list of | 427 // Pending is a vector containing the reassembled, ordered list of |
| 423 // work items. When we're ready for the next item, we first check | 428 // work items. When we're ready for the next item, we first check |
| 424 // whether it's in the Pending list. If not, we take an item from | 429 // whether it's in the Pending list. If not, we take an item from |
| 425 // the work queue, and if it's not the item we're waiting for, we | 430 // the work queue, and if it's not the item we're waiting for, we |
| 426 // insert it into Pending and repeat. The work item is deleted | 431 // insert it into Pending and repeat. The work item is deleted |
| 427 // after it is processed. | 432 // after it is processed. |
| 428 std::vector<EmitterWorkItem *> Pending; | 433 std::vector<EmitterWorkItem *> Pending; |
| 429 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); | 434 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); |
| 430 while (true) { | 435 uint32_t ShuffleStartIndex = DesiredSequenceNumber; |
| 436 uint32_t ShuffleEndIndex = DesiredSequenceNumber; | |
| 437 bool EmitQueueEmpty = false; | |
| 438 uint32_t ShuffleWindowSize = getFlags().getReorderFunctionsWindowSize() > 0 | |
|
John
2015/06/24 00:24:00
const uint32_t
qining
2015/06/24 01:20:40
Done.
| |
| 439 ? getFlags().getReorderFunctionsWindowSize() | |
| 440 : 1; | |
| 441 bool Shuffle = Threaded ? getFlags().shouldReorderFunctions() : false; | |
| 442 while (!EmitQueueEmpty) { | |
| 431 resizePending(Pending, DesiredSequenceNumber); | 443 resizePending(Pending, DesiredSequenceNumber); |
| 432 // See if Pending contains DesiredSequenceNumber. | 444 // See if Pending contains DesiredSequenceNumber. |
| 433 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber]; | 445 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber]; |
| 434 if (RawItem == nullptr) | 446 if (RawItem == nullptr) { |
| 447 // We need to fetch an EmitterWorkItem from the queue. | |
| 435 RawItem = emitQueueBlockingPop(); | 448 RawItem = emitQueueBlockingPop(); |
| 436 if (RawItem == nullptr) | 449 if (RawItem == nullptr) { |
| 437 break; | 450 // This is the notifier for an empty queue. |
| 438 uint32_t ItemSeq = RawItem->getSequenceNumber(); | 451 EmitQueueEmpty = true; |
| 439 if (Threaded && ItemSeq != DesiredSequenceNumber) { | 452 } else { |
| 440 resizePending(Pending, ItemSeq); | 453 // We get an EmitterWorkItem, we need to add it to Pending. |
| 441 Pending[ItemSeq] = RawItem; | 454 uint32_t ItemSeq = RawItem->getSequenceNumber(); |
| 455 if (Threaded && ItemSeq != DesiredSequenceNumber) { | |
| 456 // Not the desired one, add it to Pending but do not increase | |
| 457 // DesiredSequenceNumber. And do not emit the item. | |
| 458 resizePending(Pending, ItemSeq); | |
| 459 Pending[ItemSeq] = RawItem; | |
| 460 continue; | |
| 461 } else { | |
| 462 // ItemSeq == DesiredSequenceNumber, we need to check if we should | |
| 463 // emit it or not. | |
| 464 // Do not continue the loop here. | |
| 465 Pending[DesiredSequenceNumber] = RawItem; | |
| 466 } | |
| 467 } | |
| 468 } | |
| 469 // We have the desired EmitterWorkItem or an nullptr as the end notifier. | |
| 470 // If the emitter queue is not empty, increase DesiredSequenceNumber and | |
| 471 // ShuffleEndIndex. | |
| 472 if (!EmitQueueEmpty) { | |
| 473 DesiredSequenceNumber++; | |
| 474 ShuffleEndIndex++; | |
| 475 } | |
| 476 // Continue fetching EmitterWorkItem if function reordering is turned on, | |
| 477 // and emit queue is not empty, and the number of consecutive pending items | |
| 478 // is smaller than the window size, and RawItem is not a WI_GlobalInits | |
| 479 // kind. Note we should emit WI_GlobalInits kind block first, as we need to | |
| 480 // keep the blocking profiling workflow unchanged. | |
| 481 if (Shuffle && !EmitQueueEmpty && | |
| 482 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize && | |
| 483 RawItem->getKind() != EmitterWorkItem::WI_GlobalInits) | |
| 484 // Need more EmitterWorkItem to emit. | |
| 442 continue; | 485 continue; |
| 486 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to | |
| 487 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the | |
| 488 // pending items from Pending[ShuffleStartIndex] to | |
| 489 // Pending[ShuffleEndIndex]. | |
| 490 if (Shuffle) { | |
| 491 RandomShuffle(Pending.begin() + ShuffleStartIndex, | |
| 492 Pending.begin() + ShuffleEndIndex, | |
| 493 [this](uint64_t N) { return (uint32_t)RNG.next(N); }); | |
| 443 } | 494 } |
| 444 | 495 |
| 445 std::unique_ptr<EmitterWorkItem> Item(RawItem); | 496 // Emit the item from ShuffleStartIndex to ShuffleEndIndex. |
| 446 ++DesiredSequenceNumber; | 497 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) { |
| 447 switch (Item->getKind()) { | 498 std::unique_ptr<EmitterWorkItem> Item(Pending[I]); |
| 448 case EmitterWorkItem::WI_Nop: | |
| 449 break; | |
| 450 case EmitterWorkItem::WI_GlobalInits: { | |
| 451 accumulateGlobals(Item->getGlobalInits()); | |
| 452 } break; | |
| 453 case EmitterWorkItem::WI_Asm: { | |
| 454 lowerGlobalsIfNoCodeHasBeenSeen(); | |
| 455 accumulateGlobals(Item->getGlobalInits()); | |
| 456 | 499 |
| 457 std::unique_ptr<Assembler> Asm = Item->getAsm(); | 500 switch (Item->getKind()) { |
| 458 Asm->alignFunction(); | 501 case EmitterWorkItem::WI_Nop: |
| 459 IceString MangledName = mangleName(Asm->getFunctionName()); | |
| 460 switch (getFlags().getOutFileType()) { | |
| 461 case FT_Elf: | |
| 462 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(), | |
| 463 Asm.get()); | |
| 464 break; | 502 break; |
| 465 case FT_Iasm: { | 503 case EmitterWorkItem::WI_GlobalInits: { |
| 466 OstreamLocker L(this); | 504 accumulateGlobals(Item->getGlobalInits()); |
| 467 Cfg::emitTextHeader(MangledName, this, Asm.get()); | |
| 468 Asm->emitIASBytes(this); | |
| 469 } break; | 505 } break; |
| 470 case FT_Asm: | 506 case EmitterWorkItem::WI_Asm: { |
| 471 llvm::report_fatal_error("Unexpected FT_Asm"); | 507 lowerGlobalsIfNoCodeHasBeenSeen(); |
| 472 break; | 508 accumulateGlobals(Item->getGlobalInits()); |
| 473 } | |
| 474 } break; | |
| 475 case EmitterWorkItem::WI_Cfg: { | |
| 476 if (!ALLOW_DUMP) | |
| 477 llvm::report_fatal_error("WI_Cfg work item created inappropriately"); | |
| 478 lowerGlobalsIfNoCodeHasBeenSeen(); | |
| 479 accumulateGlobals(Item->getGlobalInits()); | |
| 480 | 509 |
| 481 assert(getFlags().getOutFileType() == FT_Asm); | 510 std::unique_ptr<Assembler> Asm = Item->getAsm(); |
| 482 std::unique_ptr<Cfg> Func = Item->getCfg(); | 511 Asm->alignFunction(); |
| 483 // Unfortunately, we have to temporarily install the Cfg in TLS | 512 IceString MangledName = mangleName(Asm->getFunctionName()); |
| 484 // because Variable::asType() uses the allocator to create the | 513 switch (getFlags().getOutFileType()) { |
| 485 // differently-typed copy. | 514 case FT_Elf: |
| 486 Cfg::setCurrentCfg(Func.get()); | 515 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(), |
| 487 Func->emit(); | 516 Asm.get()); |
| 488 Cfg::setCurrentCfg(nullptr); | 517 break; |
| 489 dumpStats(Func->getFunctionName()); | 518 case FT_Iasm: { |
| 490 } break; | 519 OstreamLocker L(this); |
| 491 } | 520 Cfg::emitTextHeader(MangledName, this, Asm.get()); |
| 492 } | 521 Asm->emitIASBytes(this); |
| 522 } break; | |
| 523 case FT_Asm: | |
| 524 llvm::report_fatal_error("Unexpected FT_Asm"); | |
| 525 break; | |
| 526 } // switch (getFlags().getOutFileType()) | |
| 527 } break; | |
| 528 case EmitterWorkItem::WI_Cfg: { | |
| 529 if (!ALLOW_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; | |
| 544 } // switch (Item->getKind()) | |
| 545 } // for loop | |
| 546 // Update the start index for next shuffling queue | |
| 547 ShuffleStartIndex = ShuffleEndIndex; | |
| 548 } // while loop | |
| 493 | 549 |
| 494 // 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 |
| 495 // 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. |
| 496 lowerGlobalsIfNoCodeHasBeenSeen(); | 552 lowerGlobalsIfNoCodeHasBeenSeen(); |
| 497 } | 553 } |
| 498 | 554 |
| 499 // 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 |
| 500 // 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 |
| 501 // legitimately contains that pattern, then the substitution will be | 557 // legitimately contains that pattern, then the substitution will be |
| 502 // made in error and most likely the link will fail. In this case, | 558 // made in error and most likely the link will fail. In this case, |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 921 Ctx = Func->getContext(); | 977 Ctx = Func->getContext(); |
| 922 Active = | 978 Active = |
| 923 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); | 979 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); |
| 924 if (Active) | 980 if (Active) |
| 925 Ctx->pushTimer(ID, StackID); | 981 Ctx->pushTimer(ID, StackID); |
| 926 } | 982 } |
| 927 | 983 |
| 928 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); | 984 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); |
| 929 | 985 |
| 930 } // end of namespace Ice | 986 } // end of namespace Ice |
| OLD | NEW |