diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -3261,6 +3261,8 @@ .. option:: -mgfni, -mno-gfni +.. option:: -mhreset, -mno-hreset + .. option:: -minvpcid, -mno-invpcid .. option:: -mkl, -mno-kl 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 @@ -3260,6 +3260,8 @@ def mno_invpcid : Flag<["-"], "mno-invpcid">, Group; def mgfni : Flag<["-"], "mgfni">, Group; def mno_gfni : Flag<["-"], "mno-gfni">, Group; +def mhreset : Flag<["-"], "mhreset">, Group; +def mno_hreset : Flag<["-"], "mno-hreset">, Group; def mkl : Flag<["-"], "mkl">, Group; def mno_kl : Flag<["-"], "mno-kl">, Group; def mwidekl : Flag<["-"], "mwidekl">, 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 @@ -129,6 +129,7 @@ bool HasENQCMD = false; bool HasKL = false; // For key locker bool HasWIDEKL = false; // For wide key locker + bool HasHRESET = false; bool HasAMXTILE = false; bool HasAMXINT8 = false; bool HasAMXBF16 = false; 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 @@ -298,6 +298,8 @@ HasINVPCID = true; } else if (Feature == "+enqcmd") { HasENQCMD = true; + } else if (Feature == "+hreset") { + HasHRESET = true; } else if (Feature == "+amx-bf16") { HasAMXBF16 = true; } else if (Feature == "+amx-int8") { @@ -712,6 +714,8 @@ Builder.defineMacro("__INVPCID__"); if (HasENQCMD) Builder.defineMacro("__ENQCMD__"); + if (HasHRESET) + Builder.defineMacro("__HRESET__"); if (HasAMXTILE) Builder.defineMacro("__AMXTILE__"); if (HasAMXINT8) @@ -848,6 +852,7 @@ .Case("fsgsbase", true) .Case("fxsr", true) .Case("gfni", true) + .Case("hreset", true) .Case("invpcid", true) .Case("kl", true) .Case("widekl", true) @@ -936,6 +941,7 @@ .Case("fsgsbase", HasFSGSBASE) .Case("fxsr", HasFXSR) .Case("gfni", HasGFNI) + .Case("hreset", HasHRESET) .Case("invpcid", HasINVPCID) .Case("kl", HasKL) .Case("widekl", HasWIDEKL) 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 @@ -65,6 +65,7 @@ fmaintrin.h fxsrintrin.h gfniintrin.h + hresetintrin.h htmintrin.h htmxlintrin.h ia32intrin.h @@ -124,6 +125,7 @@ wmmintrin.h __wmmintrin_aes.h __wmmintrin_pclmul.h + x86gprintrin.h x86intrin.h xmmintrin.h xopintrin.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 @@ -196,6 +196,7 @@ /* Features in %eax for leaf 7 sub-leaf 1 */ #define bit_AVX512BF16 0x00000020 +#define bit_HRESET 0x00400000 /* Features in %eax for leaf 13 sub-leaf 1 */ #define bit_XSAVEOPT 0x00000001 diff --git a/clang/lib/Headers/hresetintrin.h b/clang/lib/Headers/hresetintrin.h new file mode 100644 --- /dev/null +++ b/clang/lib/Headers/hresetintrin.h @@ -0,0 +1,49 @@ +/*===---------------- hresetintrin.h - HRESET 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 __X86GPRINTRIN_H +#error "Never use directly; include instead." +#endif + +#ifndef __HRESETINTRIN_H +#define __HRESETINTRIN_H + +#if __has_extension(gnu_asm) + +/* Define the default attributes for the functions in this file. */ +#define __DEFAULT_FN_ATTRS \ + __attribute__((__always_inline__, __nodebug__, __target__("hreset"))) + +/// Provides a hint to the processor to selectively reset the prediction +/// history of the current logical processor specified by a 32-bit integer +/// value \a __eax. +/// +/// This intrinsic corresponds to the HRESET instruction. +/// +/// \operation +/// IF __eax == 0 +/// // nop +/// ELSE +/// FOR i := 0 to 31 +/// IF __eax[i] +/// ResetPredictionFeature(i) +/// FI +/// ENDFOR +/// FI +/// \endoperation +static __inline void __DEFAULT_FN_ATTRS +_hreset(int __eax) +{ + __asm__ ("hreset $0" :: "a"(__eax)); +} + +#undef __DEFAULT_FN_ATTRS + +#endif /* __has_extension(gnu_asm) */ + +#endif /* __HRESETINTRIN_H */ 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 @@ -10,6 +10,8 @@ #ifndef __IMMINTRIN_H #define __IMMINTRIN_H +#include + #if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ defined(__MMX__) #include diff --git a/clang/lib/Headers/x86gprintrin.h b/clang/lib/Headers/x86gprintrin.h new file mode 100644 --- /dev/null +++ b/clang/lib/Headers/x86gprintrin.h @@ -0,0 +1,18 @@ +/*===--------------- x86gprintrin.h - X86 GPR 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 __X86GPRINTRIN_H +#define __X86GPRINTRIN_H + +#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ + defined(__HRESET__) +#include +#endif + +#endif /* __X86GPRINTRIN_H */ diff --git a/clang/test/CodeGen/x86-hreset-intrin.c b/clang/test/CodeGen/x86-hreset-intrin.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/x86-hreset-intrin.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -ffreestanding -triple x86_64-unknown-unknown -target-feature +hreset -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -ffreestanding -triple i386-unknown-unknown -target-feature +hreset -emit-llvm -o - | FileCheck %s + +#include + +void test_hreset(int a) +{ +// CHECK-LABEL: test_hreset +// CHECK: call void asm sideeffect "hreset $$0", "{ax},~{dirflag},~{fpsr},~{flags}"(i32 %{{[0-9]}}) + _hreset(a); +} 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 @@ -278,3 +278,8 @@ // RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-amx-int8 %s -### -o %t.o 2>&1 | FileCheck --check-prefix=NO-AMX-INT8 %s // AMX-INT8: "-target-feature" "+amx-int8" // NO-AMX-INT8: "-target-feature" "-amx-int8" + +// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mhreset %s -### -o %t.o 2>&1 | FileCheck -check-prefix=HRESET %s +// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-hreset %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-HRESET %s +// HRESET: "-target-feature" "+hreset" +// NO-HRESET: "-target-feature" "-hreset" 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 @@ -528,3 +528,11 @@ // 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 + +// RUN: %clang -target i386-unknown-unknown -march=atom -mhreset -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=HRESET %s + +// HRESET: #define __HRESET__ 1 + +// RUN: %clang -target i386-unknown-unknown -march=atom -mno-hreset -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=NOHRESET %s + +// NOHRESET-NOT: #define __HRESET__ 1 diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -114,6 +114,7 @@ the "target-cpu" attribute or TargetMachine CPU which will be used to select Instruction Set. If the attribute is not present, the tune CPU will follow the target CPU. +* Support for ISA HRESET has been added. Changes to the AMDGPU Target ----------------------------- diff --git a/llvm/include/llvm/Support/X86TargetParser.def b/llvm/include/llvm/Support/X86TargetParser.def --- a/llvm/include/llvm/Support/X86TargetParser.def +++ b/llvm/include/llvm/Support/X86TargetParser.def @@ -187,6 +187,7 @@ X86_FEATURE (XSAVEC, "xsavec") X86_FEATURE (XSAVEOPT, "xsaveopt") X86_FEATURE (XSAVES, "xsaves") +X86_FEATURE (HRESET, "hreset") // These features aren't really CPU features, but the frontend can set them. X86_FEATURE (RETPOLINE_EXTERNAL_THUNK, "retpoline-external-thunk") X86_FEATURE (RETPOLINE_INDIRECT_BRANCHES, "retpoline-indirect-branches") 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 @@ -1496,6 +1496,7 @@ bool HasLeaf7Subleaf1 = MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX); Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save; + Features["hreset"] = HasLeaf7Subleaf1 && ((EAX >> 22) & 1); bool HasLeafD = MaxLevel >= 0xd && !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX); diff --git a/llvm/lib/Support/X86TargetParser.cpp b/llvm/lib/Support/X86TargetParser.cpp --- a/llvm/lib/Support/X86TargetParser.cpp +++ b/llvm/lib/Support/X86TargetParser.cpp @@ -558,6 +558,7 @@ constexpr FeatureBitset ImpliedFeaturesAMX_TILE = {}; constexpr FeatureBitset ImpliedFeaturesAMX_BF16 = FeatureAMX_TILE; constexpr FeatureBitset ImpliedFeaturesAMX_INT8 = FeatureAMX_TILE; +constexpr FeatureBitset ImpliedFeaturesHRESET = {}; // Key Locker Features constexpr FeatureBitset ImpliedFeaturesKL = FeatureSSE2; 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 @@ -285,6 +285,8 @@ def FeatureWIDEKL : SubtargetFeature<"widekl", "HasWIDEKL", "true", "Support Key Locker wide Instructions", [FeatureKL]>; +def FeatureHRESET : SubtargetFeature<"hreset", "HasHRESET", "true", + "Has hreset instruction">; def FeatureSERIALIZE : SubtargetFeature<"serialize", "HasSERIALIZE", "true", "Has serialize instruction">; def FeatureTSXLDTRK : SubtargetFeature<"tsxldtrk", "HasTSXLDTRK", "true", diff --git a/llvm/lib/Target/X86/X86InstrFormats.td b/llvm/lib/Target/X86/X86InstrFormats.td --- a/llvm/lib/Target/X86/X86InstrFormats.td +++ b/llvm/lib/Target/X86/X86InstrFormats.td @@ -216,6 +216,7 @@ class TAPS : TA { Prefix OpPrefix = PS; } class TAPD : TA { Prefix OpPrefix = PD; } class TAXD : TA { Prefix OpPrefix = XD; } +class TAXS : TA { Prefix OpPrefix = XS; } class VEX { Encoding OpEnc = EncVEX; } class VEX_W { bit HasVEX_W = 1; } class VEX_WIG { bit IgnoresVEX_W = 1; } 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 @@ -972,6 +972,7 @@ def HasENQCMD : Predicate<"Subtarget->hasENQCMD()">; def HasKL : Predicate<"Subtarget->hasKL()">; def HasWIDEKL : Predicate<"Subtarget->hasWIDEKL()">; +def HasHRESET : Predicate<"Subtarget->hasHRESET()">; def HasSERIALIZE : Predicate<"Subtarget->hasSERIALIZE()">; def HasTSXLDTRK : Predicate<"Subtarget->hasTSXLDTRK()">; def HasAMXTILE : Predicate<"Subtarget->hasAMXTILE()">; @@ -2913,6 +2914,13 @@ def : InstAlias<"clzero\t{%eax|eax}", (CLZERO32r)>, Requires<[Not64BitMode]>; def : InstAlias<"clzero\t{%rax|rax}", (CLZERO64r)>, Requires<[In64BitMode]>; +//===----------------------------------------------------------------------===// +// HRESET Instruction +// +let Uses = [EAX], SchedRW = [WriteSystem] in + def HRESET : Ii8<0xF0, MRM_C0, (outs), (ins i32u8imm:$imm), "hreset\t$imm", []>, + Requires<[HasHRESET]>, TAXS; + //===----------------------------------------------------------------------===// // SERIALIZE Instruction // 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 @@ -401,6 +401,9 @@ /// Processor support key locker wide instructions bool HasWIDEKL = false; + /// Processor supports HRESET instruction + bool HasHRESET = false; + /// Processor supports SERIALIZE instruction bool HasSERIALIZE = false; @@ -736,6 +739,7 @@ bool hasENQCMD() const { return HasENQCMD; } bool hasKL() const { return HasKL; } bool hasWIDEKL() const { return HasWIDEKL; } + bool hasHRESET() const { return HasHRESET; } bool hasSERIALIZE() const { return HasSERIALIZE; } bool hasTSXLDTRK() const { return HasTSXLDTRK; } bool useRetpolineIndirectCalls() const { return UseRetpolineIndirectCalls; } 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 @@ -1000,3 +1000,6 @@ #CHECK: tdcall 0x66 0x0f 0x01 0xcc + +# CHECK: hreset $1 +0xf3 0x0f 0x3a 0xf0 0xc0 0x01 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 @@ -712,3 +712,6 @@ #CHECK: tdcall 0x66 0x0f 0x01 0xcc + +# CHECK: hreset $1 +0xf3 0x0f 0x3a 0xf0 0xc0 0x01 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 @@ -10891,4 +10891,8 @@ // CHECK: tdcall // CHECK: encoding: [0x66,0x0f,0x01,0xcc] -tdcall \ No newline at end of file +tdcall + +// CHECK: hreset +// CHECK: encoding: [0xf3,0x0f,0x3a,0xf0,0xc0,0x01] +hreset $1 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 @@ -2014,3 +2014,7 @@ // CHECK: tdcall // CHECK: encoding: [0x66,0x0f,0x01,0xcc] tdcall + +// CHECK: hreset +// CHECK: encoding: [0xf3,0x0f,0x3a,0xf0,0xc0,0x01] +hreset $1