diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -3175,6 +3175,8 @@ .. 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 --- a/clang/include/clang/Basic/BuiltinsX86.def +++ b/clang/include/clang/Basic/BuiltinsX86.def @@ -1903,6 +1903,10 @@ // 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 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3230,6 +3230,8 @@ 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.h b/clang/lib/Basic/Targets/X86.h --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -125,6 +125,7 @@ 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/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -859,6 +859,8 @@ HasENQCMD = true; } else if (Feature == "+serialize") { HasSERIALIZE = true; + } else if (Feature == "+tsxldtrk") { + HasTSXLDTRK = true; } X86SSEEnum Level = llvm::StringSwitch(Feature) @@ -1251,6 +1253,8 @@ 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 @@ .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 @@ .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/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -104,6 +104,7 @@ 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 --- 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 --- a/clang/lib/Headers/immintrin.h +++ b/clang/lib/Headers/immintrin.h @@ -438,6 +438,10 @@ #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 --- /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 --- /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 --- 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 --- 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 --- a/llvm/include/llvm/IR/IntrinsicsX86.td +++ b/llvm/include/llvm/IR/IntrinsicsX86.td @@ -4938,3 +4938,13 @@ 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 --- a/llvm/lib/Support/Host.cpp +++ b/llvm/lib/Support/Host.cpp @@ -1478,6 +1478,7 @@ 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 --- a/llvm/lib/Target/X86/X86.td +++ b/llvm/lib/Target/X86/X86.td @@ -275,6 +275,8 @@ "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 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -956,6 +956,7 @@ 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 @@ [(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 --- a/llvm/lib/Target/X86/X86Subtarget.h +++ b/llvm/lib/Target/X86/X86Subtarget.h @@ -400,6 +400,9 @@ /// 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 @@ 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 --- /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 --- 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 --- 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 --- 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 --- a/llvm/test/MC/X86/x86-16.s +++ b/llvm/test/MC/X86/x86-16.s @@ -1033,3 +1033,11 @@ // 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 --- a/llvm/test/MC/X86/x86-32-coverage.s +++ b/llvm/test/MC/X86/x86-32-coverage.s @@ -10880,3 +10880,11 @@ // 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 --- a/llvm/test/MC/X86/x86-64.s +++ b/llvm/test/MC/X86/x86-64.s @@ -1881,3 +1881,11 @@ // 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