Skip to content

Commit d0efd7b

Browse files
committed
[X86][MC] Disable Prefix padding after hardcode/prefix
Reviewers: reames, MaskRay, craig.topper, LuoYuanke, jyknight, eli.friedman Reviewed By: craig.topper Subscribers: hiraditya, llvm-commits, annita.zhang Tags: #llvm Differential Revision: https://reviews.llvm.org/D76475
1 parent 9180c14 commit d0efd7b

File tree

3 files changed

+74
-25
lines changed

3 files changed

+74
-25
lines changed

llvm/include/llvm/MC/MCFragment.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
259259

260260
/// The instruction this is a fragment for.
261261
MCInst Inst;
262+
/// Can we auto pad the instruction?
263+
bool AllowAutoPadding = false;
262264

263265
public:
264266
MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
@@ -269,6 +271,9 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
269271
const MCInst &getInst() const { return Inst; }
270272
void setInst(const MCInst &Value) { Inst = Value; }
271273

274+
bool getAllowAutoPadding() const { return AllowAutoPadding; }
275+
void setAllowAutoPadding(bool V) { AllowAutoPadding = V; }
276+
272277
static bool classof(const MCFragment *F) {
273278
return F->getKind() == MCFragment::FT_Relaxable;
274279
}

llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,11 @@ class X86AsmBackend : public MCAsmBackend {
136136

137137
bool needAlign(MCObjectStreamer &OS) const;
138138
bool needAlignInst(const MCInst &Inst) const;
139+
bool allowAutoPaddingForInst(const MCInst &Inst, MCObjectStreamer &OS) const;
139140
MCInst PrevInst;
140141
MCBoundaryAlignFragment *PendingBoundaryAlign = nullptr;
141142
std::pair<MCFragment *, size_t> PrevInstPosition;
143+
bool AllowAutoPaddingForInst;
142144

143145
public:
144146
X86AsmBackend(const Target &T, const MCSubtargetInfo &STI)
@@ -538,13 +540,8 @@ static size_t getSizeForInstFragment(const MCFragment *F) {
538540
}
539541
}
540542

541-
/// Check if the instruction operand needs to be aligned. Padding is disabled
542-
/// before intruction which may be rewritten by linker(e.g. TLSCALL).
543+
/// Check if the instruction operand needs to be aligned.
543544
bool X86AsmBackend::needAlignInst(const MCInst &Inst) const {
544-
// Linker may rewrite the instruction with variant symbol operand.
545-
if (hasVariantSymbol(Inst))
546-
return false;
547-
548545
const MCInstrDesc &InstDesc = MCII->get(Inst.getOpcode());
549546
return (InstDesc.isConditionalBranch() &&
550547
(AlignBranchType & X86::AlignBranchJcc)) ||
@@ -558,31 +555,53 @@ bool X86AsmBackend::needAlignInst(const MCInst &Inst) const {
558555
(AlignBranchType & X86::AlignBranchIndirect));
559556
}
560557

