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

Side by Side Diff: src/IceGlobalContext.cpp

Issue 1147023007: Subzero: Basic Block Profiler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Named constants; fflush; clang-format. 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
« no previous file with comments | « src/IceELFObjectWriter.cpp ('k') | src/IceTargetLoweringX8632.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
11 // multiple functions. 11 // multiple functions.
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #include <ctype.h> // isdigit(), isupper() 15 #include <ctype.h> // isdigit(), isupper()
16 #include <locale> // locale 16 #include <locale> // locale
17 #include <unordered_map> 17 #include <unordered_map>
18 18
19 #include "llvm/Support/Timer.h" 19 #include "llvm/Support/Timer.h"
20 20
21 #include "IceCfg.h" 21 #include "IceCfg.h"
22 #include "IceCfgNode.h"
22 #include "IceClFlags.h" 23 #include "IceClFlags.h"
23 #include "IceDefs.h" 24 #include "IceDefs.h"
24 #include "IceELFObjectWriter.h" 25 #include "IceELFObjectWriter.h"
25 #include "IceGlobalContext.h" 26 #include "IceGlobalContext.h"
26 #include "IceGlobalInits.h" 27 #include "IceGlobalInits.h"
27 #include "IceOperand.h" 28 #include "IceOperand.h"
28 #include "IceTargetLowering.h" 29 #include "IceTargetLowering.h"
29 #include "IceTimerTree.h" 30 #include "IceTimerTree.h"
30 #include "IceTypes.h" 31 #include "IceTypes.h"
31 32
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 // current function matches the -translate-only option. If 271 // current function matches the -translate-only option. If
271 // translation is disabled, just dump the high-level IR and 272 // translation is disabled, just dump the high-level IR and
272 // continue. 273 // continue.
273 if (getFlags().getDisableTranslation() || 274 if (getFlags().getDisableTranslation() ||
274 !matchSymbolName(Func->getFunctionName(), 275 !matchSymbolName(Func->getFunctionName(),
275 getFlags().getTranslateOnly())) { 276 getFlags().getTranslateOnly())) {
276 Func->dump(); 277 Func->dump();
277 Cfg::setCurrentCfg(nullptr); 278 Cfg::setCurrentCfg(nullptr);
278 continue; // Func goes out of scope and gets deleted 279 continue; // Func goes out of scope and gets deleted
279 } 280 }
281
280 Func->translate(); 282 Func->translate();
281 EmitterWorkItem *Item = nullptr; 283 EmitterWorkItem *Item = nullptr;
282 if (Func->hasError()) { 284 if (Func->hasError()) {
283 getErrorStatus()->assign(EC_Translation); 285 getErrorStatus()->assign(EC_Translation);
284 OstreamLocker L(this); 286 OstreamLocker L(this);
285 getStrError() << "ICE translation error: " << Func->getFunctionName() 287 getStrError() << "ICE translation error: " << Func->getFunctionName()
286 << ": " << Func->getError() << "\n"; 288 << ": " << Func->getError() << "\n";
287 Item = new EmitterWorkItem(Func->getSequenceNumber()); 289 Item = new EmitterWorkItem(Func->getSequenceNumber());
290 Item->setGlobalInits(Func->getGlobalInits());
288 } else { 291 } else {
289 Func->getAssembler<>()->setInternal(Func->getInternal()); 292 Func->getAssembler<>()->setInternal(Func->getInternal());
290 switch (getFlags().getOutFileType()) { 293 switch (getFlags().getOutFileType()) {
291 case FT_Elf: 294 case FT_Elf:
292 case FT_Iasm: { 295 case FT_Iasm: {
293 Func->emitIAS(); 296 Func->emitIAS();
294 // The Cfg has already emitted into the assembly buffer, so 297 // The Cfg has already emitted into the assembly buffer, so
295 // stats have been fully collected into this thread's TLS. 298 // stats have been fully collected into this thread's TLS.
296 // Dump them before TLS is reset for the next Cfg. 299 // Dump them before TLS is reset for the next Cfg.
297 dumpStats(Func->getFunctionName()); 300 dumpStats(Func->getFunctionName());
298 Assembler *Asm = Func->releaseAssembler(); 301 Assembler *Asm = Func->releaseAssembler();
299 // Copy relevant fields into Asm before Func is deleted. 302 // Copy relevant fields into Asm before Func is deleted.
300 Asm->setFunctionName(Func->getFunctionName()); 303 Asm->setFunctionName(Func->getFunctionName());
301 Item = new EmitterWorkItem(Func->getSequenceNumber(), Asm); 304 Item = new EmitterWorkItem(Func->getSequenceNumber(), Asm);
305 Item->setGlobalInits(Func->getGlobalInits());
302 } break; 306 } break;
303 case FT_Asm: 307 case FT_Asm:
304 // The Cfg has not been emitted yet, so stats are not ready 308 // The Cfg has not been emitted yet, so stats are not ready
305 // to be dumped. 309 // to be dumped.
310 std::unique_ptr<VariableDeclarationList> GlobalInits =
311 Func->getGlobalInits();
306 Item = new EmitterWorkItem(Func->getSequenceNumber(), Func.release()); 312 Item = new EmitterWorkItem(Func->getSequenceNumber(), Func.release());
313 Item->setGlobalInits(std::move(GlobalInits));
307 break; 314 break;
308 } 315 }
309 } 316 }
310 Cfg::setCurrentCfg(nullptr); 317 Cfg::setCurrentCfg(nullptr);
311 assert(Item); 318 assert(Item);
312 emitQueueBlockingPush(Item); 319 emitQueueBlockingPush(Item);
313 // The Cfg now gets deleted as Func goes out of scope. 320 // The Cfg now gets deleted as Func goes out of scope.
314 } 321 }
315 } 322 }
316 323
317 namespace { 324 namespace {
318 325
326 // Adds an array of pointers to all the profiler-generated globals. The
327 // __Sz_profile_summary function iterates over this array for printing the
328 // profiling counters.
329 VariableDeclaration *blockProfileInfo(const VariableDeclarationList &Globals) {
330 auto *Var = VariableDeclaration::create();
331 Var->setAlignment(typeWidthInBytes(IceType_i64));
332 Var->setIsConstant(true);
333
334 // Note: if you change this symbol, make sure to update
335 // runtime/szrt_profiler.c as well.
336 Var->setName("__Sz_block_profile_info");
337 Var->setLinkage(llvm::GlobalValue::ExternalLinkage);
338 for (const VariableDeclaration *Global : Globals) {
339 if (Cfg::isProfileGlobal(*Global)) {
340 constexpr RelocOffsetT BlockExecutionCounterOffset = 0;
341 Var->addInitializer(new VariableDeclaration::RelocInitializer(
342 Global, BlockExecutionCounterOffset));
343 }
344 }
345
346 // This adds a 64-bit sentinel entry to the end of our array. For 32-bit
347 // architectures this will waste 4 bytes.
348 const SizeT Sizeof64BitNullPtr = typeWidthInBytes(IceType_i64);
349 Var->addInitializer(
350 new VariableDeclaration::ZeroInitializer(Sizeof64BitNullPtr));
351
352 return Var;
353 }
354
355 void addBlockProfileInfoArrayToGlobals(VariableDeclarationList *Globals) {
356 // Purposefully create the Var temp to prevent bugs in case the compiler
357 // reorders instructions in a way that Globals is extended before the call
358 // to profileInfoArray.
359 VariableDeclaration *Var = blockProfileInfo(*Globals);
360 Globals->push_back(Var);
361 }
362
319 void lowerGlobals(GlobalContext *Ctx, 363 void lowerGlobals(GlobalContext *Ctx,
320 std::unique_ptr<VariableDeclarationList> VariableDeclarations, 364 std::unique_ptr<VariableDeclarationList> VariableDeclarations,
321 TargetDataLowering *DataLowering) { 365 TargetDataLowering *DataLowering) {
322 TimerMarker T(TimerStack::TT_emitGlobalInitializers, Ctx); 366 TimerMarker T(TimerStack::TT_emitGlobalInitializers, Ctx);
323 const bool DumpGlobalVariables = ALLOW_DUMP && Ctx->getFlags().getVerbose() && 367 const bool DumpGlobalVariables = ALLOW_DUMP && Ctx->getFlags().getVerbose() &&
324 Ctx->getFlags().getVerboseFocusOn().empty(); 368 Ctx->getFlags().getVerboseFocusOn().empty();
325 if (DumpGlobalVariables) { 369 if (DumpGlobalVariables) {
326 OstreamLocker L(Ctx); 370 OstreamLocker L(Ctx);
327 Ostream &Stream = Ctx->getStrDump(); 371 Ostream &Stream = Ctx->getStrDump();
328 for (const Ice::VariableDeclaration *Global : *VariableDeclarations) { 372 for (const Ice::VariableDeclaration *Global : *VariableDeclarations) {
329 Global->dump(Ctx, Stream); 373 Global->dump(Ctx, Stream);
330 } 374 }
331 } 375 }
332 if (Ctx->getFlags().getDisableTranslation()) 376 if (Ctx->getFlags().getDisableTranslation())
333 return; 377 return;
378
379 // There should be no need to emit the block_profile_info array if profiling
380 // is disabled. In practice, given that szrt_profiler.o will always be
381 // embedded in the application, we need to add it. In a non-profiled build
382 // this array will only contain the nullptr terminator.
383 addBlockProfileInfoArrayToGlobals(VariableDeclarations.get());
384
334 DataLowering->lowerGlobals(std::move(VariableDeclarations)); 385 DataLowering->lowerGlobals(std::move(VariableDeclarations));
335 } 386 }
336 387
337 // Ensure Pending is large enough that Pending[Index] is valid. 388 // Ensure Pending is large enough that Pending[Index] is valid.
338 void resizePending(std::vector<EmitterWorkItem *> &Pending, uint32_t Index) { 389 void resizePending(std::vector<EmitterWorkItem *> &Pending, uint32_t Index) {
339 if (Index >= Pending.size()) 390 if (Index >= Pending.size())
340 Pending.resize(Index + 1); 391 Pending.resize(Index + 1);
341 } 392 }
342 393
394 void addAllIfNotNull(std::unique_ptr<VariableDeclarationList> src,
395 VariableDeclarationList *dst) {
396 if (src != nullptr) {
397 dst->insert(dst->end(), src->begin(), src->end());
398 }
399 }
400
343 } // end of anonymous namespace 401 } // end of anonymous namespace
344 402
345 void GlobalContext::emitItems() { 403 void GlobalContext::emitItems() {
346 const bool Threaded = !getFlags().isSequential(); 404 const bool Threaded = !getFlags().isSequential();
347 // Pending is a vector containing the reassembled, ordered list of 405 // Pending is a vector containing the reassembled, ordered list of
348 // work items. When we're ready for the next item, we first check 406 // work items. When we're ready for the next item, we first check
349 // whether it's in the Pending list. If not, we take an item from 407 // whether it's in the Pending list. If not, we take an item from
350 // the work queue, and if it's not the item we're waiting for, we 408 // the work queue, and if it's not the item we're waiting for, we
351 // insert it into Pending and repeat. The work item is deleted 409 // insert it into Pending and repeat. The work item is deleted
352 // after it is processed. 410 // after it is processed.
411 std::unique_ptr<VariableDeclarationList> GlobalInits(
412 new VariableDeclarationList());
353 std::vector<EmitterWorkItem *> Pending; 413 std::vector<EmitterWorkItem *> Pending;
354 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); 414 uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
355 while (true) { 415 while (true) {
356 resizePending(Pending, DesiredSequenceNumber); 416 resizePending(Pending, DesiredSequenceNumber);
357 // See if Pending contains DesiredSequenceNumber. 417 // See if Pending contains DesiredSequenceNumber.
358 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber]; 418 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber];
359 if (RawItem == nullptr) 419 if (RawItem == nullptr)
360 RawItem = emitQueueBlockingPop(); 420 RawItem = emitQueueBlockingPop();
361 if (RawItem == nullptr) 421 if (RawItem == nullptr)
362 return; 422 break;
363 uint32_t ItemSeq = RawItem->getSequenceNumber(); 423 uint32_t ItemSeq = RawItem->getSequenceNumber();
364 if (Threaded && ItemSeq != DesiredSequenceNumber) { 424 if (Threaded && ItemSeq != DesiredSequenceNumber) {
365 resizePending(Pending, ItemSeq); 425 resizePending(Pending, ItemSeq);
366 Pending[ItemSeq] = RawItem; 426 Pending[ItemSeq] = RawItem;
367 continue; 427 continue;
368 } 428 }
369 429
370 std::unique_ptr<EmitterWorkItem> Item(RawItem); 430 std::unique_ptr<EmitterWorkItem> Item(RawItem);
371 ++DesiredSequenceNumber; 431 ++DesiredSequenceNumber;
372 switch (Item->getKind()) { 432 switch (Item->getKind()) {
373 case EmitterWorkItem::WI_Nop: 433 case EmitterWorkItem::WI_Nop:
374 break; 434 break;
375 case EmitterWorkItem::WI_GlobalInits: { 435 case EmitterWorkItem::WI_GlobalInits: {
376 lowerGlobals(this, Item->getGlobalInits(), 436 addAllIfNotNull(Item->getGlobalInits(), GlobalInits.get());
377 TargetDataLowering::createLowering(this).get());
378 } break; 437 } break;
379 case EmitterWorkItem::WI_Asm: { 438 case EmitterWorkItem::WI_Asm: {
439 addAllIfNotNull(Item->getGlobalInits(), GlobalInits.get());
380 std::unique_ptr<Assembler> Asm = Item->getAsm(); 440 std::unique_ptr<Assembler> Asm = Item->getAsm();
381 Asm->alignFunction(); 441 Asm->alignFunction();
382 IceString MangledName = mangleName(Asm->getFunctionName()); 442 IceString MangledName = mangleName(Asm->getFunctionName());
383 switch (getFlags().getOutFileType()) { 443 switch (getFlags().getOutFileType()) {
384 case FT_Elf: 444 case FT_Elf:
385 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(), 445 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(),
386 Asm.get()); 446 Asm.get());
387 break; 447 break;
388 case FT_Iasm: { 448 case FT_Iasm: {
389 OstreamLocker L(this); 449 OstreamLocker L(this);
390 Cfg::emitTextHeader(MangledName, this, Asm.get()); 450 Cfg::emitTextHeader(MangledName, this, Asm.get());
391 Asm->emitIASBytes(this); 451 Asm->emitIASBytes(this);
392 } break; 452 } break;
393 case FT_Asm: 453 case FT_Asm:
394 llvm::report_fatal_error("Unexpected FT_Asm"); 454 llvm::report_fatal_error("Unexpected FT_Asm");
395 break; 455 break;
396 } 456 }
397 } break; 457 } break;
398 case EmitterWorkItem::WI_Cfg: { 458 case EmitterWorkItem::WI_Cfg: {
399 if (!ALLOW_DUMP) 459 if (!ALLOW_DUMP)
400 llvm::report_fatal_error("WI_Cfg work item created inappropriately"); 460 llvm::report_fatal_error("WI_Cfg work item created inappropriately");
461
462 addAllIfNotNull(Item->getGlobalInits(), GlobalInits.get());
463
401 assert(getFlags().getOutFileType() == FT_Asm); 464 assert(getFlags().getOutFileType() == FT_Asm);
402 std::unique_ptr<Cfg> Func = Item->getCfg(); 465 std::unique_ptr<Cfg> Func = Item->getCfg();
403 // Unfortunately, we have to temporarily install the Cfg in TLS 466 // Unfortunately, we have to temporarily install the Cfg in TLS
404 // because Variable::asType() uses the allocator to create the 467 // because Variable::asType() uses the allocator to create the
405 // differently-typed copy. 468 // differently-typed copy.
406 Cfg::setCurrentCfg(Func.get()); 469 Cfg::setCurrentCfg(Func.get());
407 Func->emit(); 470 Func->emit();
408 Cfg::setCurrentCfg(nullptr); 471 Cfg::setCurrentCfg(nullptr);
409 dumpStats(Func->getFunctionName()); 472 dumpStats(Func->getFunctionName());
410 } break; 473 } break;
411 } 474 }
412 } 475 }
476
477 lowerGlobals(this, std::move(GlobalInits),
478 TargetDataLowering::createLowering(this).get());
413 } 479 }
414 480
415 // Scan a string for S[0-9A-Z]*_ patterns and replace them with 481 // Scan a string for S[0-9A-Z]*_ patterns and replace them with
416 // S<num>_ where <num> is the next base-36 value. If a type name 482 // S<num>_ where <num> is the next base-36 value. If a type name
417 // legitimately contains that pattern, then the substitution will be 483 // legitimately contains that pattern, then the substitution will be
418 // made in error and most likely the link will fail. In this case, 484 // made in error and most likely the link will fail. In this case,
419 // the test classes can be rewritten not to use that pattern, which is 485 // the test classes can be rewritten not to use that pattern, which is
420 // much simpler and more reliable than implementing a full demangling 486 // much simpler and more reliable than implementing a full demangling
421 // parser. Another substitution-in-error may occur if a type 487 // parser. Another substitution-in-error may occur if a type
422 // identifier ends with the pattern S[0-9A-Z]*, because an immediately 488 // identifier ends with the pattern S[0-9A-Z]*, because an immediately
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
829 Ctx = Func->getContext(); 895 Ctx = Func->getContext();
830 Active = 896 Active =
831 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); 897 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled();
832 if (Active) 898 if (Active)
833 Ctx->pushTimer(ID, StackID); 899 Ctx->pushTimer(ID, StackID);
834 } 900 }
835 901
836 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); 902 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
837 903
838 } // end of namespace Ice 904 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceELFObjectWriter.cpp ('k') | src/IceTargetLoweringX8632.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698