Index: include/llvm/IR/IntrinsicsX86.td =================================================================== --- include/llvm/IR/IntrinsicsX86.td +++ include/llvm/IR/IntrinsicsX86.td @@ -6509,3 +6509,14 @@ 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_wbinvd : GCCBuiltin<"__builtin_ia32_wbinvd">, + Intrinsic<[], [], []>; + def int_x86_wbnoinvd : GCCBuiltin<"__builtin_ia32_wbnoinvd">, + Intrinsic<[], [], []>; +} Index: lib/Support/Host.cpp =================================================================== --- lib/Support/Host.cpp +++ lib/Support/Host.cpp @@ -1215,9 +1215,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["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 @@ -246,6 +246,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">; // On some processors, instructions that implicitly take two memory operands are // slow. In practice, this means that CALL, PUSH, and POP with memory operands // should be avoided in favor of a MOV + register CALL/PUSH/POP. @@ -745,7 +747,8 @@ class IcelakeProc : ProcModel; def : IcelakeProc<"icelake">; Index: lib/Target/X86/X86InstrInfo.td =================================================================== --- lib/Target/X86/X86InstrInfo.td +++ lib/Target/X86/X86InstrInfo.td @@ -897,6 +897,7 @@ def HasIBT : Predicate<"Subtarget->hasIBT()">; def HasCLFLUSHOPT : Predicate<"Subtarget->hasCLFLUSHOPT()">; def HasCLWB : Predicate<"Subtarget->hasCLWB()">; +def HasWBNOINVD : Predicate<"Subtarget->hasWBNOINVD()">; def HasCmpxchg16b: Predicate<"Subtarget->hasCmpxchg16b()">; def Not64BitMode : Predicate<"!Subtarget->is64Bit()">, AssemblerPredicate<"!Mode64Bit", "Not 64-bit mode">; Index: lib/Target/X86/X86InstrSystem.td =================================================================== --- lib/Target/X86/X86InstrSystem.td +++ lib/Target/X86/X86InstrSystem.td @@ -479,7 +479,14 @@ // Cache instructions 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; +def WBINVD : I<0x09, RawFrm, (outs), (ins), "wbinvd", + [(int_x86_wbinvd)], IIC_INVD>, TB; + +// wbonivd 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 @@ -341,6 +341,9 @@ /// Processor supports Cache Line Write Back instruction bool HasCLWB; + /// Processor supports Write Back No Invalidate instruction + bool HasWBNOINVD; + /// Use software floating point for code generation. bool UseSoftFloat; @@ -574,6 +577,7 @@ bool hasIBT() const { return HasIBT; } bool hasCLFLUSHOPT() const { return HasCLFLUSHOPT; } bool hasCLWB() const { return HasCLWB; } + bool hasWBNOINVD() const { return HasWBNOINVD; } bool isXRaySupported() const override { return is64Bit(); } Index: lib/Target/X86/X86Subtarget.cpp =================================================================== --- lib/Target/X86/X86Subtarget.cpp +++ lib/Target/X86/X86Subtarget.cpp @@ -314,6 +314,7 @@ HasSGX = false; HasCLFLUSHOPT = false; HasCLWB = false; + HasWBNOINVD = false; IsPMULLDSlow = false; IsSHLDSlow = false; IsUAMem16Slow = false; Index: test/CodeGen/X86/wbinvd-intrinsic.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/wbinvd-intrinsic.ll @@ -0,0 +1,12 @@ +; RUN: llc < %s -mtriple=i686-- | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s + +define void @wbinvd() nounwind { +; CHECK-LABEL: wbinvd: +; CHECK: # %bb.0: +; CHECK-NEXT: wbinvd +; CHECK-NEXT: ret{{.}} + tail call void @llvm.x86.wbinvd() + ret void +} +declare void @llvm.x86.wbinvd() nounwind 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/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 @@ -1557,3 +1557,11 @@ // CHECK: ptwriteq %rax // CHECK: encoding: [0xf3,0x48,0x0f,0xae,0xe0] ptwriteq %rax + +// CHECK: wbinvd +// CHECK: encoding: [0x0f,0x09] + wbinvd + +// CHECK: wbnoinvd +// CHECK: encoding: [0xf3,0x0f,0x09] + wbnoinvd