Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: src/IceGlobalContext.cpp

Issue 1206723003: Function Layout, Global Variable Layout and Pooled Constants Layout Reordering (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698