| 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 /// \file | 10 /// \file |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 // translation is disabled, just dump the high-level IR and | 312 // translation is disabled, just dump the high-level IR and |
| 313 // continue. | 313 // continue. |
| 314 if (getFlags().getDisableTranslation() || | 314 if (getFlags().getDisableTranslation() || |
| 315 !matchSymbolName(Func->getFunctionName(), | 315 !matchSymbolName(Func->getFunctionName(), |
| 316 getFlags().getTranslateOnly())) { | 316 getFlags().getTranslateOnly())) { |
| 317 Func->dump(); | 317 Func->dump(); |
| 318 continue; // Func goes out of scope and gets deleted | 318 continue; // Func goes out of scope and gets deleted |
| 319 } | 319 } |
| 320 | 320 |
| 321 Func->translate(); | 321 Func->translate(); |
| 322 EmitterWorkItem *Item = nullptr; | 322 std::unique_ptr<EmitterWorkItem> Item; |
| 323 if (Func->hasError()) { | 323 if (Func->hasError()) { |
| 324 getErrorStatus()->assign(EC_Translation); | 324 getErrorStatus()->assign(EC_Translation); |
| 325 OstreamLocker L(this); | 325 OstreamLocker L(this); |
| 326 getStrError() << "ICE translation error: " << Func->getFunctionName() | 326 getStrError() << "ICE translation error: " << Func->getFunctionName() |
| 327 << ": " << Func->getError() << ": " | 327 << ": " << Func->getError() << ": " |
| 328 << Func->getFunctionNameAndSize() << "\n"; | 328 << Func->getFunctionNameAndSize() << "\n"; |
| 329 Item = new EmitterWorkItem(Func->getSequenceNumber()); | 329 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber()); |
| 330 } else { | 330 } else { |
| 331 Func->getAssembler<>()->setInternal(Func->getInternal()); | 331 Func->getAssembler<>()->setInternal(Func->getInternal()); |
| 332 switch (getFlags().getOutFileType()) { | 332 switch (getFlags().getOutFileType()) { |
| 333 case FT_Elf: | 333 case FT_Elf: |
| 334 case FT_Iasm: { | 334 case FT_Iasm: { |
| 335 Func->emitIAS(); | 335 Func->emitIAS(); |
| 336 // The Cfg has already emitted into the assembly buffer, so | 336 // The Cfg has already emitted into the assembly buffer, so |
| 337 // stats have been fully collected into this thread's TLS. | 337 // stats have been fully collected into this thread's TLS. |
| 338 // Dump them before TLS is reset for the next Cfg. | 338 // Dump them before TLS is reset for the next Cfg. |
| 339 dumpStats(Func->getFunctionNameAndSize()); | 339 dumpStats(Func->getFunctionNameAndSize()); |
| 340 Assembler *Asm = Func->releaseAssembler(); | 340 auto Asm = Func->releaseAssembler(); |
| 341 // Copy relevant fields into Asm before Func is deleted. | 341 // Copy relevant fields into Asm before Func is deleted. |
| 342 Asm->setFunctionName(Func->getFunctionName()); | 342 Asm->setFunctionName(Func->getFunctionName()); |
| 343 Item = new EmitterWorkItem(Func->getSequenceNumber(), Asm); | 343 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber(), |
| 344 std::move(Asm)); |
| 344 Item->setGlobalInits(Func->getGlobalInits()); | 345 Item->setGlobalInits(Func->getGlobalInits()); |
| 345 } break; | 346 } break; |
| 346 case FT_Asm: | 347 case FT_Asm: |
| 347 // The Cfg has not been emitted yet, so stats are not ready | 348 // The Cfg has not been emitted yet, so stats are not ready |
| 348 // to be dumped. | 349 // to be dumped. |
| 349 std::unique_ptr<VariableDeclarationList> GlobalInits = | 350 std::unique_ptr<VariableDeclarationList> GlobalInits = |
| 350 Func->getGlobalInits(); | 351 Func->getGlobalInits(); |
| 351 Item = new EmitterWorkItem(Func->getSequenceNumber(), Func.release()); | 352 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber(), |
| 353 std::move(Func)); |
| 352 Item->setGlobalInits(std::move(GlobalInits)); | 354 Item->setGlobalInits(std::move(GlobalInits)); |
| 353 break; | 355 break; |
| 354 } | 356 } |
| 355 } | 357 } |
| 356 assert(Item); | 358 assert(Item != nullptr); |
| 357 emitQueueBlockingPush(Item); | 359 emitQueueBlockingPush(std::move(Item)); |
| 358 // The Cfg now gets deleted as Func goes out of scope. | 360 // The Cfg now gets deleted as Func goes out of scope. |
| 359 } | 361 } |
| 360 } | 362 } |
| 361 | 363 |
| 362 namespace { | 364 namespace { |
| 363 | 365 |
| 364 // Ensure Pending is large enough that Pending[Index] is valid. | 366 // Ensure Pending is large enough that Pending[Index] is valid. |
| 365 void resizePending(std::vector<EmitterWorkItem *> &Pending, uint32_t Index) { | 367 void resizePending(std::vector<std::unique_ptr<EmitterWorkItem>> *Pending, |
| 366 if (Index >= Pending.size()) | 368 uint32_t Index) { |
| 367 Utils::reserveAndResize(Pending, Index + 1); | 369 if (Index >= Pending->size()) |
| 370 Utils::reserveAndResize(*Pending, Index + 1); |
| 368 } | 371 } |
| 369 | 372 |
| 370 } // end of anonymous namespace | 373 } // end of anonymous namespace |
| 371 | 374 |
| 372 void GlobalContext::emitFileHeader() { | 375 void GlobalContext::emitFileHeader() { |
| 373 TimerMarker T1(Ice::TimerStack::TT_emitAsm, this); | 376 TimerMarker T1(Ice::TimerStack::TT_emitAsm, this); |
| 374 if (getFlags().getOutFileType() == FT_Elf) { | 377 if (getFlags().getOutFileType() == FT_Elf) { |
| 375 getObjectWriter()->writeInitialELFHeader(); | 378 getObjectWriter()->writeInitialELFHeader(); |
| 376 } else { | 379 } else { |
| 377 if (!BuildDefs::dump()) { | 380 if (!BuildDefs::dump()) { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 } | 467 } |
| 465 | 468 |
| 466 void GlobalContext::emitItems() { | 469 void GlobalContext::emitItems() { |
| 467 const bool Threaded = !getFlags().isSequential(); | 470 const bool Threaded = !getFlags().isSequential(); |
| 468 // Pending is a vector containing the reassembled, ordered list of | 471 // Pending is a vector containing the reassembled, ordered list of |
| 469 // work items. When we're ready for the next item, we first check | 472 // work items. When we're ready for the next item, we first check |
| 470 // whether it's in the Pending list. If not, we take an item from | 473 // whether it's in the Pending list. If not, we take an item from |
| 471 // the work queue, and if it's not the item we're waiting for, we | 474 // the work queue, and if it's not the item we're waiting for, we |
| 472 // insert it into Pending and repeat. The work item is deleted | 475 // insert it into Pending and repeat. The work item is deleted |
| 473 // after it is processed. | 476 // after it is processed. |
| 474 std::vector<EmitterWorkItem *> Pending; | 477 std::vector<std::unique_ptr<EmitterWorkItem>> Pending; |
| 475 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); | 478 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); |
| 476 uint32_t ShuffleStartIndex = DesiredSequenceNumber; | 479 uint32_t ShuffleStartIndex = DesiredSequenceNumber; |
| 477 uint32_t ShuffleEndIndex = DesiredSequenceNumber; | 480 uint32_t ShuffleEndIndex = DesiredSequenceNumber; |
| 478 bool EmitQueueEmpty = false; | 481 bool EmitQueueEmpty = false; |
| 479 const uint32_t ShuffleWindowSize = | 482 const uint32_t ShuffleWindowSize = |
| 480 std::max(1u, getFlags().getReorderFunctionsWindowSize()); | 483 std::max(1u, getFlags().getReorderFunctionsWindowSize()); |
| 481 bool Shuffle = Threaded && getFlags().shouldReorderFunctions(); | 484 bool Shuffle = Threaded && getFlags().shouldReorderFunctions(); |
| 482 // Create a random number generator for function reordering. | 485 // Create a random number generator for function reordering. |
| 483 RandomNumberGenerator RNG(getFlags().getRandomSeed(), RPE_FunctionReordering); | 486 RandomNumberGenerator RNG(getFlags().getRandomSeed(), RPE_FunctionReordering); |
| 484 | 487 |
| 485 while (!EmitQueueEmpty) { | 488 while (!EmitQueueEmpty) { |
| 486 resizePending(Pending, DesiredSequenceNumber); | 489 resizePending(&Pending, DesiredSequenceNumber); |
| 487 // See if Pending contains DesiredSequenceNumber. | 490 // See if Pending contains DesiredSequenceNumber. |
| 488 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber]; | 491 if (Pending[DesiredSequenceNumber] == nullptr) { |
| 489 if (RawItem == nullptr) { | |
| 490 // We need to fetch an EmitterWorkItem from the queue. | 492 // We need to fetch an EmitterWorkItem from the queue. |
| 491 RawItem = emitQueueBlockingPop(); | 493 auto RawItem = emitQueueBlockingPop(); |
| 492 if (RawItem == nullptr) { | 494 if (RawItem == nullptr) { |
| 493 // This is the notifier for an empty queue. | 495 // This is the notifier for an empty queue. |
| 494 EmitQueueEmpty = true; | 496 EmitQueueEmpty = true; |
| 495 } else { | 497 } else { |
| 496 // We get an EmitterWorkItem, we need to add it to Pending. | 498 // We get an EmitterWorkItem, we need to add it to Pending. |
| 497 uint32_t ItemSeq = RawItem->getSequenceNumber(); | 499 uint32_t ItemSeq = RawItem->getSequenceNumber(); |
| 498 if (Threaded && ItemSeq != DesiredSequenceNumber) { | 500 if (Threaded && ItemSeq != DesiredSequenceNumber) { |
| 499 // Not the desired one, add it to Pending but do not increase | 501 // Not the desired one, add it to Pending but do not increase |
| 500 // DesiredSequenceNumber. Continue the loop, do not emit the item. | 502 // DesiredSequenceNumber. Continue the loop, do not emit the item. |
| 501 resizePending(Pending, ItemSeq); | 503 resizePending(&Pending, ItemSeq); |
| 502 Pending[ItemSeq] = RawItem; | 504 Pending[ItemSeq] = std::move(RawItem); |
| 503 continue; | 505 continue; |
| 504 } | 506 } |
| 505 // ItemSeq == DesiredSequenceNumber, we need to check if we should | 507 // ItemSeq == DesiredSequenceNumber, we need to check if we should |
| 506 // emit it or not. If !Threaded, we're OK with ItemSeq != | 508 // emit it or not. If !Threaded, we're OK with ItemSeq != |
| 507 // DesiredSequenceNumber. | 509 // DesiredSequenceNumber. |
| 508 Pending[DesiredSequenceNumber] = RawItem; | 510 Pending[DesiredSequenceNumber] = std::move(RawItem); |
| 509 } | 511 } |
| 510 } | 512 } |
| 513 const auto *CurrentWorkItem = Pending[DesiredSequenceNumber].get(); |
| 514 |
| 511 // We have the desired EmitterWorkItem or nullptr as the end notifier. | 515 // We have the desired EmitterWorkItem or nullptr as the end notifier. |
| 512 // If the emitter queue is not empty, increase DesiredSequenceNumber and | 516 // If the emitter queue is not empty, increase DesiredSequenceNumber and |
| 513 // ShuffleEndIndex. | 517 // ShuffleEndIndex. |
| 514 if (!EmitQueueEmpty) { | 518 if (!EmitQueueEmpty) { |
| 515 DesiredSequenceNumber++; | 519 DesiredSequenceNumber++; |
| 516 ShuffleEndIndex++; | 520 ShuffleEndIndex++; |
| 517 } | 521 } |
| 518 | 522 |
| 519 if (Shuffle) { | 523 if (Shuffle) { |
| 520 // Continue fetching EmitterWorkItem if function reordering is turned on, | 524 // Continue fetching EmitterWorkItem if function reordering is turned on, |
| 521 // and emit queue is not empty, and the number of consecutive pending | 525 // and emit queue is not empty, and the number of consecutive pending |
| 522 // items is smaller than the window size, and RawItem is not a | 526 // items is smaller than the window size, and RawItem is not a |
| 523 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid | 527 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid |
| 524 // holding an arbitrarily large GlobalDeclarationList. | 528 // holding an arbitrarily large GlobalDeclarationList. |
| 525 if (!EmitQueueEmpty && | 529 if (!EmitQueueEmpty && |
| 526 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize && | 530 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize && |
| 527 RawItem->getKind() != EmitterWorkItem::WI_GlobalInits) | 531 CurrentWorkItem->getKind() != EmitterWorkItem::WI_GlobalInits) |
| 528 continue; | 532 continue; |
| 529 | 533 |
| 530 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to | 534 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to |
| 531 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the | 535 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the |
| 532 // pending items from Pending[ShuffleStartIndex] to | 536 // pending items from Pending[ShuffleStartIndex] to |
| 533 // Pending[ShuffleEndIndex]. | 537 // Pending[ShuffleEndIndex]. |
| 534 RandomShuffle(Pending.begin() + ShuffleStartIndex, | 538 RandomShuffle(Pending.begin() + ShuffleStartIndex, |
| 535 Pending.begin() + ShuffleEndIndex, | 539 Pending.begin() + ShuffleEndIndex, |
| 536 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); | 540 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); |
| 537 } | 541 } |
| 538 | 542 |
| 539 // Emit the item from ShuffleStartIndex to ShuffleEndIndex. | 543 // Emit the item from ShuffleStartIndex to ShuffleEndIndex. |
| 540 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) { | 544 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) { |
| 541 std::unique_ptr<EmitterWorkItem> Item(Pending[I]); | 545 std::unique_ptr<EmitterWorkItem> Item = std::move(Pending[I]); |
| 542 | 546 |
| 543 switch (Item->getKind()) { | 547 switch (Item->getKind()) { |
| 544 case EmitterWorkItem::WI_Nop: | 548 case EmitterWorkItem::WI_Nop: |
| 545 break; | 549 break; |
| 546 case EmitterWorkItem::WI_GlobalInits: { | 550 case EmitterWorkItem::WI_GlobalInits: { |
| 547 accumulateGlobals(Item->getGlobalInits()); | 551 accumulateGlobals(Item->getGlobalInits()); |
| 548 } break; | 552 } break; |
| 549 case EmitterWorkItem::WI_Asm: { | 553 case EmitterWorkItem::WI_Asm: { |
| 550 lowerGlobalsIfNoCodeHasBeenSeen(); | 554 lowerGlobalsIfNoCodeHasBeenSeen(); |
| 551 accumulateGlobals(Item->getGlobalInits()); | 555 accumulateGlobals(Item->getGlobalInits()); |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 } | 859 } |
| 856 | 860 |
| 857 // Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr at the | 861 // Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr at the |
| 858 // interface to take and transfer ownership, but they internally store the raw | 862 // interface to take and transfer ownership, but they internally store the raw |
| 859 // Cfg pointer in the work queue. This allows e.g. future queue optimizations | 863 // Cfg pointer in the work queue. This allows e.g. future queue optimizations |
| 860 // such as the use of atomics to modify queue elements. | 864 // such as the use of atomics to modify queue elements. |
| 861 void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) { | 865 void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) { |
| 862 assert(Func); | 866 assert(Func); |
| 863 { | 867 { |
| 864 TimerMarker _(TimerStack::TT_qTransPush, this); | 868 TimerMarker _(TimerStack::TT_qTransPush, this); |
| 865 OptQ.blockingPush(Func.release()); | 869 OptQ.blockingPush(std::move(Func)); |
| 866 } | 870 } |
| 867 if (getFlags().isSequential()) | 871 if (getFlags().isSequential()) |
| 868 translateFunctions(); | 872 translateFunctions(); |
| 869 } | 873 } |
| 870 | 874 |
| 871 std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() { | 875 std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() { |
| 872 TimerMarker _(TimerStack::TT_qTransPop, this); | 876 TimerMarker _(TimerStack::TT_qTransPop, this); |
| 873 return std::unique_ptr<Cfg>(OptQ.blockingPop()); | 877 return std::unique_ptr<Cfg>(OptQ.blockingPop()); |
| 874 } | 878 } |
| 875 | 879 |
| 876 void GlobalContext::emitQueueBlockingPush(EmitterWorkItem *Item) { | 880 void GlobalContext::emitQueueBlockingPush( |
| 881 std::unique_ptr<EmitterWorkItem> Item) { |
| 877 assert(Item); | 882 assert(Item); |
| 878 { | 883 { |
| 879 TimerMarker _(TimerStack::TT_qEmitPush, this); | 884 TimerMarker _(TimerStack::TT_qEmitPush, this); |
| 880 EmitQ.blockingPush(Item); | 885 EmitQ.blockingPush(std::move(Item)); |
| 881 } | 886 } |
| 882 if (getFlags().isSequential()) | 887 if (getFlags().isSequential()) |
| 883 emitItems(); | 888 emitItems(); |
| 884 } | 889 } |
| 885 | 890 |
| 886 EmitterWorkItem *GlobalContext::emitQueueBlockingPop() { | 891 std::unique_ptr<EmitterWorkItem> GlobalContext::emitQueueBlockingPop() { |
| 887 TimerMarker _(TimerStack::TT_qEmitPop, this); | 892 TimerMarker _(TimerStack::TT_qEmitPop, this); |
| 888 return EmitQ.blockingPop(); | 893 return EmitQ.blockingPop(); |
| 889 } | 894 } |
| 890 | 895 |
| 891 void GlobalContext::dumpStats(const IceString &Name, bool Final) { | 896 void GlobalContext::dumpStats(const IceString &Name, bool Final) { |
| 892 if (!getFlags().getDumpStats()) | 897 if (!getFlags().getDumpStats()) |
| 893 return; | 898 return; |
| 894 if (Final) { | 899 if (Final) { |
| 895 getStatsCumulative()->dump(Name, this); | 900 getStatsCumulative()->dump(Name, this); |
| 896 } else { | 901 } else { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 Ctx = Func->getContext(); | 943 Ctx = Func->getContext(); |
| 939 Active = | 944 Active = |
| 940 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); | 945 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); |
| 941 if (Active) | 946 if (Active) |
| 942 Ctx->pushTimer(ID, StackID); | 947 Ctx->pushTimer(ID, StackID); |
| 943 } | 948 } |
| 944 | 949 |
| 945 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); | 950 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); |
| 946 | 951 |
| 947 } // end of namespace Ice | 952 } // end of namespace Ice |
| OLD | NEW |