[PATCH] D72225: Align branches within 32-Byte boundary(Prefix padding)
Kan Shengchen via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 11 00:15:43 PST 2020
skan added a comment.
**Summary of the usage of `MCBoundaryAlignFragment`:**
As I commented in `MCFragment.h`, `MCBoundaryAlignFragment` is a placeholder fragment used to emit NOP or values to align a set of fragments within specific boundary. And in this application, the value is the segment prefix indeed. For example, let's say the code is
pushl %ebp
pushl %edi
je .L_0
and JCC is need to be aligned.
**1. Fragment Layout**
The corresponding fragment sequence will be
BoundaryAlign1 | Data1 | BoundaryAlign2 | Data2 | BoundaryAlign3 | Relax1
Data1 holds `pushl %ebp`, Data2 holds `pushl %edi`, Relax1 holds `je .L_0`. BoundaryAlign1 and BoundaryAlign2 are used to emit prefix,
BoundaryAlign3 is used to emit NOP.
**2. Determine the range of the fragments needed to be aligned**
`MCBoundaryAlignFragment` is designed to align a set of fragments within the same section as the BoundaryAlign. BoundaryAlign1~BoundaryAlign3 are used to align fragment Relax1. Each BoundaryAlign has a member called `LastFragment`, which marks the end of the set of fragments, if we call the nearest backward `MCBoundaryAlignFragment` of `LastFragment` as `NBBF` (short for nearest backward BoundaryAlign fragment), then the set of fragments to be aligned is (NBBF, LastFragment]. In this example, the `LastFragment` is Relax1 and the `NBBF` is BoundaryAlign3.
**3. Relax the `MCBoundaryAlignFragment`**
**3.1 Prerequisites**
Before relaxation, we should guarantee that the BoundaryAlign fragment is in the same section as (NBBF, LastFragment], and each non-MCBoundaryAlignFragment in (BoundaryAlign, LastFragment] must have a fixed size after finite times of relaxation. For example, if the code is
pushl %ebp
.align 16
pushl %edi
je .L_0
the corresponding fragment sequence will be
BoundaryAlign1 | Data1 | Align1 | BoundaryAlign2 | Data2 | BoundaryAlign3 | Relax1
Align1 is `MCAlignFragment` that can grow and shrink, it is not guranteed to have a fixed size after finite times of relaxation, so the BoundaryAlign1's `LastFragment` should be NULL.
**3.2 How to relax**
Let's go back to the code
pushl %ebp
pushl %edi
je .L_0
BoundaryAlign1 | Data1 | BoundaryAlign2 | Data2 | BoundaryAlign3 | Relax1
`LastFragment` = Relax1, `NBBF` = BoundaryAlign3.
The fragments are always relaxed from left to right, namely in each iteration, BoundaryAlign1 is relaxed first, then Data1 and then BoundaryAlign2. When we relax a BoundaryAlign, we will assume that all the BoundaryAlign in [this, LastFragment) are of size 0. For example, let's say the size of BoundaryAlign1 and BoundaryAlign2 is **limited** by 1, and size of BoundaryAlign3 is not limited, and the boundary size is 32.
In the **first** iteration and before Relax1 is relaxed, Relax1's offset is 0x1e and size is 2, so Relax1 needs 2-byte padding.
BoundaryAlign1(0) | Data1(1) | BoundaryAlign2(0) | Data2(1) | BoundaryAlign3(0) | Relax1(2, 0x1e)
After BoundaryAlign3 is relaxed, the sequence will be
BoundaryAlign1(1) | Data1(1) | BoundaryAlign2(1) | Data2(1) | BoundaryAlign3(0) | Relax1(2, 0x20)
In the **second** iteration and before Relax1 is relaxed, Relax1's offset may become 0x1a and size become 6.
BoundaryAlign1(1) | Data1(1) | BoundaryAlign2(1) | Data2(1) | BoundaryAlign3(0) | Relax1(6, 0x1a)
When relax BoudaryAlign1, we will assume Relax1's offset is 0x18 (0x1a -1 -1), so Relax1 needs 0-byte padding. After BoudaryAlign3 is relaxed,
the sequence will be
BoundaryAlign1(0) | Data1(1) | BoundaryAlign2(0) | Data2(1) | BoundaryAlign3(0) | Relax1(6, 0x18)
**Note**
If need to align fused jcc, 2 and 3 are same as above, only 1 is slightly different. When the code is
pushl %ebp
pushl %edi
cmp %eax, %ebp
je .L_0
The corresponding fragment sequence will be
BoundaryAlign1 | Data1 | BoundaryAlign2 | Data2 | BoundaryAlign3 | Data3 | Relax1
Data1 holds `pushl %ebp`, Data2 holds `pushl %edi`, Data3 holds `cmp %eax, %ebp`, Relax1 holds `je .L_0`. BoundaryAlign1 and BoundaryAlign2 are used to emit prefix, BoundaryAlign3 is used to emit NOP. `LastFragment` = Relax1, `NBBF` = BoundaryAlign3.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D72225/new/
https://reviews.llvm.org/D72225
More information about the llvm-commits
mailing list