Skip to content

Commit

Permalink
Add new flag and intrinsic support for MWAITX and MONITORX instructions
Browse files Browse the repository at this point in the history
Summary:

MONITORX/MWAITX instructions provide similar capability to the MONITOR/MWAIT
pair while adding a timer function, such that another termination of the MWAITX
instruction occurs when the timer expires. The presence of the MONITORX and
MWAITX instructions is indicated by CPUID 8000_0001, ECX, bit 29.

The MONITORX and MWAITX instructions are intercepted by the same bits that
intercept MONITOR and MWAIT. MONITORX instruction establishes a range to be
monitored. MWAITX instruction causes the processor to stop instruction execution
and enter an implementation-dependent optimized state until occurrence of a
class of events.

Opcode of MONITORX instruction is "0F 01 FA". Opcode of MWAITX instruction is
"0F 01 FB". These opcode information is used in adding tests for the
disassembler.

These instructions are enabled for AMD's bdver4 architecture.

Patch by Ganesh Gopalasubramanian!

Reviewers: echristo, craig.topper, RKSimon
Subscribers: RKSimon, joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D19795

llvm-svn: 269911
  • Loading branch information
nema-ashutosh committed May 18, 2016
1 parent e64e230 commit 348af9c
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 15 deletions.
11 changes: 11 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsX86.td
Expand Up @@ -8709,3 +8709,14 @@ let TargetPrefix = "x86" in {
def int_x86_sha256msg2 : GCCBuiltin<"__builtin_ia32_sha256msg2">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>;
}

