From 08e4fe6c61967d5c6c16ef7a4cc63d51c4992b55 Mon Sep 17 00:00:00 2001 From: Paul Robinson Date: Thu, 30 Jun 2022 13:23:41 -0700 Subject: [PATCH] [X86] Add RDPRU instruction Add support for the RDPRU instruction on Zen2 processors. User-facing features: - Clang option -m[no-]rdpru to enable/disable the feature - Support is implicit for znver2/znver3 processors - Preprocessor symbol __RDPRU__ to indicate support - Header rdpruintrin.h to define intrinsics - "rdpru" mnemonic supported for assembler code Internal features: - Clang builtin __builtin_ia32_rdpru - IR intrinsic @llvm.x86.rdpru Differential Revision: https://reviews.llvm.org/D128934 --- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/Basic/BuiltinsX86.def | 1 + clang/include/clang/Driver/Options.td | 2 + clang/lib/Basic/Targets/X86.cpp | 6 ++ clang/lib/Basic/Targets/X86.h | 1 + clang/lib/Headers/CMakeLists.txt | 1 + clang/lib/Headers/rdpruintrin.h | 57 +++++++++++++ clang/lib/Headers/x86intrin.h | 4 + clang/test/CodeGen/rdpru-builtins.c | 37 ++++++++ clang/test/Driver/x86-target-features.c | 5 ++ clang/test/Preprocessor/x86_target_features.c | 8 ++ llvm/docs/ReleaseNotes.rst | 1 + llvm/include/llvm/IR/IntrinsicsX86.td | 6 ++ llvm/include/llvm/Support/X86TargetParser.def | 1 + llvm/lib/Support/X86TargetParser.cpp | 6 +- llvm/lib/Target/X86/X86.td | 3 + llvm/lib/Target/X86/X86ISelLowering.cpp | 7 ++ llvm/lib/Target/X86/X86InstrInfo.td | 1 + llvm/lib/Target/X86/X86InstrSystem.td | 9 ++ llvm/lib/Target/X86/X86IntrinsicsInfo.h | 3 +- llvm/test/CodeGen/X86/rdpru.ll | 85 +++++++++++++++++++ llvm/test/MC/Disassembler/X86/x86-32.txt | 3 + llvm/test/MC/Disassembler/X86/x86-64.txt | 3 + llvm/test/MC/X86/RDPRU.s | 17 ++++ 24 files changed, 267 insertions(+), 3 deletions(-) create mode 100644 clang/lib/Headers/rdpruintrin.h create mode 100644 clang/test/CodeGen/rdpru-builtins.c create mode 100644 llvm/test/CodeGen/X86/rdpru.ll create mode 100644 llvm/test/MC/X86/RDPRU.s diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 98153fd6e68d..0f542e08b841 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -527,6 +527,9 @@ X86 Support in Clang - Support for the ``_Float16`` type has been added for all targets with SSE2. When AVX512-FP16 is not available, arithmetic on ``_Float16`` is emulated using ``float``. +- Added the ``-m[no-]rdpru`` flag to enable/disable the RDPRU instruction + provided by AMD Zen2 and later processors. Defined intrinsics for using + this instruction (see rdpruintrin.h). DWARF Support in Clang ---------------------- diff --git a/clang/include/clang/Basic/BuiltinsX86.def b/clang/include/clang/Basic/BuiltinsX86.def index 3e5c376f9bc1..6bf35c340c2d 100644 --- a/clang/include/clang/Basic/BuiltinsX86.def +++ b/clang/include/clang/Basic/BuiltinsX86.def @@ -825,6 +825,7 @@ BUILTIN(__rdtsc, "UOi", "") BUILTIN(__builtin_ia32_rdtscp, "UOiUi*", "") TARGET_BUILTIN(__builtin_ia32_rdpid, "Ui", "n", "rdpid") +TARGET_BUILTIN(__builtin_ia32_rdpru, "ULLii", "n", "rdpru") // PKU TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "n", "pku") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index f4fe08aa1a5b..8ae9145a271a 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4570,6 +4570,8 @@ def mptwrite : Flag<["-"], "mptwrite">, Group; def mno_ptwrite : Flag<["-"], "mno-ptwrite">, Group; def mrdpid : Flag<["-"], "mrdpid">, Group; def mno_rdpid : Flag<["-"], "mno-rdpid">, Group; +def mrdpru : Flag<["-"], "mrdpru">, Group; +def mno_rdpru : Flag<["-"], "mno-rdpru">, Group; def mrdrnd : Flag<["-"], "mrdrnd">, Group; def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group; def mrtm : Flag<["-"], "mrtm">, Group; diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 06988830eaed..69afdf8a3584 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -297,6 +297,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector &Features, HasCLDEMOTE = true; } else if (Feature == "+rdpid") { HasRDPID = true; + } else if (Feature == "+rdpru") { + HasRDPRU = true; } else if (Feature == "+kl") { HasKL = true; } else if (Feature == "+widekl") { @@ -743,6 +745,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__WIDEKL__"); if (HasRDPID) Builder.defineMacro("__RDPID__"); + if (HasRDPRU) + Builder.defineMacro("__RDPRU__"); if (HasCLDEMOTE) Builder.defineMacro("__CLDEMOTE__"); if (HasWAITPKG) @@ -926,6 +930,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const { .Case("prfchw", true) .Case("ptwrite", true) .Case("rdpid", true) + .Case("rdpru", true) .Case("rdrnd", true) .Case("rdseed", true) .Case("rtm", true) @@ -1021,6 +1026,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("prfchw", HasPRFCHW) .Case("ptwrite", HasPTWRITE) .Case("rdpid", HasRDPID) + .Case("rdpru", HasRDPRU) .Case("rdrnd", HasRDRND) .Case("rdseed", HasRDSEED) .Case("retpoline-external-thunk", HasRetpolineExternalThunk) diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 78e444f4e4eb..00662517ae37 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 HasMOVBE = false; bool HasPREFETCHWT1 = false; bool HasRDPID = false; + bool HasRDPRU = false; bool HasRetpolineExternalThunk = false; bool HasLAHFSAHF = false; bool HasWBNOINVD = false; diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 5a0268da14a5..6e2060991b92 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -170,6 +170,7 @@ set(x86_files popcntintrin.h prfchwintrin.h ptwriteintrin.h + rdpruintrin.h rdseedintrin.h rtmintrin.h serializeintrin.h diff --git a/clang/lib/Headers/rdpruintrin.h b/clang/lib/Headers/rdpruintrin.h new file mode 100644 index 000000000000..89732bb8b3cf --- /dev/null +++ b/clang/lib/Headers/rdpruintrin.h @@ -0,0 +1,57 @@ +/*===---- rdpruintrin.h - RDPRU 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 + * + *===-----------------------------------------------------------------------=== + */ + +#if !defined __X86INTRIN_H +#error "Never use directly; include instead." +#endif + +#ifndef __RDPRUINTRIN_H +#define __RDPRUINTRIN_H + +/* Define the default attributes for the functions in this file. */ +#define __DEFAULT_FN_ATTRS \ + __attribute__((__always_inline__, __nodebug__, __target__("rdpru"))) + + +/// Reads the content of a processor register. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the RDPRU instruction. +/// +/// \param reg_id +/// A processor register identifier. +static __inline__ unsigned long long __DEFAULT_FN_ATTRS +__rdpru (int reg_id) +{ + return __builtin_ia32_rdpru(reg_id); +} + +#define __RDPRU_MPERF 0 +#define __RDPRU_APERF 1 + +/// Reads the content of processor register MPERF. +/// +/// \headerfile +/// +/// This intrinsic generates instruction RDPRU to read the value of +/// register MPERF. +#define __mperf() __builtin_ia32_rdpru(__RDPRU_MPERF) + +/// Reads the content of processor register APERF. +/// +/// \headerfile +/// +/// This intrinsic generates instruction RDPRU to read the value of +/// register APERF. +#define __aperf() __builtin_ia32_rdpru(__RDPRU_APERF) + +#undef __DEFAULT_FN_ATTRS + +#endif /* __RDPRUINTRIN_H */ diff --git a/clang/lib/Headers/x86intrin.h b/clang/lib/Headers/x86intrin.h index 768d0e56ab05..450fd008dab9 100644 --- a/clang/lib/Headers/x86intrin.h +++ b/clang/lib/Headers/x86intrin.h @@ -59,5 +59,9 @@ #include #endif +#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ + defined(__RDPRU__) +#include +#endif #endif /* __X86INTRIN_H */ diff --git a/clang/test/CodeGen/rdpru-builtins.c b/clang/test/CodeGen/rdpru-builtins.c new file mode 100644 index 000000000000..03bf0af8336b --- /dev/null +++ b/clang/test/CodeGen/rdpru-builtins.c @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -ffreestanding %s -triple=i686-- -target-feature +rdpru -emit-llvm -o - -Wall -Werror | FileCheck %s +// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-- -target-feature +rdpru -emit-llvm -o - -Wall -Werror | FileCheck %s +// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-- -target-cpu znver2 -emit-llvm -o - -Wall -Werror | FileCheck %s + +#include + +// NOTE: This should correspond to the tests in llvm/test/CodeGen/X86/rdpru.ll + +unsigned long long test_rdpru(int regid) { + // CHECK-LABEL: test_rdpru + // CHECK: [[RESULT:%.*]] = call i64 @llvm.x86.rdpru(i32 %{{.*}}) + // CHECK-NEXT: ret i64 [[RESULT]] + return __rdpru(regid); +} + +unsigned long long test_mperf() { + // CHECK-LABEL: test_mperf + // CHECK: [[RESULT:%.*]] = call i64 @llvm.x86.rdpru(i32 0) + // CHECK-NEXT: ret i64 [[RESULT]] + return __mperf(); +} + +unsigned long long test_aperf() { + // CHECK-LABEL: test_aperf + // CHECK: [[RESULT:%.*]] = call i64 @llvm.x86.rdpru(i32 1) + // CHECK-NEXT: ret i64 [[RESULT]] + return __aperf(); +} + +void test_direct_calls_to_builtin_rdpru(int regid) { + // CHECK: call i64 @llvm.x86.rdpru(i32 0) + // CHECK: call i64 @llvm.x86.rdpru(i32 1) + // CHECK: call i64 @llvm.x86.rdpru(i32 %{{.*}}) + (void) __builtin_ia32_rdpru(0); + (void) __builtin_ia32_rdpru(1); + (void) __builtin_ia32_rdpru(regid); +} diff --git a/clang/test/Driver/x86-target-features.c b/clang/test/Driver/x86-target-features.c index 453656a1b98f..d30215d45334 100644 --- a/clang/test/Driver/x86-target-features.c +++ b/clang/test/Driver/x86-target-features.c @@ -136,6 +136,11 @@ // RDPID: "-target-feature" "+rdpid" // NO-RDPID: "-target-feature" "-rdpid" +// RUN: %clang --target=i386 -march=i386 -mrdpru %s -### 2>&1 | FileCheck -check-prefix=RDPRU %s +// RUN: %clang --target=i386 -march=i386 -mno-rdpru %s -### 2>&1 | FileCheck -check-prefix=NO-RDPRU %s +// RDPRU: "-target-feature" "+rdpru" +// NO-RDPRU: "-target-feature" "-rdpru" + // RUN: %clang -target i386-linux-gnu -mretpoline %s -### 2>&1 | FileCheck -check-prefix=RETPOLINE %s // RUN: %clang -target i386-linux-gnu -mno-retpoline %s -### 2>&1 | FileCheck -check-prefix=NO-RETPOLINE %s // RETPOLINE: "-target-feature" "+retpoline-indirect-calls" "-target-feature" "+retpoline-indirect-branches" diff --git a/clang/test/Preprocessor/x86_target_features.c b/clang/test/Preprocessor/x86_target_features.c index c5be4be6f5c6..c9258bd5fd1d 100644 --- a/clang/test/Preprocessor/x86_target_features.c +++ b/clang/test/Preprocessor/x86_target_features.c @@ -588,3 +588,11 @@ // RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-crc32 -x c -E -dM -o - %s | FileCheck -check-prefix=NOCRC32 %s // NOCRC32-NOT: #define __CRC32__ 1 + +// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mrdpru -x c -E -dM -o - %s | FileCheck -check-prefix=RDPRU %s + +// RDPRU: #define __RDPRU__ 1 + +// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-rdpru -x c -E -dM -o - %s | FileCheck -check-prefix=NORDPRU %s + +// NORDPRU-NOT: #define __RDPRU__ 1 diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index b164d2cf7cc7..b61121427964 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -163,6 +163,7 @@ Changes to the X86 Backend -------------------------- * Support ``half`` type on SSE2 and above targets. +* Support ``rdpru`` instruction on Zen2 and above targets. Changes to the OCaml bindings ----------------------------- diff --git a/llvm/include/llvm/IR/IntrinsicsX86.td b/llvm/include/llvm/IR/IntrinsicsX86.td index 0930abcc0993..c274e3504250 100644 --- a/llvm/include/llvm/IR/IntrinsicsX86.td +++ b/llvm/include/llvm/IR/IntrinsicsX86.td @@ -72,6 +72,12 @@ let TargetPrefix = "x86" in { [ImmArg>]>; } +// Read Processor Register. +let TargetPrefix = "x86" in { + def int_x86_rdpru : ClangBuiltin<"__builtin_ia32_rdpru">, + Intrinsic<[llvm_i64_ty], [llvm_i32_ty], []>; +} + //===----------------------------------------------------------------------===// // CET SS let TargetPrefix = "x86" in { diff --git a/llvm/include/llvm/Support/X86TargetParser.def b/llvm/include/llvm/Support/X86TargetParser.def index 58fa3b3842e7..1a928e5a9acc 100644 --- a/llvm/include/llvm/Support/X86TargetParser.def +++ b/llvm/include/llvm/Support/X86TargetParser.def @@ -178,6 +178,7 @@ X86_FEATURE (PREFETCHWT1, "prefetchwt1") X86_FEATURE (PRFCHW, "prfchw") X86_FEATURE (PTWRITE, "ptwrite") X86_FEATURE (RDPID, "rdpid") +X86_FEATURE (RDPRU, "rdpru") X86_FEATURE (RDRND, "rdrnd") X86_FEATURE (RDSEED, "rdseed") X86_FEATURE (RTM, "rtm") diff --git a/llvm/lib/Support/X86TargetParser.cpp b/llvm/lib/Support/X86TargetParser.cpp index 10f9692d217e..2567f3ed8034 100644 --- a/llvm/lib/Support/X86TargetParser.cpp +++ b/llvm/lib/Support/X86TargetParser.cpp @@ -285,8 +285,9 @@ constexpr FeatureBitset FeaturesZNVER1 = FeatureSSE | FeatureSSE2 | FeatureSSE3 | FeatureSSSE3 | FeatureSSE4_1 | FeatureSSE4_2 | FeatureSSE4_A | FeatureXSAVE | FeatureXSAVEC | FeatureXSAVEOPT | FeatureXSAVES; -constexpr FeatureBitset FeaturesZNVER2 = - FeaturesZNVER1 | FeatureCLWB | FeatureRDPID | FeatureWBNOINVD; +constexpr FeatureBitset FeaturesZNVER2 = FeaturesZNVER1 | FeatureCLWB | + FeatureRDPID | FeatureRDPRU | + FeatureWBNOINVD; static constexpr FeatureBitset FeaturesZNVER3 = FeaturesZNVER2 | FeatureINVPCID | FeaturePKU | FeatureVAES | FeatureVPCLMULQDQ; @@ -490,6 +491,7 @@ constexpr FeatureBitset ImpliedFeaturesPREFETCHWT1 = {}; constexpr FeatureBitset ImpliedFeaturesPRFCHW = {}; constexpr FeatureBitset ImpliedFeaturesPTWRITE = {}; constexpr FeatureBitset ImpliedFeaturesRDPID = {}; +constexpr FeatureBitset ImpliedFeaturesRDPRU = {}; constexpr FeatureBitset ImpliedFeaturesRDRND = {}; constexpr FeatureBitset ImpliedFeaturesRDSEED = {}; constexpr FeatureBitset ImpliedFeaturesRTM = {}; diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td index a5c6b40c493c..a859176220c7 100644 --- a/llvm/lib/Target/X86/X86.td +++ b/llvm/lib/Target/X86/X86.td @@ -266,6 +266,8 @@ def FeatureWBNOINVD : SubtargetFeature<"wbnoinvd", "HasWBNOINVD", "true", "Write Back No Invalidate">; def FeatureRDPID : SubtargetFeature<"rdpid", "HasRDPID", "true", "Support RDPID instructions">; +def FeatureRDPRU : SubtargetFeature<"rdpru", "HasRDPRU", "true", + "Support RDPRU instructions">; def FeatureWAITPKG : SubtargetFeature<"waitpkg", "HasWAITPKG", "true", "Wait and pause enhancements">; def FeatureENQCMD : SubtargetFeature<"enqcmd", "HasENQCMD", "true", @@ -1238,6 +1240,7 @@ def ProcessorFeatures { TuningInsertVZEROUPPER]; list ZN2AdditionalFeatures = [FeatureCLWB, FeatureRDPID, + FeatureRDPRU, FeatureWBNOINVD]; list ZN2Tuning = ZNTuning; list ZN2Features = diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 379b4ed931a1..d54d6e4d8cac 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -27887,11 +27887,14 @@ static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget &Subtarget, } // Read Performance Monitoring Counters. case RDPMC: + // Read Processor Register. + case RDPRU: // GetExtended Control Register. case XGETBV: { SmallVector Results; // RDPMC uses ECX to select the index of the performance counter to read. + // RDPRU uses ECX to select the processor register to read. // XGETBV uses ECX to select the index of the XCR register to return. // The result is stored into registers EDX:EAX. expandIntrinsicWChainHelper(Op.getNode(), dl, DAG, IntrData->Opc0, X86::ECX, @@ -32894,6 +32897,10 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N, expandIntrinsicWChainHelper(N, dl, DAG, X86::RDPMC, X86::ECX, Subtarget, Results); return; + case Intrinsic::x86_rdpru: + expandIntrinsicWChainHelper(N, dl, DAG, X86::RDPRU, X86::ECX, Subtarget, + Results); + return; case Intrinsic::x86_xgetbv: expandIntrinsicWChainHelper(N, dl, DAG, X86::XGETBV, X86::ECX, Subtarget, Results); diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 7f6ef3479d40..4a9a281d5b99 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -978,6 +978,7 @@ def HasCLFLUSHOPT : Predicate<"Subtarget->hasCLFLUSHOPT()">; def HasCLWB : Predicate<"Subtarget->hasCLWB()">; def HasWBNOINVD : Predicate<"Subtarget->hasWBNOINVD()">; def HasRDPID : Predicate<"Subtarget->hasRDPID()">; +def HasRDPRU : Predicate<"Subtarget->hasRDPRU()">; def HasWAITPKG : Predicate<"Subtarget->hasWAITPKG()">; def HasINVPCID : Predicate<"Subtarget->hasINVPCID()">; def HasCX8 : Predicate<"Subtarget->hasCX8()">; diff --git a/llvm/lib/Target/X86/X86InstrSystem.td b/llvm/lib/Target/X86/X86InstrSystem.td index 3a653a56e534..b1ca87279007 100644 --- a/llvm/lib/Target/X86/X86InstrSystem.td +++ b/llvm/lib/Target/X86/X86InstrSystem.td @@ -734,6 +734,15 @@ def PTWRITE64r : RI<0xAE, MRM4r, (outs), (ins GR64:$dst), Requires<[In64BitMode, HasPTWRITE]>; } // SchedRW +//===----------------------------------------------------------------------===// +// RDPRU - Read Processor Register instruction. + +let SchedRW = [WriteSystem] in { +let Uses = [ECX], Defs = [EAX, EDX] in + def RDPRU : I<0x01, MRM_FD, (outs), (ins), "rdpru", []>, PS, + Requires<[HasRDPRU]>; +} + //===----------------------------------------------------------------------===// // Platform Configuration instruction diff --git a/llvm/lib/Target/X86/X86IntrinsicsInfo.h b/llvm/lib/Target/X86/X86IntrinsicsInfo.h index 3c8be95b43e3..6112c0b7d6c3 100644 --- a/llvm/lib/Target/X86/X86IntrinsicsInfo.h +++ b/llvm/lib/Target/X86/X86IntrinsicsInfo.h @@ -37,7 +37,7 @@ enum IntrinsicType : uint16_t { TRUNCATE_TO_REG, CVTPS2PH_MASK, CVTPD2DQ_MASK, CVTQQ2PS_MASK, TRUNCATE_TO_MEM_VI8, TRUNCATE_TO_MEM_VI16, TRUNCATE_TO_MEM_VI32, FIXUPIMM, FIXUPIMM_MASKZ, GATHER_AVX2, - ROUNDP, ROUNDS + ROUNDP, ROUNDS, RDPRU }; struct IntrinsicData { @@ -309,6 +309,7 @@ static const IntrinsicData IntrinsicsWithChain[] = { X86_INTRINSIC_DATA(avx512_scattersiv8_sf, SCATTER, 0, 0), X86_INTRINSIC_DATA(avx512_scattersiv8_si, SCATTER, 0, 0), X86_INTRINSIC_DATA(rdpmc, RDPMC, X86::RDPMC, 0), + X86_INTRINSIC_DATA(rdpru, RDPRU, X86::RDPRU, 0), X86_INTRINSIC_DATA(rdrand_16, RDRAND, X86ISD::RDRAND, 0), X86_INTRINSIC_DATA(rdrand_32, RDRAND, X86ISD::RDRAND, 0), X86_INTRINSIC_DATA(rdrand_64, RDRAND, X86ISD::RDRAND, 0), diff --git a/llvm/test/CodeGen/X86/rdpru.ll b/llvm/test/CodeGen/X86/rdpru.ll new file mode 100644 index 000000000000..66d4b4c0f6be --- /dev/null +++ b/llvm/test/CodeGen/X86/rdpru.ll @@ -0,0 +1,85 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i686-- -mattr=+rdpru | FileCheck %s --check-prefix=X86 +; RUN: llc < %s -mtriple=i686-- -mattr=+rdpru -fast-isel | FileCheck %s --check-prefix=X86 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+rdpru | FileCheck %s --check-prefix=X64 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+rdpru -fast-isel | FileCheck %s --check-prefix=X64 +; RUN: llc < %s -mtriple=x86_64-- -mcpu=znver2 | FileCheck %s --check-prefix=X64 +; RUN: llc < %s -mtriple=x86_64-- -mcpu=znver3 -fast-isel | FileCheck %s --check-prefix=X64 + +define void @rdpru_asm() { +; X86-LABEL: rdpru_asm: +; X86: # %bb.0: # %entry +; X86-NEXT: #APP +; X86-NEXT: rdpru +; X86-NEXT: #NO_APP +; X86-NEXT: retl +; +; X64-LABEL: rdpru_asm: +; X64: # %bb.0: # %entry +; X64-NEXT: #APP +; X64-NEXT: rdpru +; X64-NEXT: #NO_APP +; X64-NEXT: retq +entry: + call void asm sideeffect "rdpru", "~{dirflag},~{fpsr},~{flags}"() + ret void +} + +define i64 @rdpru_param(i32 %regid) local_unnamed_addr { +; X86-LABEL: rdpru_param: +; X86: # %bb.0: # %entry +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: rdpru +; X86-NEXT: retl +; +; X64-LABEL: rdpru_param: +; X64: # %bb.0: # %entry +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: rdpru +; X64-NEXT: shlq $32, %rdx +; X64-NEXT: orq %rdx, %rax +; X64-NEXT: retq +entry: + %0 = tail call i64 @llvm.x86.rdpru(i32 %regid) + ret i64 %0 +} + +define i64 @rdpru_mperf() local_unnamed_addr { +; X86-LABEL: rdpru_mperf: +; X86: # %bb.0: # %entry +; X86-NEXT: xorl %ecx, %ecx +; X86-NEXT: rdpru +; X86-NEXT: retl +; +; X64-LABEL: rdpru_mperf: +; X64: # %bb.0: # %entry +; X64-NEXT: xorl %ecx, %ecx +; X64-NEXT: rdpru +; X64-NEXT: shlq $32, %rdx +; X64-NEXT: orq %rdx, %rax +; X64-NEXT: retq +entry: + %0 = tail call i64 @llvm.x86.rdpru(i32 0) + ret i64 %0 +} + +define i64 @rdpru_aperf() local_unnamed_addr { +; X86-LABEL: rdpru_aperf: +; X86: # %bb.0: # %entry +; X86-NEXT: movl $1, %ecx +; X86-NEXT: rdpru +; X86-NEXT: retl +; +; X64-LABEL: rdpru_aperf: +; X64: # %bb.0: # %entry +; X64-NEXT: movl $1, %ecx +; X64-NEXT: rdpru +; X64-NEXT: shlq $32, %rdx +; X64-NEXT: orq %rdx, %rax +; X64-NEXT: retq +entry: + %0 = tail call i64 @llvm.x86.rdpru(i32 1) + ret i64 %0 +} + +declare i64 @llvm.x86.rdpru(i32) diff --git a/llvm/test/MC/Disassembler/X86/x86-32.txt b/llvm/test/MC/Disassembler/X86/x86-32.txt index 6c063ead4419..336134b064c6 100644 --- a/llvm/test/MC/Disassembler/X86/x86-32.txt +++ b/llvm/test/MC/Disassembler/X86/x86-32.txt @@ -1015,3 +1015,6 @@ # CHECK: hreset $1 0xf3 0x0f 0x3a 0xf0 0xc0 0x01 + +# CHECK: rdpru +0x0f,0x01,0xfd diff --git a/llvm/test/MC/Disassembler/X86/x86-64.txt b/llvm/test/MC/Disassembler/X86/x86-64.txt index 5e56d4c796e6..80e0942ab64d 100644 --- a/llvm/test/MC/Disassembler/X86/x86-64.txt +++ b/llvm/test/MC/Disassembler/X86/x86-64.txt @@ -758,3 +758,6 @@ # CHECK: senduipi %r13 0xf3,0x41,0x0f,0xc7,0xf5 + +# CHECK: rdpru +0x0f,0x01,0xfd diff --git a/llvm/test/MC/X86/RDPRU.s b/llvm/test/MC/X86/RDPRU.s new file mode 100644 index 000000000000..f3892a1cbb43 --- /dev/null +++ b/llvm/test/MC/X86/RDPRU.s @@ -0,0 +1,17 @@ +/// Encoding and disassembly of rdpru. + +// RUN: llvm-mc -triple i686-- --show-encoding %s |\ +// RUN: FileCheck %s --check-prefixes=CHECK,ENCODING + +// RUN: llvm-mc -triple i686-- -filetype=obj %s |\ +// RUN: llvm-objdump -d - | FileCheck %s + +// RUN: llvm-mc -triple x86_64-- --show-encoding %s |\ +// RUN: FileCheck %s --check-prefixes=CHECK,ENCODING + +// RUN: llvm-mc -triple x86_64-- -filetype=obj %s |\ +// RUN: llvm-objdump -d - | FileCheck %s + +// CHECK: rdpru +// ENCODING: encoding: [0x0f,0x01,0xfd] +rdpru