@@ -49,10 +49,6 @@ llvm::cl::opt<unsigned> SILNumOptPassesToRun(
49
49
" sil-opt-pass-count" , llvm::cl::init(UINT_MAX),
50
50
llvm::cl::desc(" Stop optimizing after <N> optimization passes" ));
51
51
52
- llvm::cl::opt<unsigned > SILFunctionPassPipelineLimit (" sil-pipeline-limit" ,
53
- llvm::cl::init (10 ),
54
- llvm::cl::desc(" " ));
55
-
56
52
llvm::cl::opt<std::string> SILBreakOnFun (
57
53
" sil-break-on-function" , llvm::cl::init(" " ),
58
54
llvm::cl::desc(
@@ -274,110 +270,92 @@ static bool breakBeforeRunning(StringRef fnName, StringRef passName) {
274
270
return fnName == SILBreakOnFun && passName == SILBreakOnPass;
275
271
}
276
272
277
- void SILPassManager::runPassesOnFunction (PassList FuncTransforms,
278
- SILFunction *F,
279
- bool runToCompletion) {
280
-
281
- const SILOptions &Options = getOptions ();
282
-
283
- CompletedPasses &completedPasses = CompletedPassesMap[F];
273
+ void SILPassManager::runPassOnFunction (SILFunctionTransform *SFT,
274
+ SILFunction *F) {
284
275
285
276
assert (analysesUnlocked () && " Expected all analyses to be unlocked!" );
286
277
287
- for (auto SFT : FuncTransforms) {
288
- PrettyStackTraceSILFunctionTransform X (SFT, NumPassesRun);
289
- DebugPrintEnabler DebugPrint (NumPassesRun);
290
-
291
- SFT->injectPassManager (this );
292
- SFT->injectFunction (F);
293
-
294
- // If nothing changed since the last run of this pass, we can skip this
295
- // pass.
296
- if (completedPasses.test ((size_t )SFT->getPassKind ()) &&
297
- !SILDisableSkippingPasses) {
298
- if (SILPrintPassName)
299
- llvm::dbgs () << " (Skip) Stage: " << StageName
300
- << " Pass: " << SFT->getName ()
301
- << " , Function: " << F->getName () << " \n " ;
302
- continue ;
303
- }
304
-
305
- if (isDisabled (SFT)) {
306
- if (SILPrintPassName)
307
- llvm::dbgs () << " (Disabled) Stage: " << StageName
308
- << " Pass: " << SFT->getName ()
309
- << " , Function: " << F->getName () << " \n " ;
310
- continue ;
311
- }
278
+ PrettyStackTraceSILFunctionTransform X (SFT, NumPassesRun);
279
+ DebugPrintEnabler DebugPrint (NumPassesRun);
312
280
313
- CurrentPassHasInvalidated = false ;
281
+ SFT->injectPassManager (this );
282
+ SFT->injectFunction (F);
314
283
284
+ // If nothing changed since the last run of this pass, we can skip this
285
+ // pass.
286
+ CompletedPasses &completedPasses = CompletedPassesMap[F];
287
+ if (completedPasses.test ((size_t )SFT->getPassKind ()) &&
288
+ !SILDisableSkippingPasses) {
315
289
if (SILPrintPassName)
316
- llvm::dbgs () << " # " << NumPassesRun << " Stage: " << StageName
290
+ llvm::dbgs () << " (Skip) Stage: " << StageName
317
291
<< " Pass: " << SFT->getName ()
318
292
<< " , Function: " << F->getName () << " \n " ;
293
+ return ;
294
+ }
319
295
320
- if (doPrintBefore (SFT, F)) {
321
- llvm::dbgs () << " *** SIL function before " << StageName << " "
322
- << SFT->getName () << " (" << NumOptimizationIterations
323
- << " ) ***\n " ;
324
- F->dump (Options.EmitVerboseSIL );
325
- }
296
+ if (isDisabled (SFT)) {
297
+ if (SILPrintPassName)
298
+ llvm::dbgs () << " (Disabled) Stage: " << StageName
299
+ << " Pass: " << SFT->getName ()
300
+ << " , Function: " << F->getName () << " \n " ;
301
+ return ;
302
+ }
326
303
327
- llvm::sys::TimeValue StartTime = llvm::sys::TimeValue::now ();
328
- Mod->registerDeleteNotificationHandler (SFT);
329
- if (breakBeforeRunning (F->getName (), SFT->getName ()))
330
- LLVM_BUILTIN_DEBUGTRAP;
331
- SFT->run ();
332
- assert (analysesUnlocked () && " Expected all analyses to be unlocked!" );
333
- Mod->removeDeleteNotificationHandler (SFT);
334
-
335
- // Did running the transform result in new functions being added
336
- // to the top of our worklist?
337
- bool newFunctionsAdded = (F != FunctionWorklist.back ());
338
-
339
- if (SILPrintPassTime) {
340
- auto Delta =
341
- llvm::sys::TimeValue::now ().nanoseconds () - StartTime.nanoseconds ();
342
- llvm::dbgs () << Delta << " (" << SFT->getName () << " ," << F->getName ()
343
- << " )\n " ;
344
- }
304
+ CurrentPassHasInvalidated = false ;
345
305
346
- // If this pass invalidated anything, print and verify.
347
- if (doPrintAfter (SFT, F, CurrentPassHasInvalidated && SILPrintAll)) {
348
- llvm::dbgs () << " *** SIL function after " << StageName << " "
349
- << SFT->getName () << " (" << NumOptimizationIterations
350
- << " ) ***\n " ;
351
- F->dump (Options.EmitVerboseSIL );
352
- }
306
+ if (SILPrintPassName)
307
+ llvm::dbgs () << " #" << NumPassesRun << " Stage: " << StageName
308
+ << " Pass: " << SFT->getName ()
309
+ << " , Function: " << F->getName () << " \n " ;
353
310
354
- // Remember if this pass didn't change anything.
355
- if (!CurrentPassHasInvalidated)
356
- completedPasses.set ((size_t )SFT->getPassKind ());
311
+ if (doPrintBefore (SFT, F)) {
312
+ llvm::dbgs () << " *** SIL function before " << StageName << " "
313
+ << SFT->getName () << " (" << NumOptimizationIterations
314
+ << " ) ***\n " ;
315
+ F->dump (getOptions ().EmitVerboseSIL );
316
+ }
357
317
358
- if (Options.VerifyAll &&
359
- (CurrentPassHasInvalidated || SILVerifyWithoutInvalidation)) {
360
- F->verify ();
361
- verifyAnalyses (F);
362
- }
318
+ llvm::sys::TimeValue StartTime = llvm::sys::TimeValue::now ();
319
+ Mod->registerDeleteNotificationHandler (SFT);
320
+ if (breakBeforeRunning (F->getName (), SFT->getName ()))
321
+ LLVM_BUILTIN_DEBUGTRAP;
322
+ SFT->run ();
323
+ assert (analysesUnlocked () && " Expected all analyses to be unlocked!" );
324
+ Mod->removeDeleteNotificationHandler (SFT);
363
325
364
- ++NumPassesRun;
326
+ if (SILPrintPassTime) {
327
+ auto Delta =
328
+ llvm::sys::TimeValue::now ().nanoseconds () - StartTime.nanoseconds ();
329
+ llvm::dbgs () << Delta << " (" << SFT->getName () << " ," << F->getName ()
330
+ << " )\n " ;
331
+ }
365
332
366
- if (!continueTransforming ())
367
- return ;
333
+ // If this pass invalidated anything, print and verify.
334
+ if (doPrintAfter (SFT, F, CurrentPassHasInvalidated && SILPrintAll)) {
335
+ llvm::dbgs () << " *** SIL function after " << StageName << " "
336
+ << SFT->getName () << " (" << NumOptimizationIterations
337
+ << " ) ***\n " ;
338
+ F->dump (getOptions ().EmitVerboseSIL );
339
+ }
368
340
369
- if (runToCompletion)
370
- continue ;
341
+ // Remember if this pass didn't change anything.
342
+ if (!CurrentPassHasInvalidated)
343
+ completedPasses.set ((size_t )SFT->getPassKind ());
371
344
372
- // If running the transform resulted in new functions on the top
373
- // of the worklist, we'll return so that we can begin processing
374
- // those new functions.
375
- if (shouldRestartPipeline () || newFunctionsAdded)
376
- return ;
345
+ if (getOptions ().VerifyAll &&
346
+ (CurrentPassHasInvalidated || SILVerifyWithoutInvalidation)) {
347
+ F->verify ();
348
+ verifyAnalyses (F);
377
349
}
350
+
351
+ ++NumPassesRun;
378
352
}
379
353
380
354
void SILPassManager::runFunctionPasses (PassList FuncTransforms) {
355
+
356
+ if (FuncTransforms.empty ())
357
+ return ;
358
+
381
359
BasicCalleeAnalysis *BCA = getAnalysis<BasicCalleeAnalysis>();
382
360
BottomUpFunctionOrder BottomUpOrder (*Mod, BCA);
383
361
auto BottomUpFunctions = BottomUpOrder.getFunctions ();
@@ -395,82 +373,41 @@ void SILPassManager::runFunctionPasses(PassList FuncTransforms) {
395
373
FunctionWorklist.push_back (*I);
396
374
}
397
375
398
- // Used to track how many times a given function has been
399
- // (partially) optimized by the function pass pipeline in this
400
- // invocation.
401
- llvm::DenseMap<SILFunction *, unsigned > CountOptimized;
402
-
403
- // Count of how many iterations we've had since any function was
404
- // popped off the function worklist. This is used to ensure progress
405
- // and eliminate the chance of going into an infinite loop in cases
406
- // where (for example) we have recursive type-based specialization
376
+ // The maximum number of times the pass pipeline can be restarted for a
377
+ // function. This is used to ensure we are not going into an infinite loop in
378
+ // cases where (for example) we have recursive type-based specialization
407
379
// happening.
408
- unsigned IterationsWithoutProgress = 0 ;
380
+ const unsigned MaxNumRestarts = 20 ;
409
381
410
- // The maximum number of functions we'll optimize without popping
411
- // any off the worklist. This is expected to non-zero.
412
- const unsigned MaxIterationsWithoutProgress = 20 ;
382
+ if (SILPrintPassName)
383
+ llvm::dbgs () << " Start function passes at stage: " << StageName << " \n " ;
413
384
414
- // Pop functions off the worklist, and run all function transforms
415
- // on each of them.
385
+ // Run all transforms for all functions, starting at the tail of the worklist.
416
386
while (!FunctionWorklist.empty () && continueTransforming ()) {
417
- auto *F = FunctionWorklist.back ();
387
+ unsigned TailIdx = FunctionWorklist.size () - 1 ;
388
+ unsigned PipelineIdx = FunctionWorklist[TailIdx].PipelineIdx ;
389
+ SILFunction *F = FunctionWorklist[TailIdx].F ;
418
390
419
- // If we've done many iterations without progress, pop the current
420
- // function and any other function we've run any optimizations on
421
- // on from the stack and then continue.
422
- if (IterationsWithoutProgress == (MaxIterationsWithoutProgress - 1 )) {
423
- // Pop the current (potentially not-yet-optimized) function off.
391
+ if (PipelineIdx >= FuncTransforms.size ()) {
392
+ // All passes did already run for the function. Pop it off the worklist.
424
393
FunctionWorklist.pop_back ();
425
- IterationsWithoutProgress = 0 ;
426
-
427
- // Pop any remaining functions that have been optimized (at
428
- // least through some portion of the pipeline).
429
- while (!FunctionWorklist.empty () &&
430
- CountOptimized[FunctionWorklist.back ()] > 0 )
431
- FunctionWorklist.pop_back ();
432
-
433
394
continue ;
434
395
}
435
-
436
- if (CountOptimized[F] > SILFunctionPassPipelineLimit) {
437
- DEBUG (llvm::dbgs () << " *** Hit limit optimizing: " << F->getName ()
438
- << ' \n ' );
439
- FunctionWorklist.pop_back ();
440
- IterationsWithoutProgress = 0 ;
441
- continue ;
442
- }
443
-
444
- assert (
445
- !shouldRestartPipeline () &&
396
+ assert (!shouldRestartPipeline () &&
446
397
" Did not expect function pipeline set up to restart from beginning!" );
447
398
448
- assert (CountOptimized[F] <= SILFunctionPassPipelineLimit &&
449
- " Function optimization count exceeds limit!" );
450
- auto runToCompletion = CountOptimized[F] == SILFunctionPassPipelineLimit;
451
-
452
- runPassesOnFunction (FuncTransforms, F, runToCompletion);
453
- ++CountOptimized[F];
454
- ++IterationsWithoutProgress;
455
-
456
- if (runToCompletion) {
457
- FunctionWorklist.pop_back ();
458
- IterationsWithoutProgress = 0 ;
459
- clearRestartPipeline ();
460
- continue ;
461
- }
462
-
399
+ runPassOnFunction (FuncTransforms[PipelineIdx], F);
463
400
464
- // If running the function transforms did not result in new
465
- // functions being added to the top of the worklist, then we're
466
- // done with this function and can pop it off and continue.
467
- // Otherwise, we'll return to this function and reoptimize after
468
- // processing the new functions that were added.
469
- if (F == FunctionWorklist.back () && !shouldRestartPipeline ()) {
470
- FunctionWorklist.pop_back ();
471
- IterationsWithoutProgress = 0 ;
401
+ // Note: Don't get entry reference prior to runPassOnFunction().
402
+ // A pass can push a new function to the worklist which may cause a
403
+ // reallocation of the buffer and that would invalidate the reference.
404
+ WorklistEntry &Entry = FunctionWorklist[TailIdx];
405
+ if (shouldRestartPipeline () && Entry.NumRestarts < MaxNumRestarts) {
406
+ ++Entry.NumRestarts ;
407
+ Entry.PipelineIdx = 0 ;
408
+ } else {
409
+ ++Entry.PipelineIdx ;
472
410
}
473
-
474
411
clearRestartPipeline ();
475
412
}
476
413
}
0 commit comments