diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index 511f3145e7e80a..e5a6497020377f 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -3175,6 +3175,8 @@ X86 .. option:: -mtbm, -mno-tbm +.. option:: -mtsxldtrk, -mno-tsxldtrk + .. option:: -mvaes, -mno-vaes .. option:: -mvpclmulqdq, -mno-vpclmulqdq diff --git a/clang/include/clang/Basic/BuiltinsX86.def b/clang/include/clang/Basic/BuiltinsX86.def index ccb6f341d63da6..7dcbcf086ede44 100644 --- a/clang/include/clang/Basic/BuiltinsX86.def +++ b/clang/include/clang/Basic/BuiltinsX86.def @@ -1903,6 +1903,10 @@ TARGET_BUILTIN(__builtin_ia32_enqcmds, "Ucv*vC*", "n", "enqcmd") // SERIALIZE TARGET_BUILTIN(__builtin_ia32_serialize, "v", "n", "serialize") +// TSXLDTRK +TARGET_BUILTIN(__builtin_ia32_xsusldtrk, "v", "n", "tsxldtrk") +TARGET_BUILTIN(__builtin_ia32_xresldtrk, "v", "n", "tsxldtrk") + // MSVC TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 0d057ac579f5ad..2caf02b51d40cf 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3230,6 +3230,8 @@ def msha : Flag<["-"], "msha">, Group; def mno_sha : Flag<["-"], "mno-sha">, Group; def mtbm : Flag<["-"], "mtbm">, Group; def mno_tbm : Flag<["-"], "mno-tbm">, Group; +def mtsxldtrk : Flag<["-"], "mtsxldtrk">, Group; +def mno_tsxldtrk : Flag<["-"], "mno-tsxldtrk">, Group; def mvaes : Flag<["-"], "mvaes">, Group; def mno_vaes : Flag<["-"], "mno-vaes">, Group; def mvpclmulqdq : Flag<["-"], "mvpclmulqdq">, Group; diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index def23a65edde71..747d07692fee64 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -859,6 +859,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector &Features, HasENQCMD = true; } else if (Feature == "+serialize") { HasSERIALIZE = true; + } else if (Feature == "+tsxldtrk") { + HasTSXLDTRK = true; } X86SSEEnum Level = llvm::StringSwitch(Feature) @@ -1251,6 +1253,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__ENQCMD__"); if (HasSERIALIZE) Builder.defineMacro("__SERIALIZE__"); + if (HasTSXLDTRK) + Builder.defineMacro("__TSXLDTRK__"); // Each case falls through to the previous one here. switch (SSELevel) { @@ -1407,6 +1411,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const { .Case("sse4.2", true) .Case("sse4a", true) .Case("tbm", true) + .Case("tsxldtrk", true) .Case("vaes", true) .Case("vpclmulqdq", true) .Case("wbnoinvd", true) @@ -1491,6 +1496,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("sse4.2", SSELevel >= SSE42) .Case("sse4a", XOPLevel >= SSE4A) .Case("tbm", HasTBM) + .Case("tsxldtrk", HasTSXLDTRK) .Case("vaes", HasVAES) .Case("vpclmulqdq", HasVPCLMULQDQ) .Case("wbnoinvd", HasWBNOINVD) diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index e14b101a3fa5f3..a68109a604d598 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -125,6 +125,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { bool HasINVPCID = false; bool HasENQCMD = false; bool HasSERIALIZE = false; + bool HasTSXLDTRK = false; protected: /// Enumeration of all of the X86 CPUs supported by Clang. diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index d6c8ed5e1fc6f7..60d359ff9aa2d9 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -104,6 +104,7 @@ set(files tbmintrin.h tgmath.h tmmintrin.h + tsxldtrkintrin.h unwind.h vadefs.h vaesintrin.h diff --git a/clang/lib/Headers/cpuid.h b/clang/lib/Headers/cpuid.h index b06c37fa08ccf7..ebce6478178856 100644 --- a/clang/lib/Headers/cpuid.h +++ b/clang/lib/Headers/cpuid.h @@ -183,6 +183,7 @@ #define bit_AVX5124VNNIW 0x00000004 #define bit_AVX5124FMAPS 0x00000008 #define bit_SERIALIZE 0x00004000 +#define bit_TSXLDTRK 0x00010000 #define bit_PCONFIG 0x00040000 #define bit_IBT 0x00100000 diff --git a/clang/lib/Headers/immintrin.h b/clang/lib/Headers/immintrin.h index 164b1f40478dc8..64841412155b8c 100644 --- a/clang/lib/Headers/immintrin.h +++ b/clang/lib/Headers/immintrin.h @@ -438,6 +438,10 @@ _storebe_i64(void * __P, long long __D) { #include #endif +#if !defined(_MSC_VER) || __has_feature(modules) || defined(__TSXLDTRK__) +#include +#endif + #if defined(_MSC_VER) && __has_extension(gnu_asm) /* Define the default attributes for these intrinsics */ #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__)) diff --git a/clang/lib/Headers/tsxldtrkintrin.h b/clang/lib/Headers/tsxldtrkintrin.h new file mode 100644 index 00000000000000..491823e93fc027 --- /dev/null +++ b/clang/lib/Headers/tsxldtrkintrin.h @@ -0,0 +1,56 @@ +/*===------------- tsxldtrkintrin.h - tsxldtrk intrinsics ------------------=== + * + * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + * See https://llvm.org/LICENSE.txt for license information. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __IMMINTRIN_H +#error "Never use directly; include instead." +#endif + +#ifndef __TSXLDTRKINTRIN_H +#define __TSXLDTRKINTRIN_H + +/* Define the default attributes for the functions in this file */ +#define _DEFAULT_FN_ATTRS \ + __attribute__((__always_inline__, __nodebug__, __target__("tsxldtrk"))) + +/// Marks the start of an TSX (RTM) suspend load address tracking region. If +/// this intrinsic is used inside a transactional region, subsequent loads +/// are not added to the read set of the transaction. If it's used inside a +/// suspend load address tracking region it will cause transaction abort. +/// If it's used outside of a transactional region it behaves like a NOP. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c XSUSLDTRK instruction. +/// +static __inline__ void _DEFAULT_FN_ATTRS +_xsusldtrk (void) +{ + __builtin_ia32_xsusldtrk(); +} + +/// Marks the end of an TSX (RTM) suspend load address tracking region. If this +/// intrinsic is used inside a suspend load address tracking region it will +/// end the suspend region and all following load addresses will be added to +/// the transaction read set. If it's used inside an active transaction but +/// not in a suspend region it will cause transaction abort. If it's used +/// outside of a transactional region it behaves like a NOP. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c XRESLDTRK instruction. +/// +static __inline__ void _DEFAULT_FN_ATTRS +_xresldtrk (void) +{ + __builtin_ia32_xresldtrk(); +} + +#undef _DEFAULT_FN_ATTRS + +#endif /* __TSXLDTRKINTRIN_H */ diff --git a/clang/test/CodeGen/x86-tsxldtrk-builtins.c b/clang/test/CodeGen/x86-tsxldtrk-builtins.c new file mode 100644 index 00000000000000..96c53704e1e42c --- /dev/null +++ b/clang/test/CodeGen/x86-tsxldtrk-builtins.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -ffreestanding -triple i386-unknown-unknown -target-feature +tsxldtrk -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -ffreestanding -triple x86_64-unknown-unknown -target-feature +tsxldtrk -emit-llvm -o - | FileCheck %s + +#include + +void test_xsusldtrk() { +// CHECK-LABEL: test_xsusldtrk +// CHECK: call void @llvm.x86.xsusldtrk() + _xsusldtrk(); +} + +void test_xresldtrk() { +// CHECK-LABEL: test_xresldtrk +// CHECK: call void @llvm.x86.xresldtrk() + _xresldtrk(); +} diff --git a/clang/test/Driver/x86-target-features.c b/clang/test/Driver/x86-target-features.c index 872a228c2a333f..a280caff236657 100644 --- a/clang/test/Driver/x86-target-features.c +++ b/clang/test/Driver/x86-target-features.c @@ -208,3 +208,8 @@ // RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-serialize %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-SERIALIZE %s // SERIALIZE: "-target-feature" "+serialize" // NO-SERIALIZE: "-target-feature" "-serialize" + +// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mtsxldtrk %s -### -o %t.o 2>&1 | FileCheck --check-prefix=TSXLDTRK %s +// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-tsxldtrk %s -### -o %t.o 2>&1 | FileCheck --check-prefix=NO-TSXLDTRK %s +// TSXLDTRK: "-target-feature" "+tsxldtrk" +// NO-TSXLDTRK: "-target-feature" "-tsxldtrk" diff --git a/clang/test/Preprocessor/x86_target_features.c b/clang/test/Preprocessor/x86_target_features.c index e3bfdc5270899d..8e24c151872082 100644 --- a/clang/test/Preprocessor/x86_target_features.c +++ b/clang/test/Preprocessor/x86_target_features.c @@ -491,3 +491,11 @@ // RUN: %clang -target i386-unknown-unknown -march=atom -mno-serialize -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=NOSERIALIZE %s // NOSERIALIZE-NOT: #define __SERIALIZE__ 1 + +// RUN: %clang -target i386-unknown-unknown -march=atom -mtsxldtrk -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=TSXLDTRK %s + +// TSXLDTRK: #define __TSXLDTRK__ 1 + +// RUN: %clang -target i386-unknown-unknown -march=atom -mno-tsxldtrk -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=NOTSXLDTRK %s + +// NOTSXLDTRK-NOT: #define __TSXLDTRK__ 1 diff --git a/llvm/include/llvm/IR/IntrinsicsX86.td b/llvm/include/llvm/IR/IntrinsicsX86.td index 8623be78478afa..4a85b033fe04d7 100644 --- a/llvm/include/llvm/IR/IntrinsicsX86.td +++ b/llvm/include/llvm/IR/IntrinsicsX86.td @@ -4938,3 +4938,13 @@ let TargetPrefix = "x86" in { def int_x86_serialize : GCCBuiltin<"__builtin_ia32_serialize">, Intrinsic<[], [], []>; } + +//===----------------------------------------------------------------------===// +// TSXLDTRK - TSX Suspend Load Address Tracking + +let TargetPrefix = "x86" in { + def int_x86_xsusldtrk : GCCBuiltin<"__builtin_ia32_xsusldtrk">, + Intrinsic<[], [], []>; + def int_x86_xresldtrk : GCCBuiltin<"__builtin_ia32_xresldtrk">, + Intrinsic<[], [], []>; +} diff --git a/llvm/lib/Support/Host.cpp b/llvm/lib/Support/Host.cpp index 6b8f7ca2c45bb4..f23645680648f1 100644 --- a/llvm/lib/Support/Host.cpp +++ b/llvm/lib/Support/Host.cpp @@ -1478,6 +1478,7 @@ bool sys::getHostCPUFeatures(StringMap &Features) { Features["enqcmd"] = HasLeaf7 && ((ECX >> 29) & 1); Features["serialize"] = HasLeaf7 && ((EDX >> 14) & 1); + Features["tsxldtrk"] = HasLeaf7 && ((EDX >> 16) & 1); // There are two CPUID leafs which information associated with the pconfig // instruction: // EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td index 13ccf3c940b920..49dbfdebc59f65 100644 --- a/llvm/lib/Target/X86/X86.td +++ b/llvm/lib/Target/X86/X86.td @@ -275,6 +275,8 @@ def FeatureENQCMD : SubtargetFeature<"enqcmd", "HasENQCMD", "true", "Has ENQCMD instructions">; def FeatureSERIALIZE : SubtargetFeature<"serialize", "HasSERIALIZE", "true", "Has serialize instruction">; +def FeatureTSXLDTRK : SubtargetFeature<"tsxldtrk", "HasTSXLDTRK", "true", + "Support TSXLDTRK instructions">; // 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. diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 4e2bc02dcdd346..6daa6ef394cf6a 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -956,6 +956,7 @@ def HasCmpxchg16b: Predicate<"Subtarget->hasCmpxchg16b()">; def HasPCONFIG : Predicate<"Subtarget->hasPCONFIG()">; def HasENQCMD : Predicate<"Subtarget->hasENQCMD()">; def HasSERIALIZE : Predicate<"Subtarget->hasSERIALIZE()">; +def HasTSXLDTRK : Predicate<"Subtarget->hasTSXLDTRK()">; def Not64BitMode : Predicate<"!Subtarget->is64Bit()">, AssemblerPredicate<(all_of (not Mode64Bit)), "Not 64-bit mode">; def In64BitMode : Predicate<"Subtarget->is64Bit()">, @@ -2869,6 +2870,16 @@ def SERIALIZE : I<0x01, MRM_E8, (outs), (ins), "serialize", [(int_x86_serialize)]>, PS, Requires<[HasSERIALIZE]>; +//===----------------------------------------------------------------------===// +// TSXLDTRK - TSX Suspend Load Address Tracking +// +let Predicates = [HasTSXLDTRK] in { + def XSUSLDTRK : I<0x01, MRM_E8, (outs), (ins), "xsusldtrk", + [(int_x86_xsusldtrk)]>, XD; + def XRESLDTRK : I<0x01, MRM_E9, (outs), (ins), "xresldtrk", + [(int_x86_xresldtrk)]>, XD; +} + //===----------------------------------------------------------------------===// // Pattern fragments to auto generate TBM instructions. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/X86/X86Subtarget.h b/llvm/lib/Target/X86/X86Subtarget.h index a23588a07e57fd..658401c293000f 100644 --- a/llvm/lib/Target/X86/X86Subtarget.h +++ b/llvm/lib/Target/X86/X86Subtarget.h @@ -400,6 +400,9 @@ class X86Subtarget final : public X86GenSubtargetInfo { /// Processor supports SERIALIZE instruction bool HasSERIALIZE = false; + /// Processor supports TSXLDTRK instruction + bool HasTSXLDTRK = false; + /// Processor has a single uop BEXTR implementation. bool HasFastBEXTR = false; @@ -716,6 +719,7 @@ class X86Subtarget final : public X86GenSubtargetInfo { bool hasINVPCID() const { return HasINVPCID; } bool hasENQCMD() const { return HasENQCMD; } bool hasSERIALIZE() const { return HasSERIALIZE; } + bool hasTSXLDTRK() const { return HasTSXLDTRK; } bool useRetpolineIndirectCalls() const { return UseRetpolineIndirectCalls; } bool useRetpolineIndirectBranches() const { return UseRetpolineIndirectBranches; diff --git a/llvm/test/CodeGen/X86/tsxldtrk-intrinsic.ll b/llvm/test/CodeGen/X86/tsxldtrk-intrinsic.ll new file mode 100644 index 00000000000000..5b780e14957932 --- /dev/null +++ b/llvm/test/CodeGen/X86/tsxldtrk-intrinsic.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+tsxldtrk | FileCheck %s --check-prefix=X64 +; RUN: llc < %s -mtriple=i386-unknown-unknown -mattr=+tsxldtrk | FileCheck %s --check-prefix=X86 +; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -mattr=+tsxldtrk | FileCheck %s --check-prefix=X32 + +define void @test_tsxldtrk() { +; X64-LABEL: test_tsxldtrk: +; X64: # %bb.0: # %entry +; X64-NEXT: xsusldtrk +; X64-NEXT: xresldtrk +; X64-NEXT: retq +; +; X86-LABEL: test_tsxldtrk: +; X86: # %bb.0: # %entry +; X86-NEXT: xsusldtrk +; X86-NEXT: xresldtrk +; X86-NEXT: retl +; +; X32-LABEL: test_tsxldtrk: +; X32: # %bb.0: # %entry +; X32-NEXT: xsusldtrk +; X32-NEXT: xresldtrk +; X32-NEXT: retq +entry: + call void @llvm.x86.xsusldtrk() + call void @llvm.x86.xresldtrk() + ret void +} + +declare void @llvm.x86.xsusldtrk() +declare void @llvm.x86.xresldtrk() + diff --git a/llvm/test/MC/Disassembler/X86/x86-16.txt b/llvm/test/MC/Disassembler/X86/x86-16.txt index 95948e33ac6836..824daef691cd5c 100644 --- a/llvm/test/MC/Disassembler/X86/x86-16.txt +++ b/llvm/test/MC/Disassembler/X86/x86-16.txt @@ -839,3 +839,9 @@ # CHECK: serialize 0x0f 0x01 0xe8 + +# CHECK: xsusldtrk +0xf2 0x0f 0x01 0xe8 + +# CHECK: xresldtrk +0xf2 0x0f 0x01 0xe9 diff --git a/llvm/test/MC/Disassembler/X86/x86-32.txt b/llvm/test/MC/Disassembler/X86/x86-32.txt index 9e04cc27d879e1..5fba2a8be65b01 100644 --- a/llvm/test/MC/Disassembler/X86/x86-32.txt +++ b/llvm/test/MC/Disassembler/X86/x86-32.txt @@ -946,3 +946,9 @@ # CHECK: serialize 0x0f 0x01 0xe8 + +# CHECK: xsusldtrk +0xf2 0x0f 0x01 0xe8 + +# CHECK: xresldtrk +0xf2 0x0f 0x01 0xe9 diff --git a/llvm/test/MC/Disassembler/X86/x86-64.txt b/llvm/test/MC/Disassembler/X86/x86-64.txt index 8ef1363e4c4830..22374841b0acba 100644 --- a/llvm/test/MC/Disassembler/X86/x86-64.txt +++ b/llvm/test/MC/Disassembler/X86/x86-64.txt @@ -694,3 +694,9 @@ # CHECK: serialize 0x0f 0x01 0xe8 + +# CHECK: xsusldtrk +0xf2 0x0f 0x01 0xe8 + +# CHECK: xresldtrk +0xf2 0x0f 0x01 0xe9 diff --git a/llvm/test/MC/X86/x86-16.s b/llvm/test/MC/X86/x86-16.s index 531a5302886c84..955f1e206e384b 100644 --- a/llvm/test/MC/X86/x86-16.s +++ b/llvm/test/MC/X86/x86-16.s @@ -1033,3 +1033,11 @@ enqcmds (%edi), %edi // CHECK: serialize // CHECK: encoding: [0x0f,0x01,0xe8] serialize + +// CHECK: xsusldtrk +// CHECK: encoding: [0xf2,0x0f,0x01,0xe8] +xsusldtrk + +// CHECK: xresldtrk +// CHECK: encoding: [0xf2,0x0f,0x01,0xe9] +xresldtrk diff --git a/llvm/test/MC/X86/x86-32-coverage.s b/llvm/test/MC/X86/x86-32-coverage.s index 0e6d0afe63b1fd..4e199c7af188fe 100644 --- a/llvm/test/MC/X86/x86-32-coverage.s +++ b/llvm/test/MC/X86/x86-32-coverage.s @@ -10880,3 +10880,11 @@ enqcmds 8128(%bx,%di), %ax // CHECK: serialize // CHECK: encoding: [0x0f,0x01,0xe8] serialize + +// CHECK: xsusldtrk +// CHECK: encoding: [0xf2,0x0f,0x01,0xe8] +xsusldtrk + +// CHECK: xresldtrk +// CHECK: encoding: [0xf2,0x0f,0x01,0xe9] +xresldtrk diff --git a/llvm/test/MC/X86/x86-64.s b/llvm/test/MC/X86/x86-64.s index 8339e675be5b0c..a1c7e431cef7e3 100644 --- a/llvm/test/MC/X86/x86-64.s +++ b/llvm/test/MC/X86/x86-64.s @@ -1881,3 +1881,11 @@ enqcmds 485498096, %rax // CHECK: serialize // CHECK: encoding: [0x0f,0x01,0xe8] serialize + +// CHECK: xsusldtrk +// CHECK: encoding: [0xf2,0x0f,0x01,0xe8] +xsusldtrk + +// CHECK: xresldtrk +// CHECK: encoding: [0xf2,0x0f,0x01,0xe9] +xresldtrk