Index: include/llvm/IR/IntrinsicsX86.td =================================================================== --- include/llvm/IR/IntrinsicsX86.td +++ include/llvm/IR/IntrinsicsX86.td @@ -6421,3 +6421,12 @@ def int_x86_clzero : GCCBuiltin<"__builtin_ia32_clzero">, Intrinsic<[], [llvm_ptr_ty], []>; } + +//===----------------------------------------------------------------------===// +// Cache line write back intrinsics + +// Write back no-invalidate +let TargetPrefix = "x86" in { + def int_x86_wbnoinvd : GCCBuiltin<"__builtin_ia32_wbnoinvd">, + Intrinsic<[], [], []>; +} Index: lib/Support/Host.cpp =================================================================== --- lib/Support/Host.cpp +++ lib/Support/Host.cpp @@ -1216,9 +1216,12 @@ Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1); Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1); + // Miscellaneous memory related features, detected by + // using the 0x80000008 leaf of the CPUID instruction bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 && !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX); - Features["clzero"] = HasExtLeaf8 && ((EBX >> 0) & 1); + Features["clzero"] = HasExtLeaf8 && ((EBX >> 0) & 1); + Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1); bool HasLeaf7 = MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); Index: lib/Target/X86/X86.td =================================================================== --- lib/Target/X86/X86.td +++ lib/Target/X86/X86.td @@ -249,6 +249,8 @@ "Flush A Cache Line Optimized">; def FeatureCLWB : SubtargetFeature<"clwb", "HasCLWB", "true", "Cache Line Write Back">; +def FeatureWBNOINVD : SubtargetFeature<"wbnoinvd", "HasWBNOINVD", "true", + "Write Back No Invalidate">; def FeatureRDPID : SubtargetFeature<"rdpid", "HasRDPID", "true", "Support RDPID instructions">; // On some processors, instructions that implicitly take two memory operands are @@ -422,7 +424,9 @@ def ProcIntelCNL : SubtargetFeature<"cannonlake", "X86ProcFamily", "IntelCannonlake", "Intel Cannonlake processors">; def ProcIntelICL : SubtargetFeature<"icelake", "X86ProcFamily", - "IntelIcelake", "Intel Icelake processors">; + "IntelIcelake", "Intel Icelake Client processors">; +def ProcIntelICX : SubtargetFeature<"icelakex", "X86ProcFamily", + "IntelIcelakeServer", "Intel Icelake Server processors">; class Proc Features> : ProcessorModel; @@ -819,6 +823,14 @@ ]>; def : IcelakeProc<"icelake">; +class IcelakeServerProc : ProcModel; +def : IcelakeServerProc<"icelakex">; + // AMD CPUs. def : Proc<"k6", [FeatureX87, FeatureSlowUAMem16, FeatureMMX]>; Index: lib/Target/X86/X86InstrInfo.td =================================================================== --- lib/Target/X86/X86InstrInfo.td +++ lib/Target/X86/X86InstrInfo.td @@ -880,6 +880,7 @@ def HasIBT : Predicate<"Subtarget->hasIBT()">; def HasCLFLUSHOPT : Predicate<"Subtarget->hasCLFLUSHOPT()">; def HasCLWB : Predicate<"Subtarget->hasCLWB()">; +def HasWBNOINVD : Predicate<"Subtarget->hasWBNOINVD()">; def HasRDPID : Predicate<"Subtarget->hasRDPID()">; def HasCmpxchg16b: Predicate<"Subtarget->hasCmpxchg16b()">; def Not64BitMode : Predicate<"!Subtarget->is64Bit()">, Index: lib/Target/X86/X86InstrSystem.td =================================================================== --- lib/Target/X86/X86InstrSystem.td +++ lib/Target/X86/X86InstrSystem.td @@ -482,6 +482,12 @@ let SchedRW = [WriteSystem] in { def INVD : I<0x08, RawFrm, (outs), (ins), "invd", [], IIC_INVD>, TB; def WBINVD : I<0x09, RawFrm, (outs), (ins), "wbinvd", [], IIC_INVD>, TB; + +// wbnoinvd is like wbinvd, except without invalidation +// XS refers to the extra F3 prefix -- which originally used refer to repetition +def WBNOINVD : I<0x09, RawFrm, (outs), (ins), "wbnoinvd", + [(int_x86_wbnoinvd)], IIC_INVD>, XS, + Requires<[HasWBNOINVD]>; } // SchedRW //===----------------------------------------------------------------------===// Index: lib/Target/X86/X86Subtarget.h =================================================================== --- lib/Target/X86/X86Subtarget.h +++ lib/Target/X86/X86Subtarget.h @@ -64,6 +64,7 @@ IntelSKX, IntelCannonlake, IntelIcelake, + IntelIcelakeServer, }; protected: @@ -359,6 +360,9 @@ /// Processor supports Cache Line Write Back instruction bool HasCLWB; + /// Processor supports Write Back No Invalidate instruction + bool HasWBNOINVD; + /// Processor support RDPID instruction bool HasRDPID; @@ -621,6 +625,7 @@ bool hasIBT() const { return HasIBT; } bool hasCLFLUSHOPT() const { return HasCLFLUSHOPT; } bool hasCLWB() const { return HasCLWB; } + bool hasWBNOINVD() const { return HasWBNOINVD; } bool hasRDPID() const { return HasRDPID; } bool useRetpoline() const { return UseRetpoline; } bool useRetpolineExternalThunk() const { return UseRetpolineExternalThunk; } Index: lib/Target/X86/X86Subtarget.cpp =================================================================== --- lib/Target/X86/X86Subtarget.cpp +++ lib/Target/X86/X86Subtarget.cpp @@ -324,6 +324,7 @@ HasSGX = false; HasCLFLUSHOPT = false; HasCLWB = false; + HasWBNOINVD = false; HasRDPID = false; UseRetpoline = false; UseRetpolineExternalThunk = false; Index: test/CodeGen/X86/cpus.ll =================================================================== --- test/CodeGen/X86/cpus.ll +++ test/CodeGen/X86/cpus.ll @@ -47,6 +47,7 @@ ; RUN: llc < %s -o /dev/null -mtriple=x86_64-unknown-unknown -mcpu=skx 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ERROR --allow-empty ; RUN: llc < %s -o /dev/null -mtriple=x86_64-unknown-unknown -mcpu=cannonlake 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ERROR --allow-empty ; RUN: llc < %s -o /dev/null -mtriple=x86_64-unknown-unknown -mcpu=icelake 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ERROR --allow-empty +; RUN: llc < %s -o /dev/null -mtriple=x86_64-unknown-unknown -mcpu=icelakex 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ERROR --allow-empty ; RUN: llc < %s -o /dev/null -mtriple=x86_64-unknown-unknown -mcpu=atom 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ERROR --allow-empty ; RUN: llc < %s -o /dev/null -mtriple=x86_64-unknown-unknown -mcpu=bonnell 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ERROR --allow-empty ; RUN: llc < %s -o /dev/null -mtriple=x86_64-unknown-unknown -mcpu=silvermont 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ERROR --allow-empty Index: test/CodeGen/X86/wbnoinvd-intrinsic.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/wbnoinvd-intrinsic.ll @@ -0,0 +1,12 @@ +; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+wbnoinvd | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+wbnoinvd | FileCheck %s + +define void @wbnoinvd() nounwind { +; CHECK-LABEL: wbnoinvd: +; CHECK: # %bb.0: +; CHECK-NEXT: wbnoinvd +; CHECK-NEXT: ret{{.}} + tail call void @llvm.x86.wbnoinvd() + ret void +} +declare void @llvm.x86.wbnoinvd() nounwind Index: test/MC/Disassembler/X86/x86-32.txt =================================================================== --- test/MC/Disassembler/X86/x86-32.txt +++ test/MC/Disassembler/X86/x86-32.txt @@ -820,3 +820,6 @@ # CHECK: ptwritel %eax 0xf3 0x0f 0xae 0xe0 + +# CHECK: wbnoinvd +0xf3 0x0f 0x09 Index: test/MC/Disassembler/X86/x86-64.txt =================================================================== --- test/MC/Disassembler/X86/x86-64.txt +++ test/MC/Disassembler/X86/x86-64.txt @@ -516,3 +516,6 @@ # CHECK: ptwriteq %rax 0xf3 0x48 0x0f 0xae 0xe0 + +# CHECK: wbnoinvd +0xf3 0x0f 0x09 Index: test/MC/X86/x86-32-coverage.s =================================================================== --- test/MC/X86/x86-32-coverage.s +++ test/MC/X86/x86-32-coverage.s @@ -2776,6 +2776,10 @@ // CHECK: encoding: [0x0f,0x09] wbinvd +// CHECK: wbnoinvd +// CHECK: encoding: [0xf3,0x0f,0x09] + wbnoinvd + // CHECK: cpuid // CHECK: encoding: [0x0f,0xa2] cpuid Index: test/MC/X86/x86-64.s =================================================================== --- test/MC/X86/x86-64.s +++ test/MC/X86/x86-64.s @@ -1559,6 +1559,10 @@ // CHECK: encoding: [0xf3,0x48,0x0f,0xae,0xe0] ptwriteq %rax +// CHECK: wbnoinvd +// CHECK: encoding: [0xf3,0x0f,0x09] + wbnoinvd + // __asm __volatile( // "pushf \n\t" // "popf \n\t"