@@ -4945,6 +4945,9 @@ weight_t Compiler::ThreeOptLayout::GetLayoutCost(unsigned startPos, unsigned end
4945
4945
// block - The block to consider creating fallthrough from
4946
4946
// next - The block to consider creating fallthrough into
4947
4947
//
4948
+ // Returns:
4949
+ // The cost
4950
+ //
4948
4951
weight_t Compiler::ThreeOptLayout::GetCost (BasicBlock* block, BasicBlock* next)
4949
4952
{
4950
4953
assert (block != nullptr );
@@ -4964,8 +4967,8 @@ weight_t Compiler::ThreeOptLayout::GetCost(BasicBlock* block, BasicBlock* next)
4964
4967
}
4965
4968
4966
4969
// -----------------------------------------------------------------------------
4967
- // Compiler::ThreeOptLayout::TrySwappingPartitions: Evaluates the cost of swapping the given partitions.
4968
- // If it is profitable, write the swapped partitions back to 'blockOrder' .
4970
+ // Compiler::ThreeOptLayout::GetPartitionCostDelta: Computes the current cost of the given partitions,
4971
+ // and the cost of swapping S2 and S3, returning the difference between them .
4969
4972
//
4970
4973
// Parameters:
4971
4974
// s1Start - The starting position of the first partition
@@ -4975,24 +4978,10 @@ weight_t Compiler::ThreeOptLayout::GetCost(BasicBlock* block, BasicBlock* next)
4975
4978
// s4End - The ending position (inclusive) of the fourth partition
4976
4979
//
4977
4980
// Returns:
4978
- // True if the swap was performed, false otherwise
4979
- //
4980
- // Notes:
4981
- // Here is the proposed partition:
4982
- // S1: s1Start ~ s2Start-1
4983
- // S2: s2Start ~ s3Start-1
4984
- // S3: s3Start ~ s3End
4985
- // S4: remaining blocks
4986
- //
4987
- // After the swap:
4988
- // S1: s1Start ~ s2Start-1
4989
- // S3: s3Start ~ s3End
4990
- // S2: s2Start ~ s3Start-1
4991
- // S4: remaining blocks
4981
+ // The difference in cost between the current and proposed layouts.
4982
+ // A negative delta indicates the proposed layout is an improvement.
4992
4983
//
4993
- // If 's3End' and 's4End' are the same, the fourth partition doesn't exist.
4994
- //
4995
- bool Compiler::ThreeOptLayout::TrySwappingPartitions (
4984
+ weight_t Compiler::ThreeOptLayout::GetPartitionCostDelta (
4996
4985
unsigned s1Start, unsigned s2Start, unsigned s3Start, unsigned s3End, unsigned s4End)
4997
4986
{
4998
4987
BasicBlock* const s2Block = blockOrder[s2Start];
@@ -5019,16 +5008,38 @@ bool Compiler::ThreeOptLayout::TrySwappingPartitions(
5019
5008
newCost += s3BlockPrev->bbWeight ;
5020
5009
}
5021
5010
5022
- // Check if the swap is profitable
5023
- if ((newCost >= currCost) || Compiler::fgProfileWeightsEqual (newCost, currCost, 0.001 ))
5024
- {
5025
- return false ;
5026
- }
5011
+ return newCost - currCost;
5012
+ }
5027
5013
5028
- // We've found a profitable cut point. Continue with the swap.
5029
- JITDUMP (" Swapping partitions [" FMT_BB " , " FMT_BB " ] and [" FMT_BB " , " FMT_BB
5030
- " ] (current partition cost = %f, new partition cost = %f)\n " ,
5031
- s2Block->bbNum , s3BlockPrev->bbNum , s3Block->bbNum , lastBlock->bbNum , currCost, newCost);
5014
+ // -----------------------------------------------------------------------------
5015
+ // Compiler::ThreeOptLayout::SwapPartitions: Swap the specified partitions.
5016
+ // It is assumed (and asserted) that the swap is profitable.
5017
+ //
5018
+ // Parameters:
5019
+ // s1Start - The starting position of the first partition
5020
+ // s2Start - The starting position of the second partition
5021
+ // s3Start - The starting position of the third partition
5022
+ // s3End - The ending position (inclusive) of the third partition
5023
+ // s4End - The ending position (inclusive) of the fourth partition
5024
+ //
5025
+ // Notes:
5026
+ // Here is the proposed partition:
5027
+ // S1: s1Start ~ s2Start-1
5028
+ // S2: s2Start ~ s3Start-1
5029
+ // S3: s3Start ~ s3End
5030
+ // S4: remaining blocks
5031
+ //
5032
+ // After the swap:
5033
+ // S1: s1Start ~ s2Start-1
5034
+ // S3: s3Start ~ s3End
5035
+ // S2: s2Start ~ s3Start-1
5036
+ // S4: remaining blocks
5037
+ //
5038
+ // If 's3End' and 's4End' are the same, the fourth partition doesn't exist.
5039
+ //
5040
+ void Compiler::ThreeOptLayout::SwapPartitions (
5041
+ unsigned s1Start, unsigned s2Start, unsigned s3Start, unsigned s3End, unsigned s4End)
5042
+ {
5032
5043
INDEBUG (const weight_t currLayoutCost = GetLayoutCost (s1Start, s4End));
5033
5044
5034
5045
// Swap the partitions
@@ -5062,8 +5073,6 @@ bool Compiler::ThreeOptLayout::TrySwappingPartitions(
5062
5073
Compiler::fgProfileWeightsEqual (newLayoutCost, currLayoutCost, 0.001 ));
5063
5074
}
5064
5075
#endif // DEBUG
5065
-
5066
- return true ;
5067
5076
}
5068
5077
5069
5078
// -----------------------------------------------------------------------------
@@ -5364,6 +5373,7 @@ bool Compiler::ThreeOptLayout::RunGreedyThreeOptPass(unsigned startPos, unsigned
5364
5373
5365
5374
const bool isForwardJump = (srcPos < dstPos);
5366
5375
unsigned s2Start, s3Start, s3End;
5376
+ weight_t costChange;
5367
5377
5368
5378
if (isForwardJump)
5369
5379
{
@@ -5378,35 +5388,83 @@ bool Compiler::ThreeOptLayout::RunGreedyThreeOptPass(unsigned startPos, unsigned
5378
5388
// S3: dstPos ~ endPos
5379
5389
// S2: srcPos+1 ~ dstPos-1
5380
5390
// S4: remaining blocks
5381
- s2Start = srcPos + 1 ;
5382
- s3Start = dstPos;
5383
- s3End = endPos;
5391
+ s2Start = srcPos + 1 ;
5392
+ s3Start = dstPos;
5393
+ s3End = endPos;
5394
+ costChange = GetPartitionCostDelta (startPos, s2Start, s3Start, s3End, endPos);
5384
5395
}
5385
5396
else
5386
5397
{
5387
-
5398
+ // For backward jumps, we will employ a greedy 4-opt approach to find the ideal cut point
5399
+ // between the destination and source blocks.
5388
5400
// Here is the proposed partition:
5389
5401
// S1: startPos ~ dstPos-1
5390
- // S2: dstPos ~ srcPos -1
5391
- // S3: srcPos
5402
+ // S2: dstPos ~ s3Start -1
5403
+ // S3: s3Start ~ srcPos
5392
5404
// S4: srcPos+1 ~ endPos
5393
5405
//
5394
5406
// After the swap:
5395
5407
// S1: startPos ~ dstPos-1
5396
- // S3: srcPos
5397
- // S2: dstPos ~ srcPos -1
5408
+ // S3: s3Start ~ srcPos
5409
+ // S2: dstPos ~ s3Start -1
5398
5410
// S4: srcPos+1 ~ endPos
5399
- s2Start = dstPos;
5400
- s3Start = srcPos;
5401
- s3End = srcPos;
5411
+ s2Start = dstPos;
5412
+ s3Start = srcPos;
5413
+ s3End = srcPos;
5414
+ costChange = BB_ZERO_WEIGHT;
5415
+
5416
+ // The cut points before S2 and after S3 are fixed.
5417
+ // We will search for the optimal cut point before S3.
5418
+ BasicBlock* const s2Block = blockOrder[s2Start];
5419
+ BasicBlock* const s2BlockPrev = blockOrder[s2Start - 1 ];
5420
+ BasicBlock* const lastBlock = blockOrder[s3End];
5421
+
5422
+ // Because the above cut points are fixed, don't waste time re-computing their costs.
5423
+ // Instead, pre-compute them here.
5424
+ const weight_t currCostBase =
5425
+ GetCost (s2BlockPrev, s2Block) +
5426
+ ((s3End < endPos) ? GetCost (lastBlock, blockOrder[s3End + 1 ]) : lastBlock->bbWeight );
5427
+ const weight_t newCostBase = GetCost (lastBlock, s2Block);
5428
+
5429
+ // Search for the ideal start to S3
5430
+ for (unsigned position = s2Start + 1 ; position <= s3End; position++)
5431
+ {
5432
+ BasicBlock* const s3Block = blockOrder[position];
5433
+ BasicBlock* const s3BlockPrev = blockOrder[position - 1 ];
5434
+
5435
+ // Don't consider any cut points that would break up call-finally pairs
5436
+ if (s3Block->KindIs (BBJ_CALLFINALLYRET))
5437
+ {
5438
+ continue ;
5439
+ }
5440
+
5441
+ // Compute the cost delta of this partition
5442
+ const weight_t currCost = currCostBase + GetCost (s3BlockPrev, s3Block);
5443
+ const weight_t newCost =
5444
+ newCostBase + GetCost (s2BlockPrev, s3Block) +
5445
+ ((s3End < endPos) ? GetCost (s3BlockPrev, blockOrder[s3End + 1 ]) : s3BlockPrev->bbWeight );
5446
+ const weight_t delta = newCost - currCost;
5447
+
5448
+ if (delta < costChange)
5449
+ {
5450
+ costChange = delta;
5451
+ s3Start = position;
5452
+ }
5453
+ }
5402
5454
}
5403
5455
5404
5456
// Continue evaluating partitions if this one isn't profitable
5405
- if (! TrySwappingPartitions (startPos, s2Start, s3Start, s3End, endPos ))
5457
+ if ((costChange >= BB_ZERO_WEIGHT) || Compiler::fgProfileWeightsEqual (costChange, BB_ZERO_WEIGHT, 0.001 ))
5406
5458
{
5407
5459
continue ;
5408
5460
}
5409
5461
5462
+ JITDUMP (" Swapping partitions [" FMT_BB " , " FMT_BB " ] and [" FMT_BB " , " FMT_BB " ] (cost change = %f)\n " ,
5463
+ blockOrder[s2Start]->bbNum , blockOrder[s3Start - 1 ]->bbNum , blockOrder[s3Start]->bbNum ,
5464
+ blockOrder[s3End]->bbNum , costChange);
5465
+
5466
+ SwapPartitions (startPos, s2Start, s3Start, s3End, endPos);
5467
+
5410
5468
// Update the ordinals for the blocks we moved
5411
5469
for (unsigned i = s2Start; i <= endPos; i++)
5412
5470
{
0 commit comments