@@ -119,7 +119,11 @@ bool unlikelyExecuted(BasicBlock &BB) {
119
119
120
120
// / Check whether it's safe to outline \p BB.
121
121
static bool mayExtractBlock (const BasicBlock &BB) {
122
- return !BB.hasAddressTaken () && !BB.isEHPad ();
122
+ // EH pads are unsafe to outline because doing so breaks EH type tables. It
123
+ // follows that invoke instructions cannot be extracted, because CodeExtractor
124
+ // requires unwind destinations to be within the extraction region.
125
+ return !BB.hasAddressTaken () && !BB.isEHPad () &&
126
+ !isa<InvokeInst>(BB.getTerminator ());
123
127
}
124
128
125
129
// / Check whether \p Region is profitable to outline.
@@ -283,6 +287,8 @@ using BlockTy = std::pair<BasicBlock *, unsigned>;
283
287
namespace {
284
288
// / A maximal outlining region. This contains all blocks post-dominated by a
285
289
// / sink block, the sink block itself, and all blocks dominated by the sink.
290
+ // / If sink-predecessors and sink-successors cannot be extracted in one region,
291
+ // / the static constructor returns a list of suitable extraction regions.
286
292
class OutliningRegion {
287
293
// / A list of (block, score) pairs. A block's score is non-zero iff it's a
288
294
// / viable sub-region entry point. Blocks with higher scores are better entry
@@ -297,12 +303,9 @@ class OutliningRegion {
297
303
// / Whether the entire function is cold.
298
304
bool EntireFunctionCold = false ;
299
305
300
- // / Whether or not \p BB could be the entry point of an extracted region.
301
- static bool isViableEntryPoint (BasicBlock &BB) { return !BB.isEHPad (); }
302
-
303
306
// / If \p BB is a viable entry point, return \p Score. Return 0 otherwise.
304
307
static unsigned getEntryPointScore (BasicBlock &BB, unsigned Score) {
305
- return isViableEntryPoint (BB) ? Score : 0 ;
308
+ return mayExtractBlock (BB) ? Score : 0 ;
306
309
}
307
310
308
311
// / These scores should be lower than the score for predecessor blocks,
@@ -318,21 +321,23 @@ class OutliningRegion {
318
321
OutliningRegion (OutliningRegion &&) = default ;
319
322
OutliningRegion &operator =(OutliningRegion &&) = default ;
320
323
321
- static OutliningRegion create (BasicBlock &SinkBB, const DominatorTree &DT ,
322
- const PostDominatorTree &PDT) {
323
- OutliningRegion ColdRegion;
324
-
324
+ static std::vector< OutliningRegion> create (BasicBlock &SinkBB,
325
+ const DominatorTree &DT,
326
+ const PostDominatorTree &PDT) {
327
+ std::vector<OutliningRegion> Regions;
325
328
SmallPtrSet<BasicBlock *, 4 > RegionBlocks;
326
329
330
+ Regions.emplace_back ();
331
+ OutliningRegion *ColdRegion = &Regions.back ();
332
+
327
333
auto addBlockToRegion = [&](BasicBlock *BB, unsigned Score) {
328
334
RegionBlocks.insert (BB);
329
- ColdRegion.Blocks .emplace_back (BB, Score);
330
- assert (RegionBlocks.size () == ColdRegion.Blocks .size () && " Duplicate BB" );
335
+ ColdRegion->Blocks .emplace_back (BB, Score);
331
336
};
332
337
333
338
// The ancestor farthest-away from SinkBB, and also post-dominated by it.
334
339
unsigned SinkScore = getEntryPointScore (SinkBB, ScoreForSinkBlock);
335
- ColdRegion. SuggestedEntryPoint = (SinkScore > 0 ) ? &SinkBB : nullptr ;
340
+ ColdRegion-> SuggestedEntryPoint = (SinkScore > 0 ) ? &SinkBB : nullptr ;
336
341
unsigned BestScore = SinkScore;
337
342
338
343
// Visit SinkBB's ancestors using inverse DFS.
@@ -345,8 +350,8 @@ class OutliningRegion {
345
350
// If the predecessor is cold and has no predecessors, the entire
346
351
// function must be cold.
347
352
if (SinkPostDom && pred_empty (&PredBB)) {
348
- ColdRegion. EntireFunctionCold = true ;
349
- return ColdRegion ;
353
+ ColdRegion-> EntireFunctionCold = true ;
354
+ return Regions ;
350
355
}
351
356
352
357
// If SinkBB does not post-dominate a predecessor, do not mark the
@@ -361,18 +366,27 @@ class OutliningRegion {
361
366
// considered as entry points before the sink block.
362
367
unsigned PredScore = getEntryPointScore (PredBB, PredIt.getPathLength ());
363
368
if (PredScore > BestScore) {
364
- ColdRegion. SuggestedEntryPoint = &PredBB;
369
+ ColdRegion-> SuggestedEntryPoint = &PredBB;
365
370
BestScore = PredScore;
366
371
}
367
372
368
373
addBlockToRegion (&PredBB, PredScore);
369
374
++PredIt;
370
375
}
371
376
372
- // Add SinkBB to the cold region. It's considered as an entry point before
373
- // any sink-successor blocks.
374
- if (mayExtractBlock (SinkBB))
377
+ // If the sink can be added to the cold region, do so. It's considered as
378
+ // an entry point before any sink-successor blocks.
379
+ //
380
+ // Otherwise, split cold sink-successor blocks using a separate region.
381
+ // This satisfies the requirement that all extraction blocks other than the
382
+ // first have predecessors within the extraction region.
383
+ if (mayExtractBlock (SinkBB)) {
375
384
addBlockToRegion (&SinkBB, SinkScore);
385
+ } else {
386
+ Regions.emplace_back ();
387
+ ColdRegion = &Regions.back ();
388
+ BestScore = 0 ;
389
+ }
376
390
377
391
// Find all successors of SinkBB dominated by SinkBB using DFS.
378
392
auto SuccIt = ++df_begin (&SinkBB);
@@ -393,15 +407,15 @@ class OutliningRegion {
393
407
394
408
unsigned SuccScore = getEntryPointScore (SuccBB, ScoreForSuccBlock);
395
409
if (SuccScore > BestScore) {
396
- ColdRegion. SuggestedEntryPoint = &SuccBB;
410
+ ColdRegion-> SuggestedEntryPoint = &SuccBB;
397
411
BestScore = SuccScore;
398
412
}
399
413
400
414
addBlockToRegion (&SuccBB, SuccScore);
401
415
++SuccIt;
402
416
}
403
417
404
- return ColdRegion ;
418
+ return Regions ;
405
419
}
406
420
407
421
// / Whether this region has nothing to extract.
@@ -496,28 +510,30 @@ bool HotColdSplitting::outlineColdRegions(Function &F, bool HasProfileSummary) {
496
510
if (!PDT)
497
511
PDT = make_unique<PostDominatorTree>(F);
498
512
499
- auto Region = OutliningRegion::create (*BB, *DT, *PDT);
500
- if (Region.empty ())
501
- continue ;
513
+ auto Regions = OutliningRegion::create (*BB, *DT, *PDT);
514
+ for (OutliningRegion &Region : Regions) {
515
+ if (Region.empty ())
516
+ continue ;
502
517
503
- if (Region.isEntireFunctionCold ()) {
504
- LLVM_DEBUG (dbgs () << " Entire function is cold\n " );
505
- return markFunctionCold (F);
506
- }
518
+ if (Region.isEntireFunctionCold ()) {
519
+ LLVM_DEBUG (dbgs () << " Entire function is cold\n " );
520
+ return markFunctionCold (F);
521
+ }
507
522
508
- // If this outlining region intersects with another, drop the new region.
509
- //
510
- // TODO: It's theoretically possible to outline more by only keeping the
511
- // largest region which contains a block, but the extra bookkeeping to do
512
- // this is tricky/expensive.
513
- bool RegionsOverlap = any_of (Region.blocks (), [&](const BlockTy &Block) {
514
- return !ColdBlocks.insert (Block.first ).second ;
515
- });
516
- if (RegionsOverlap)
517
- continue ;
523
+ // If this outlining region intersects with another, drop the new region.
524
+ //
525
+ // TODO: It's theoretically possible to outline more by only keeping the
526
+ // largest region which contains a block, but the extra bookkeeping to do
527
+ // this is tricky/expensive.
528
+ bool RegionsOverlap = any_of (Region.blocks (), [&](const BlockTy &Block) {
529
+ return !ColdBlocks.insert (Block.first ).second ;
530
+ });
531
+ if (RegionsOverlap)
532
+ continue ;
518
533
519
- OutliningWorklist.emplace_back (std::move (Region));
520
- ++NumColdRegionsFound;
534
+ OutliningWorklist.emplace_back (std::move (Region));
535
+ ++NumColdRegionsFound;
536
+ }
521
537
}
522
538
523
539
// Outline single-entry cold regions, splitting up larger regions as needed.
0 commit comments