| 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 auto *RNGPtr = &RNG; |
| 400 RandomShuffle(Globals.begin(), Globals.end(), |
| 401 [RNGPtr](int N) { return (uint32_t)RNGPtr->next(N); }); |
| 402 } |
| 397 DataLowering->lowerGlobals(Globals, SectionSuffix); | 403 DataLowering->lowerGlobals(Globals, SectionSuffix); |
| 398 for (VariableDeclaration *Var : Globals) { | 404 for (VariableDeclaration *Var : Globals) { |
| 399 Var->discardInitializers(); | 405 Var->discardInitializers(); |
| 400 } | 406 } |
| 401 Globals.clear(); | 407 Globals.clear(); |
| 402 } | 408 } |
| 403 | 409 |
| 404 void GlobalContext::lowerProfileData() { | 410 void GlobalContext::lowerProfileData() { |
| 405 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only | 411 // ProfileBlockInfoVarDecl is initialized in the constructor, and will only |
| 406 // 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... |
| 420 void GlobalContext::emitItems() { | 426 void GlobalContext::emitItems() { |
| 421 const bool Threaded = !getFlags().isSequential(); | 427 const bool Threaded = !getFlags().isSequential(); |
| 422 // Pending is a vector containing the reassembled, ordered list of | 428 // Pending is a vector containing the reassembled, ordered list of |
| 423 // 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 |
| 424 // 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 |
| 425 // 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 |
| 426 // insert it into Pending and repeat. The work item is deleted | 432 // insert it into Pending and repeat. The work item is deleted |
| 427 // after it is processed. | 433 // after it is processed. |
| 428 std::vector<EmitterWorkItem *> Pending; | 434 std::vector<EmitterWorkItem *> Pending; |
| 429 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); | 435 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); |
| 430 while (true) { | 436 uint32_t ShuffleStartIndex = DesiredSequenceNumber; |
| 437 uint32_t ShuffleEndIndex = DesiredSequenceNumber; |
| 438 bool EmitQueueEmpty = false; |
| 439 const uint32_t ShuffleWindowSize = |
| 440 getFlags().getReorderFunctionsWindowSize() > 0 |
| 441 ? getFlags().getReorderFunctionsWindowSize() |
| 442 : 1; |
| 443 bool Shuffle = Threaded ? getFlags().shouldReorderFunctions() : false; |
| 444 while (!EmitQueueEmpty) { |
| 431 resizePending(Pending, DesiredSequenceNumber); | 445 resizePending(Pending, DesiredSequenceNumber); |
| 432 // See if Pending contains DesiredSequenceNumber. | 446 // See if Pending contains DesiredSequenceNumber. |
| 433 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber]; | 447 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber]; |
| 434 if (RawItem == nullptr) | 448 if (RawItem == nullptr) { |
| 449 // We need to fetch an EmitterWorkItem from the queue. |
| 435 RawItem = emitQueueBlockingPop(); | 450 RawItem = emitQueueBlockingPop(); |
| 436 if (RawItem == nullptr) | 451 if (RawItem == nullptr) { |
| 437 break; | 452 // This is the notifier for an empty queue. |
| 438 uint32_t ItemSeq = RawItem->getSequenceNumber(); | 453 EmitQueueEmpty = true; |
| 439 if (Threaded && ItemSeq != DesiredSequenceNumber) { | 454 } else { |
| 440 resizePending(Pending, ItemSeq); | 455 // We get an EmitterWorkItem, we need to add it to Pending. |
| 441 Pending[ItemSeq] = RawItem; | 456 uint32_t ItemSeq = RawItem->getSequenceNumber(); |
| 442 continue; | 457 if (Threaded && ItemSeq != DesiredSequenceNumber) { |
| 458 // Not the desired one, add it to Pending but do not increase |
| 459 // DesiredSequenceNumber. Continue the loop, do not emit the item. |
| 460 resizePending(Pending, ItemSeq); |
| 461 Pending[ItemSeq] = RawItem; |
| 462 continue; |
| 463 } |
| 464 // ItemSeq == DesiredSequenceNumber, we need to check if we should |
| 465 // emit it or not. If !Threaded, we're OK with ItemSeq != |
| 466 // DesiredSequenceNumber. |
| 467 Pending[DesiredSequenceNumber] = RawItem; |
| 468 } |
| 469 } |
| 470 // We have the desired EmitterWorkItem or an nullptr as the end notifier. |
| 471 // If the emitter queue is not empty, increase DesiredSequenceNumber and |
| 472 // ShuffleEndIndex. |
| 473 if (!EmitQueueEmpty) { |
| 474 DesiredSequenceNumber++; |
| 475 ShuffleEndIndex++; |
| 443 } | 476 } |
| 444 | 477 |
| 445 std::unique_ptr<EmitterWorkItem> Item(RawItem); | 478 if (Shuffle) { |
| 446 ++DesiredSequenceNumber; | 479 // Continue fetching EmitterWorkItem if function reordering is turned on, |
| 447 switch (Item->getKind()) { | 480 // and emit queue is not empty, and the number of consecutive pending |
| 448 case EmitterWorkItem::WI_Nop: | 481 // items is smaller than the window size, and RawItem is not a |
| 449 break; | 482 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid |
| 450 case EmitterWorkItem::WI_GlobalInits: { | 483 // holding an arbitrarily large GlobalDeclarationList. |
| 451 accumulateGlobals(Item->getGlobalInits()); | 484 if (!EmitQueueEmpty && |
| 452 } break; | 485 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize && |
| 453 case EmitterWorkItem::WI_Asm: { | 486 RawItem->getKind() != EmitterWorkItem::WI_GlobalInits) |
| 454 lowerGlobalsIfNoCodeHasBeenSeen(); | 487 continue; |
| 455 accumulateGlobals(Item->getGlobalInits()); | |
| 456 | 488 |
| 457 std::unique_ptr<Assembler> Asm = Item->getAsm(); | 489 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to |
| 458 Asm->alignFunction(); | 490 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the |
| 459 IceString MangledName = mangleName(Asm->getFunctionName()); | 491 // pending items from Pending[ShuffleStartIndex] to |
| 460 switch (getFlags().getOutFileType()) { | 492 // Pending[ShuffleEndIndex]. |
| 461 case FT_Elf: | 493 RandomShuffle(Pending.begin() + ShuffleStartIndex, |
| 462 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(), | 494 Pending.begin() + ShuffleEndIndex, |
| 463 Asm.get()); | 495 [this](uint64_t N) { return (uint32_t)RNG.next(N); }); |
| 496 } |
| 497 |
| 498 // Emit the item from ShuffleStartIndex to ShuffleEndIndex. |
| 499 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) { |
| 500 std::unique_ptr<EmitterWorkItem> Item(Pending[I]); |
| 501 |
| 502 switch (Item->getKind()) { |
| 503 case EmitterWorkItem::WI_Nop: |
| 464 break; | 504 break; |
| 465 case FT_Iasm: { | 505 case EmitterWorkItem::WI_GlobalInits: { |
| 466 OstreamLocker L(this); | 506 accumulateGlobals(Item->getGlobalInits()); |
| 467 Cfg::emitTextHeader(MangledName, this, Asm.get()); | |
| 468 Asm->emitIASBytes(this); | |
| 469 } break; | 507 } break; |
| 470 case FT_Asm: | 508 case EmitterWorkItem::WI_Asm: { |
| 471 llvm::report_fatal_error("Unexpected FT_Asm"); | 509 lowerGlobalsIfNoCodeHasBeenSeen(); |
| 472 break; | 510 accumulateGlobals(Item->getGlobalInits()); |
| 511 |
| 512 std::unique_ptr<Assembler> Asm = Item->getAsm(); |
| 513 Asm->alignFunction(); |
| 514 IceString MangledName = mangleName(Asm->getFunctionName()); |
| 515 switch (getFlags().getOutFileType()) { |
| 516 case FT_Elf: |
| 517 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(), |
| 518 Asm.get()); |
| 519 break; |
| 520 case FT_Iasm: { |
| 521 OstreamLocker L(this); |
| 522 Cfg::emitTextHeader(MangledName, this, Asm.get()); |
| 523 Asm->emitIASBytes(this); |
| 524 } break; |
| 525 case FT_Asm: |
| 526 llvm::report_fatal_error("Unexpected FT_Asm"); |
| 527 break; |
| 528 } |
| 529 } break; |
| 530 case EmitterWorkItem::WI_Cfg: { |
| 531 if (!ALLOW_DUMP) |
| 532 llvm::report_fatal_error("WI_Cfg work item created inappropriately"); |
| 533 lowerGlobalsIfNoCodeHasBeenSeen(); |
| 534 accumulateGlobals(Item->getGlobalInits()); |
| 535 |
| 536 assert(getFlags().getOutFileType() == FT_Asm); |
| 537 std::unique_ptr<Cfg> Func = Item->getCfg(); |
| 538 // Unfortunately, we have to temporarily install the Cfg in TLS |
| 539 // because Variable::asType() uses the allocator to create the |
| 540 // differently-typed copy. |
| 541 Cfg::setCurrentCfg(Func.get()); |
| 542 Func->emit(); |
| 543 Cfg::setCurrentCfg(nullptr); |
| 544 dumpStats(Func->getFunctionName()); |
| 545 } break; |
| 473 } | 546 } |
| 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 | |
| 481 assert(getFlags().getOutFileType() == FT_Asm); | |
| 482 std::unique_ptr<Cfg> Func = Item->getCfg(); | |
| 483 // Unfortunately, we have to temporarily install the Cfg in TLS | |
| 484 // because Variable::asType() uses the allocator to create the | |
| 485 // differently-typed copy. | |
| 486 Cfg::setCurrentCfg(Func.get()); | |
| 487 Func->emit(); | |
| 488 Cfg::setCurrentCfg(nullptr); | |
| 489 dumpStats(Func->getFunctionName()); | |
| 490 } break; | |
| 491 } | 547 } |
| 548 // Update the start index for next shuffling queue |
| 549 ShuffleStartIndex = ShuffleEndIndex; |
| 492 } | 550 } |
| 493 | 551 |
| 494 // In case there are no code to be generated, we invoke the conditional | 552 // 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. | 553 // lowerGlobals again -- this is a no-op if code has been emitted. |
| 496 lowerGlobalsIfNoCodeHasBeenSeen(); | 554 lowerGlobalsIfNoCodeHasBeenSeen(); |
| 497 } | 555 } |
| 498 | 556 |
| 499 // Scan a string for S[0-9A-Z]*_ patterns and replace them with | 557 // 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 | 558 // S<num>_ where <num> is the next base-36 value. If a type name |
| 501 // legitimately contains that pattern, then the substitution will be | 559 // legitimately contains that pattern, then the substitution will be |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 921 Ctx = Func->getContext(); | 979 Ctx = Func->getContext(); |
| 922 Active = | 980 Active = |
| 923 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); | 981 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); |
| 924 if (Active) | 982 if (Active) |
| 925 Ctx->pushTimer(ID, StackID); | 983 Ctx->pushTimer(ID, StackID); |
| 926 } | 984 } |
| 927 | 985 |
| 928 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); | 986 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); |
| 929 | 987 |
| 930 } // end of namespace Ice | 988 } // end of namespace Ice |
| OLD | NEW |