Skip to content

Commit 18c218e

Browse files
committed
[LLVM][CodeGen][X86] Support larger NOOPs on x86 when available
The mnop-mcount attribute benefits from using a single no-op instruction instead of 3 when supported. Update codegen to support single instruction 3-10 byte NOOPs.
1 parent aae9774 commit 18c218e

3 files changed

Lines changed: 38 additions & 10 deletions

File tree

llvm/lib/Target/X86/X86MCInstLower.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -664,9 +664,8 @@ static unsigned emitNop(MCStreamer &OS, unsigned NumBytes,
664664
// target cpu. 15-bytes is the longest single NOP instruction, but some
665665
// platforms can't decode the longest forms efficiently.
666666
unsigned MaxNopLength = 1;
667+
unsigned BaseReg = X86::RAX;
667668
if (Subtarget->is64Bit()) {
668-
// FIXME: We can use NOOPL on 32-bit targets with FeatureNOPL, but the
669-
// IndexReg/BaseReg below need to be updated.
670669
if (Subtarget->hasFeature(X86::TuningFast7ByteNOP))
671670
MaxNopLength = 7;
672671
else if (Subtarget->hasFeature(X86::TuningFast15ByteNOP))
@@ -675,16 +674,19 @@ static unsigned emitNop(MCStreamer &OS, unsigned NumBytes,
675674
MaxNopLength = 11;
676675
else
677676
MaxNopLength = 10;
678-
} if (Subtarget->is32Bit())
677+
} else if (Subtarget->is32Bit() && Subtarget->getFeatureBits()[X86::FeatureNOPL]) {
678+
BaseReg = X86::EAX;
679+
MaxNopLength = 10;
680+
}
681+
else if (Subtarget->is32Bit())
679682
MaxNopLength = 2;
680683

681684
// Cap a single nop emission at the profitable value for the target
682685
NumBytes = std::min(NumBytes, MaxNopLength);
683686

684687
unsigned NopSize;
685-
unsigned Opc, BaseReg, ScaleVal, IndexReg, Displacement, SegmentReg;
688+
unsigned Opc, ScaleVal, IndexReg, Displacement, SegmentReg;
686689
IndexReg = Displacement = SegmentReg = 0;
687-
BaseReg = X86::RAX;
688690
ScaleVal = 1;
689691
switch (NumBytes) {
690692
case 0:
@@ -711,13 +713,13 @@ static unsigned emitNop(MCStreamer &OS, unsigned NumBytes,
711713
NopSize = 5;
712714
Opc = X86::NOOPL;
713715
Displacement = 8;
714-
IndexReg = X86::RAX;
716+
IndexReg = BaseReg;
715717
break;
716718
case 6:
717719
NopSize = 6;
718720
Opc = X86::NOOPW;
719721
Displacement = 8;
720-
IndexReg = X86::RAX;
722+
IndexReg = BaseReg;
721723
break;
722724
case 7:
723725
NopSize = 7;
@@ -728,19 +730,19 @@ static unsigned emitNop(MCStreamer &OS, unsigned NumBytes,
728730
NopSize = 8;
729731
Opc = X86::NOOPL;
730732
Displacement = 512;
731-
IndexReg = X86::RAX;
733+
IndexReg = BaseReg;
732734
break;
733735
case 9:
734736
NopSize = 9;
735737
Opc = X86::NOOPW;
736738
Displacement = 512;
737-
IndexReg = X86::RAX;
739+
IndexReg = BaseReg;
738740
break;
739741
default:
740742
NopSize = 10;
741743
Opc = X86::NOOPW;
742744
Displacement = 512;
743-
IndexReg = X86::RAX;
745+
IndexReg = BaseReg;
744746
SegmentReg = X86::CS;
745747
break;
746748
}

llvm/test/CodeGen/X86/mnop-mcount-01.ll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
; RUN: | FileCheck --check-prefixes=X64 %s
33
; RUN: llc %s -mtriple=i686-linux-gnu -o - -verify-machineinstrs \
44
; RUN: | FileCheck --check-prefix=X86 %s
5+
; RUN: llc %s -mtriple=i686-linux-gnu -mcpu=pentium_pro -o - -verify-machineinstrs \
6+
; RUN: | FileCheck --check-prefix=PPRO %s
57

68
define void @test1() #0 {
79
entry:
@@ -13,6 +15,9 @@ entry:
1315
; X86-LABEL: @test1
1416
; X86: calll __fentry__
1517
; X86: retl
18+
; PPRO-LABEL: @test1
19+
; PPRO: calll __fentry__
20+
; PPRO: retl
1621
}
1722

1823
define void @test2() #1 {
@@ -29,6 +34,10 @@ entry:
2934
; X86: xchgw %ax, %ax
3035
; X86: nop
3136
; X86: retl
37+
; PPRO-LABEL: @test2
38+
; PPRO: nopl 8(%eax,%eax)
39+
; PPRO-NOT: calll __fentry__
40+
; PPRO: retl
3241
}
3342

3443
attributes #0 = { "fentry-call"="true" }

llvm/test/CodeGen/X86/mrecord-mcount-01.ll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
; RUN: | FileCheck --check-prefix=X64 %s
33
; RUN: llc %s -mtriple=i686-linux-gnu -o - -verify-machineinstrs \
44
; RUN: | FileCheck --check-prefix=X86 %s
5+
; RUN: llc %s -mtriple=i686-linux-gnu -mcpu=pentium_pro -o - -verify-machineinstrs \
6+
; RUN: | FileCheck --check-prefix=PPRO %s
57

68
define void @test1() #0 {
79
entry:
@@ -21,6 +23,13 @@ entry:
2123
; X86: .Ltmp0:
2224
; X86: calll __fentry__
2325
; X86: retl
26+
; PPRO-LABEL: test1:
27+
; PPRO: .section __mcount_loc,"a",@progbits
28+
; PPRO: .long .Ltmp0
29+
; PPRO: .text
30+
; PPRO: .Ltmp0:
31+
; PPRO: calll __fentry__
32+
; PPRO: retl
2433
}
2534

2635
define void @test2() #1 {
@@ -45,6 +54,14 @@ entry:
4554
; X86: nop
4655
; X86-NOT: calll __fentry__
4756
; X86: retl
57+
; PPRO-LABEL: test2:
58+
; PPRO: .section __mcount_loc,"a",@progbits
59+
; PPRO: .long .Ltmp1
60+
; PPRO: .text
61+
; PPRO: .Ltmp1:
62+
; PPRO: nopl 8(%eax,%eax)
63+
; PPRO-NOT: calll __fentry__
64+
; PPRO: retl
4865
}
4966

5067
attributes #0 = { "fentry-call"="true" "mrecord-mcount" }

0 commit comments

Comments
 (0)