-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
LSRA comes up with a block order in which it would allocate register for the code inside it. It would sequence all the predecessors of a block before scheduling a block. It also compares the bbWeight of a block and gives preference to the block with higher weights.
It is not uncommon to have multiple blocks of same weight (either because of lack of enough profile data or other reasons) and in such cases, we rely on the block number of the block as seen below.
runtime/src/coreclr/jit/lsra.cpp
Lines 1030 to 1060 in 96ef47b
| int LinearScan::compareBlocksForSequencing(BasicBlock* block1, BasicBlock* block2, bool useBlockWeights) | |
| { | |
| if (useBlockWeights) | |
| { | |
| weight_t weight1 = block1->getBBWeight(compiler); | |
| weight_t weight2 = block2->getBBWeight(compiler); | |
| if (weight1 > weight2) | |
| { | |
| return -1; | |
| } | |
| else if (weight1 < weight2) | |
| { | |
| return 1; | |
| } | |
| } | |
| // If weights are the same prefer LOWER bbnum | |
| if (block1->bbNum < block2->bbNum) | |
| { | |
| return -1; | |
| } | |
| else if (block1->bbNum == block2->bbNum) | |
| { | |
| return 0; | |
| } | |
| else | |
| { | |
| return 1; | |
| } | |
| } |
This is arguably not a good heuristic to arrange LSRA block sequencing. The bbNum are purely dependent on the how the blocks are laid out our data structure and might not represent the flow graph. The original thinking could be that the blocks with lower bbNum are executed first than the ones with higher numbers, but still, it is not the optimal strategy to have. If the blocks are renumbered, it can drastically change the allocation strategy because of different block sequencing coming out of it. This was seen in #66967 where I had to skip renumbering the blocks so the impact of "unreachable block elimination" doesn't regress register allocation.
Just to give a sense, I tried following strategies and the impact it has on code size is huge.
| Strategy | Methods improved | Methods regressed | Code size impact (in bytes) |
|---|---|---|---|
Prefer block1 over block2 if block1 has more predecessors than those of block2. |
2292 | 3313 | 23028 |
Prefer block1 over block2 if block1 has less predecessors than those of block2. |
2669 | 3141 | 3079 |
Prefer block1 over block2 if block1 has more bbReach nodes than those of block2. |
3495 | 3923 | 14156 |
Prefer block1 over block2 if block1 has less bbReach nodes than those of block2. |
2642 | 3425 | 4155 |
Some other strategies could be:
- Prefer blocks depending on if they have critical in/out edges.
- Prefer blocks depending on if they have EH boundary in/out edges.
- Prefer blocks if they are in loop (this could be mostly taken care by
bbWeightbut should double check).
A clever way is to have a mix of above listed strategies in choosing the block sequencing.
category:design
theme:register-allocator
skill-level:expert
cost:medium
impact:large