This is an archive of the discontinued LLVM Phabricator instance.

Reimplement BoundaryAlign mechanism (mostly, but not quite NFC)
AbandonedPublic

Authored by reames on Jan 6 2020, 10:16 AM.

Details

Summary

This patch is an implementation of a review suggestion I had made on the original review. Essentially, rather than using up to two boundary align fragments to refine the region of interest, instead use a single one at the beginning of the region with an explicit end pointer. I happen to think this is a simpler and more clear implementation, but it may be a matter of opinion. I'm curious what others think.

This turned out to quite be NFC for an unexpected reason; we hadn't be flushing pending labels when starting a boundary align region. As such labels between a pair of instructions would sometimes have nops inserted before the previous instruction and the resulting label placement. As noted in the other negative tests, binding the label to the preceding instruction isn't *always* what you want, but it seems like a pretty reasonable default.

Since the patch was already NFC, I went ahead and reduced the maximum padding amount so that I could keep the size of a boundary align fragment the same on 64 bit platforms.

Diff Detail

Event Timeline

reames created this revision.Jan 6 2020, 10:16 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 6 2020, 10:16 AM
skan added inline comments.Jan 6 2020, 6:28 PM
llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
513–514

If
a) the next instruction is a relaxable instruction (e.g. jump) and is emitted into a RelaxableFragment, or

b) the next instruction has no fixup and is emitted into a CompactEncodedInstFragment, or

c) the next fragment is a AlignFragment,

the data fragment will be unused. From my perspective, an unused BoundaryAlignFragment is normal when it doesn't have a 'LastFragment' by design. However a unused data fragment is kind of strange.

skan added inline comments.Jan 6 2020, 6:46 PM
llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
481–484

Case

cmp %rax %rcx
.align 16
je .Label0

isn't correctly handled here. We should not emit NOP before cmp %rax %rcx, it may cause infinite loop.

skan added inline comments.Jan 6 2020, 6:59 PM
llvm/include/llvm/MC/MCFragment.h
541–542

I think using uint64_t as the type of Size is good enough here. And the maximum size of the BoundaryAlignFragment is 30 (15+15, 15 is the maximum of an instruction) indeed. So if you really want Size is more space-saving, I suggest uint8_t.

skan added a comment.Jan 7 2020, 12:26 AM

Some meta comments:

Currently, the NOP padding version doesn't check the hardcode so that it has some common issues( not introduced by the reimplementation):

1. Some unfused pair is padded as if it is fused

cmp %rax %rcx
.byte 0x90
je .Label0

.byte 0x90 is not emitted by the function MCObjectStreamer::EmitInstruction, so current code can't see .byte 0x90 and thinks the CMP is fused with JE, however, they are not fused apparently.

2. Some expected check will fail
MCBoudaryAlignFragment is used to align one instruction or a fused pair, so it's size is expected to be no more than 30(the maximun size of two instructions).
When we encounter the case

cmp %rax %rcx
.rept 30
.byte 0x90
.endr
je .Label0

current code will emit NOP before the CMP and think the size of the instructions to be aligned is sizeof(CMP) + 30 + sizeof(JE) incorrectly, then the size of padding may be greater than 30.

3. NOP may be inserted after hardcode
As @jyknight says,

 p4_general_done:
	.byte 0xf3
	ret

Inserting anything between the tacked-on-prefix with .byte, and the rest of the instruction written mnemonically, would be bad.

Although all these case can be correctly addressed by adding assembler directive (your proposal D72303) manually, they can also be dealt with correctly and naturally
by not appending hardcode to fragment that has an instruction.

Prefix padding patch
To support for aligning branch with prefix padding, I have uploaded a new patch D72225. All three issues above have been resolved and my design for MCBoundaryAlignFragment is really similar to your reimplementation, do you mind if we directly focus on the prefix padding patch?

MaskRay added inline comments.Jan 8 2020, 4:25 PM
llvm/include/llvm/MC/MCFragment.h
541–542
uint8_t Size = 0;
Align AlignBoundary;
MCFragment *LastFragment = nullptr;

can make sizeof(MCBoundaryAlignFragment) 8 bytes smaller.

This patch does not apply on master. It needs a rebase.

reames planned changes to this revision.Jan 14 2020, 3:19 PM

Getting this off review queues for the moment. Will return to this once other more urgent items in this area settle out.

reames abandoned this revision.Dec 3 2020, 3:03 PM