561-
/// Insert BoundaryAlignFragment before instructions to align branches.
562-
void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS,
563-
const MCInst &Inst) {
564-
if (!needAlign(OS))
565-
return;
558+
/// Return true if we can insert NOP or prefixes automatically before the
559+
/// the instruction to be emitted.
560+
bool X86AsmBackend::allowAutoPaddingForInst(const MCInst &Inst,
561+
MCObjectStreamer &OS) const {
562+
if (hasVariantSymbol(Inst))
563+
// Linker may rewrite the instruction with variant symbol operand(e.g.
564+
// TLSCALL).
565+
return false;
566566

567567
if (hasInterruptDelaySlot(PrevInst))
568568
// If this instruction follows an interrupt enabling instruction with a one
569569
// instruction delay, inserting a nop would change behavior.
570-
return;
570+
return false;
571571

572572
if (isPrefix(PrevInst, *MCII))
573-
// If this instruction follows a prefix, inserting a nop would change
573+
// If this instruction follows a prefix, inserting a nop/prefix would change
574574
// semantic.
575-
return;
575+
return false;
576+
577+
if (isPrefix(Inst, *MCII))
578+
// If this instruction is a prefix, inserting a prefix would change
579+
// semantic.
580+
return false;
576581

577582
if (isRightAfterData(OS.getCurrentFragment(), PrevInstPosition))
578583
// If this instruction follows any data, there is no clear
579-
// instruction boundary, inserting a nop would change semantic.
584+
// instruction boundary, inserting a nop/prefix would change semantic.
585+
return false;
586+
587+
return true;
588+
}
589+
590+
/// Insert BoundaryAlignFragment before instructions to align branches.
591+
void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS,
592+
const MCInst &Inst) {
593+
AllowAutoPaddingForInst = allowAutoPaddingForInst(Inst, OS);
594+
595+
if (!needAlign(OS))
580596
return;
581597

582598
if (!isMacroFused(PrevInst, Inst))
583599
// Macro fusion doesn't happen indeed, clear the pending.
584600
PendingBoundaryAlign = nullptr;
585601

602+
if (!AllowAutoPaddingForInst)
603+
return;
604+
586605
if (PendingBoundaryAlign &&
587606
OS.getCurrentFragment()->getPrevNode() == PendingBoundaryAlign) {
588607
// Macro fusion actually happens and there is no other fragment inserted
@@ -617,12 +636,14 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS,
617636

618637
/// Set the last fragment to be aligned for the BoundaryAlignFragment.
619638
void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS, const MCInst &Inst) {
620-
if (!needAlign(OS))
621-
return;
622-
623639
PrevInst = Inst;
624640
MCFragment *CF = OS.getCurrentFragment();
625641
PrevInstPosition = std::make_pair(CF, getSizeForInstFragment(CF));
642+
if (auto *F = dyn_cast_or_null<MCRelaxableFragment>(CF))
643+
F->setAllowAutoPadding(AllowAutoPaddingForInst);
644+
645+
if (!needAlign(OS))
646+
return;
626647

627648
if (!needAlignInst(Inst) || !PendingBoundaryAlign)
628649
return;
@@ -827,12 +848,6 @@ static bool isFullyRelaxed(const MCRelaxableFragment &RF) {
827848
return getRelaxedOpcode(Inst, Is16BitMode) == Inst.getOpcode();
828849
}
829850

830-
831-
static bool shouldAddPrefix(const MCInst &Inst, const MCInstrInfo &MCII) {
832-
// Linker may rewrite the instruction with variant symbol operand.
833-
return !hasVariantSymbol(Inst);
834-
}
835-
836851
static unsigned getRemainingPrefixSize(const MCInst &Inst,
837852
const MCSubtargetInfo &STI,
838853
MCCodeEmitter &Emitter) {
@@ -856,7 +871,7 @@ static unsigned getRemainingPrefixSize(const MCInst &Inst,
856871
bool X86AsmBackend::padInstructionViaPrefix(MCRelaxableFragment &RF,
857872
MCCodeEmitter &Emitter,
858873
unsigned &RemainingSize) const {
859-
if (!shouldAddPrefix(RF.getInst(), *MCII))
874+
if (!RF.getAllowAutoPadding())
860875
return false;
861876
// If the instruction isn't fully relaxed, shifting it around might require a
862877
// larger value for one of the fixups then can be encoded. The outer loop
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# RUN: llvm-mc -mcpu=skylake -filetype=obj -triple x86_64-pc-linux-gnu %s -x86-pad-max-prefix-size=5 | llvm-objdump -d - | FileCheck %s
2+
3+
4+
# The first test check the correctness cornercase - can't add prefixes on a
5+
# instruction following by a prefix.
6+
.globl labeled_prefix_test
7+
labeled_prefix_test:
8+
# CHECK: 0: 2e 2e 2e 2e 2e e9 06 00 00 00 jmp
9+
# CHECK: a: 3e e9 00 00 00 00 jmp
10+
jmp bar
11+
DS
12+
jmp bar
13+
.p2align 4
14+
bar:
15+
ret
16+
17+
# The second test is similar to the second test - can't add prefixes on a
18+
# instruction following by hardcode.
19+
.p2align 5
20+
.globl labeled_hardcode_test
21+
labeled_hardcode_test:
22+
# CHECK: 20: 2e 2e 2e 2e 2e e9 06 00 00 00 jmp
23+
# CHECK: 2a: 3e e9 00 00 00 00 jmp
24+
jmp baz
25+
.byte 0x3e
26+
jmp baz
27+
.p2align 4
28+
baz:
29+
ret

0 commit comments

Comments
 (0)