//===----------------------------------------------------------------------===//
// Thread synchronization ops with timer.
let TargetPrefix = "x86" in {
def int_x86_monitorx
: GCCBuiltin<"__builtin_ia32_monitorx">,
Intrinsic<[], [ llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty ], []>;
def int_x86_mwaitx
: GCCBuiltin<"__builtin_ia32_mwaitx">,
Intrinsic<[], [ llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ], []>;
}
2 changes: 2 additions & 0 deletions llvm/lib/Support/Host.cpp
Expand Up @@ -252,6 +252,7 @@ StringRef sys::getHostCPUName() {
GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
bool Em64T = (EDX >> 29) & 0x1;
bool HasTBM = (ECX >> 21) & 0x1;
bool HasMWAITX = (ECX >> 29) & 0x1;

if (memcmp(text.c, "GenuineIntel", 12) == 0) {
switch (Family) {
Expand Down Expand Up @@ -803,6 +804,7 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1);
Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);

bool HasLeaf7 = MaxLevel >= 7 &&
!GetX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/X86/X86.td
Expand Up @@ -198,6 +198,8 @@ def FeatureRDSEED : SubtargetFeature<"rdseed", "HasRDSEED", "true",
"Support RDSEED instruction">;
def FeatureLAHFSAHF : SubtargetFeature<"sahf", "HasLAHFSAHF", "true",
"Support LAHF and SAHF instructions">;
def FeatureMWAITX : SubtargetFeature<"mwaitx", "HasMWAITX", "true",
"Enable MONITORX/MWAITX timer functionality">;
def FeatureMPX : SubtargetFeature<"mpx", "HasMPX", "true",
"Support MPX instructions">;
def FeatureLEAForSP : SubtargetFeature<"lea-sp", "UseLeaForSP", "true",
Expand Down Expand Up @@ -728,7 +730,8 @@ def : Proc<"bdver4", [
FeatureFMA,
FeatureXSAVEOPT,
FeatureFSGSBase,
FeatureLAHFSAHF
FeatureLAHFSAHF,
FeatureMWAITX
]>;

def : Proc<"geode", [FeatureX87, FeatureSlowUAMem16, Feature3DNowA]>;
Expand Down
9 changes: 6 additions & 3 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Expand Up @@ -22349,7 +22349,8 @@ static MachineBasicBlock *emitRDPKRU(MachineInstr *MI, MachineBasicBlock *BB,
}

static MachineBasicBlock *emitMonitor(MachineInstr *MI, MachineBasicBlock *BB,
const X86Subtarget &Subtarget) {
const X86Subtarget &Subtarget,
unsigned Opc) {
DebugLoc dl = MI->getDebugLoc();
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
// Address into RAX/EAX, other two args into ECX, EDX.
Expand All @@ -22366,7 +22367,7 @@ static MachineBasicBlock *emitMonitor(MachineInstr *MI, MachineBasicBlock *BB,
.addReg(MI->getOperand(ValOps+1).getReg());

// The instruction doesn't actually take any operands though.
BuildMI(*BB, MI, dl, TII->get(X86::MONITORrrr));
BuildMI(*BB, MI, dl, TII->get(Opc));

MI->eraseFromParent(); // The pseudo is gone now.
return BB;
Expand Down Expand Up @@ -23867,7 +23868,9 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,

// Thread synchronization.
case X86::MONITOR:
return emitMonitor(MI, BB, Subtarget);
return emitMonitor(MI, BB, Subtarget, X86::MONITORrrr);
case X86::MONITORX:
return emitMonitor(MI, BB, Subtarget, X86::MONITORXrrr);
// PKU feature
case X86::WRPKRU:
return emitWRPKRU(MI, BB, Subtarget);
Expand Down
35 changes: 24 additions & 11 deletions llvm/lib/Target/X86/X86InstrInfo.td
Expand Up @@ -847,6 +847,7 @@ def HasPRFCHW : Predicate<"Subtarget->hasPRFCHW()">;
def HasRDSEED : Predicate<"Subtarget->hasRDSEED()">;
def HasPrefetchW : Predicate<"Subtarget->hasPRFCHW()">;
def HasLAHFSAHF : Predicate<"Subtarget->hasLAHFSAHF()">;
def HasMWAITX : Predicate<"Subtarget->hasMWAITX()">;
def FPStackf32 : Predicate<"!Subtarget->hasSSE1()">;
def FPStackf64 : Predicate<"!Subtarget->hasSSE2()">;
def HasMPX : Predicate<"Subtarget->hasMPX()">;
Expand Down Expand Up @@ -2401,22 +2402,34 @@ defm TZMSK : tbm_binary_intr<0x01, "tzmsk", MRM4r, MRM4m>;
//===----------------------------------------------------------------------===//
// MONITORX/MWAITX Instructions
//
let SchedRW = [WriteSystem] in {
let Uses = [EAX, ECX, EDX] in
def MONITORXrrr : I<0x01, MRM_FA, (outs), (ins), "monitorx", [],
IIC_SSE_MONITOR>, TB;
let Uses = [ECX, EAX, EBX] in
def MWAITXrr : I<0x01, MRM_FB, (outs), (ins), "mwaitx", [], IIC_SSE_MWAIT>,
TB;
let SchedRW = [ WriteSystem ] in {
let usesCustomInserter = 1 in {
def MONITORX : PseudoI<(outs), (ins i32mem:$src1, GR32:$src2, GR32:$src3),
[(int_x86_monitorx addr:$src1, GR32:$src2, GR32:$src3)]>,
Requires<[ HasMWAITX ]>;
}

let Uses = [ EAX, ECX, EDX ] in {
def MONITORXrrr : I<0x01, MRM_FA, (outs), (ins), "monitorx", [], IIC_SSE_MONITORX>,
TB, Requires<[ HasMWAITX ]>;
}

let Uses = [ ECX, EAX, EBX ] in {
def MWAITXrrr : I<0x01, MRM_FB, (outs), (ins), "mwaitx",
[(int_x86_mwaitx ECX, EAX, EBX)], IIC_SSE_MWAITX>,
TB, Requires<[ HasMWAITX ]>;
}
} // SchedRW

def : InstAlias<"mwaitx\t{%eax, %ecx, %ebx|ebx, ecx, eax}", (MWAITXrr)>, Requires<[Not64BitMode]>;
def : InstAlias<"mwaitx\t{%rax, %rcx, %rbx|rbx, rcx, rax}", (MWAITXrr)>, Requires<[In64BitMode]>;
def : InstAlias<"mwaitx\t{%eax, %ecx, %ebx|ebx, ecx, eax}", (MWAITXrrr)>,
Requires<[ Not64BitMode ]>;
def : InstAlias<"mwaitx\t{%rax, %rcx, %rbx|rbx, rcx, rax}", (MWAITXrrr)>,
Requires<[ In64BitMode ]>;

def : InstAlias<"monitorx\t{%eax, %ecx, %edx|edx, ecx, eax}", (MONITORXrrr)>,
Requires<[Not64BitMode]>;
Requires<[ Not64BitMode ]>;
def : InstAlias<"monitorx\t{%rax, %rcx, %rdx|rdx, rcx, rax}", (MONITORXrrr)>,
Requires<[In64BitMode]>;
Requires<[ In64BitMode ]>;

//===----------------------------------------------------------------------===//
// CLZERO Instruction
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/X86/X86InstrSSE.td
Expand Up @@ -5802,6 +5802,7 @@ def MONITOR : PseudoI<(outs), (ins i32mem:$src1, GR32:$src2, GR32:$src3),
let Uses = [EAX, ECX, EDX] in
def MONITORrrr : I<0x01, MRM_C8, (outs), (ins), "monitor", [], IIC_SSE_MONITOR>,
TB, Requires<[HasSSE3]>;

let Uses = [ECX, EAX] in
def MWAITrr : I<0x01, MRM_C9, (outs), (ins), "mwait",
[(int_x86_sse3_mwait ECX, EAX)], IIC_SSE_MWAIT>,
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/X86/X86Schedule.td
Expand Up @@ -364,6 +364,8 @@ def IIC_SSE_PALIGNRR : InstrItinClass;
def IIC_SSE_PALIGNRM : InstrItinClass;
def IIC_SSE_MWAIT : InstrItinClass;
def IIC_SSE_MONITOR : InstrItinClass;
def IIC_SSE_MWAITX : InstrItinClass;
def IIC_SSE_MONITORX : InstrItinClass;

def IIC_SSE_PREFETCH : InstrItinClass;
def IIC_SSE_PAUSE : InstrItinClass;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/X86/X86Subtarget.cpp
Expand Up @@ -313,6 +313,7 @@ void X86Subtarget::initializeEnvironment() {
HasPRFCHW = false;
HasRDSEED = false;
HasLAHFSAHF = false;
HasMWAITX = false;
HasMPX = false;
IsBTMemSlow = false;
IsSHLDSlow = false;
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/X86/X86Subtarget.h
Expand Up @@ -164,6 +164,9 @@ class X86Subtarget final : public X86GenSubtargetInfo {
/// Processor has LAHF/SAHF instructions.
bool HasLAHFSAHF;

/// Processor has MONITORX/MWAITX instructions.
bool HasMWAITX;

/// Processor has Prefetch with intent to Write instruction
bool HasPFPREFETCHWT1;

Expand Down Expand Up @@ -421,6 +424,7 @@ class X86Subtarget final : public X86GenSubtargetInfo {
bool hasPRFCHW() const { return HasPRFCHW; }
bool hasRDSEED() const { return HasRDSEED; }
bool hasLAHFSAHF() const { return HasLAHFSAHF; }
bool hasMWAITX() const { return HasMWAITX; }
bool isBTMemSlow() const { return IsBTMemSlow; }
bool isSHLDSlow() const { return IsSHLDSlow; }
bool isUnalignedMem16Slow() const { return IsUAMem16Slow; }
Expand Down
38 changes: 38 additions & 0 deletions llvm/test/CodeGen/X86/mwaitx.ll
@@ -0,0 +1,38 @@
; RUN: llc < %s -mtriple=x86_64-linux -mattr=+mwaitx | FileCheck %s
; RUN: llc < %s -mtriple=x86_64-win32 -mattr=+mwaitx | FileCheck %s -check-prefix=WIN64
; RUN: llc < %s -mtriple=x86_64-linux -mcpu=bdver4 | FileCheck %s
; RUN: llc < %s -mtriple=x86_64-win32 -mcpu=bdver4 | FileCheck %s -check-prefix=WIN64

; CHECK-LABEL: foo:
; CHECK: leaq (%rdi), %rax
; CHECK-NEXT: movl %esi, %ecx
; CHECK-NEXT: monitorx
; WIN64-LABEL: foo:
; WIN64: leaq (%rcx), %rax
; WIN64-NEXT: movl %edx, %ecx
; WIN64-NEXT: movl %r8d, %edx
; WIN64-NEXT: monitorx
define void @foo(i8* %P, i32 %E, i32 %H) nounwind {
entry:
tail call void @llvm.x86.monitorx(i8* %P, i32 %E, i32 %H)
ret void
}

declare void @llvm.x86.monitorx(i8*, i32, i32) nounwind

; CHECK-LABEL: bar:
; CHECK: movl %edi, %ecx
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: movl %edx, %ebx
; CHECK-NEXT: mwaitx
; WIN64-LABEL: bar:
; WIN64: movl %edx, %eax
; WIN64: movl %r8d, %ebx
; WIN64-NEXT: mwaitx
define void @bar(i32 %E, i32 %H, i32 %C) nounwind {
entry:
tail call void @llvm.x86.mwaitx(i32 %E, i32 %H, i32 %C)
ret void
}

declare void @llvm.x86.mwaitx(i32, i32, i32) nounwind
6 changes: 6 additions & 0 deletions llvm/test/MC/Disassembler/X86/simple-tests.txt
Expand Up @@ -51,6 +51,12 @@
# CHECK: rdtscp
0x0f 0x01 0xf9

# CHECK: monitorx
0x0f 0x01 0xfa

# CHECK: mwaitx
0x0f 0x01 0xfb

# CHECK: vmxon
0xf3 0x0f 0xc7 0x30

Expand Down
6 changes: 6 additions & 0 deletions llvm/test/MC/Disassembler/X86/x86-32.txt
Expand Up @@ -90,6 +90,12 @@
# CHECK: rdtscp
0x0f 0x01 0xf9

# CHECK: monitorx
0x0f 0x01 0xfa

# CHECK: mwaitx
0x0f 0x01 0xfb

# CHECK: vmxon
0xf3 0x0f 0xc7 0x30

Expand Down

0 comments on commit 348af9c

Please sign in to comment.