[clang] 819ac45 - [X86] Add USER_MSR instructions. (#68944)

via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 15 19:12:58 PDT 2023


Author: Freddy Ye
Date: 2023-10-16T10:12:53+08:00
New Revision: 819ac45d1c1b7a2d784b2606c84de46ce714f278

URL: https://github.com/llvm/llvm-project/commit/819ac45d1c1b7a2d784b2606c84de46ce714f278
DIFF: https://github.com/llvm/llvm-project/commit/819ac45d1c1b7a2d784b2606c84de46ce714f278.diff

LOG: [X86] Add USER_MSR instructions. (#68944)

For more details about this instruction, please refer to the latest ISE
document:
https://www.intel.com/content/www/us/en/develop/download/intel-architecture-instruction-set-extensions-programming-reference.html

Added: 
    clang/lib/Headers/usermsrintrin.h
    clang/test/CodeGen/X86/usermsr-builtins-error-32.c
    clang/test/CodeGen/X86/usermsr-builtins.c
    llvm/test/CodeGen/X86/usermsr-intrinsics.ll
    llvm/test/MC/Disassembler/X86/usermsr-64.txt
    llvm/test/MC/X86/usermsr-64-att.s
    llvm/test/MC/X86/usermsr-64-intel.s

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/BuiltinsX86_64.def
    clang/include/clang/Driver/Options.td
    clang/lib/Basic/Targets/X86.cpp
    clang/lib/Basic/Targets/X86.h
    clang/lib/Headers/CMakeLists.txt
    clang/lib/Headers/x86gprintrin.h
    clang/test/Driver/x86-target-features.c
    clang/test/Preprocessor/x86_target_features.c
    llvm/docs/ReleaseNotes.rst
    llvm/include/llvm/IR/IntrinsicsX86.td
    llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
    llvm/include/llvm/TargetParser/X86TargetParser.def
    llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
    llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
    llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
    llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
    llvm/lib/Target/X86/X86.td
    llvm/lib/Target/X86/X86InstrFormats.td
    llvm/lib/Target/X86/X86InstrInfo.td
    llvm/lib/Target/X86/X86InstrSystem.td
    llvm/lib/TargetParser/Host.cpp
    llvm/lib/TargetParser/X86TargetParser.cpp
    llvm/utils/TableGen/X86DisassemblerTables.cpp
    llvm/utils/TableGen/X86DisassemblerTables.h
    llvm/utils/TableGen/X86RecognizableInstr.cpp
    llvm/utils/TableGen/X86RecognizableInstr.h

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6d315e9f84ddfe8..52d5b9a3f66d155 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -551,6 +551,9 @@ X86 Support
 
 - Added option ``-m[no-]evex512`` to disable ZMM and 64-bit mask instructions
   for AVX512 features.
+- Support ISA of ``USER_MSR``.
+  * Support intrinsic of ``_urdmsr``.
+  * Support intrinsic of ``_uwrmsr``.
 
 Arm and AArch64 Support
 ^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/include/clang/Basic/BuiltinsX86_64.def b/clang/include/clang/Basic/BuiltinsX86_64.def
index e5c1fe8b319217e..5e00916d4b25ae3 100644
--- a/clang/include/clang/Basic/BuiltinsX86_64.def
+++ b/clang/include/clang/Basic/BuiltinsX86_64.def
@@ -104,6 +104,9 @@ TARGET_BUILTIN(__builtin_ia32_clui, "v", "n", "uintr")
 TARGET_BUILTIN(__builtin_ia32_stui, "v", "n", "uintr")
 TARGET_BUILTIN(__builtin_ia32_testui, "Uc", "n", "uintr")
 TARGET_BUILTIN(__builtin_ia32_senduipi, "vUWi", "n", "uintr")
+// USERMSR
+TARGET_BUILTIN(__builtin_ia32_urdmsr, "ULLiULLi", "n", "usermsr")
+TARGET_BUILTIN(__builtin_ia32_uwrmsr, "vULLiULLi", "n", "usermsr")
 
 // AMX internal builtin
 TARGET_BUILTIN(__builtin_ia32_tile_loadconfig_internal, "vvC*", "n", "amx-tile")

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 54afd652ad3d0fe..640044622fc09ee 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5904,6 +5904,8 @@ def mtsxldtrk : Flag<["-"], "mtsxldtrk">, Group<m_x86_Features_Group>;
 def mno_tsxldtrk : Flag<["-"], "mno-tsxldtrk">, Group<m_x86_Features_Group>;
 def muintr : Flag<["-"], "muintr">, Group<m_x86_Features_Group>;
 def mno_uintr : Flag<["-"], "mno-uintr">, Group<m_x86_Features_Group>;
+def musermsr : Flag<["-"], "musermsr">, Group<m_x86_Features_Group>;
+def mno_usermsr : Flag<["-"], "mno-usermsr">, Group<m_x86_Features_Group>;
 def mvaes : Flag<["-"], "mvaes">, Group<m_x86_Features_Group>;
 def mno_vaes : Flag<["-"], "mno-vaes">, Group<m_x86_Features_Group>;
 def mvpclmulqdq : Flag<["-"], "mvpclmulqdq">, Group<m_x86_Features_Group>;

diff  --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp
index 022d5753135e160..bea5c52a7b8d7c9 100644
--- a/clang/lib/Basic/Targets/X86.cpp
+++ b/clang/lib/Basic/Targets/X86.cpp
@@ -376,6 +376,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
       HasTSXLDTRK = true;
     } else if (Feature == "+uintr") {
       HasUINTR = true;
+    } else if (Feature == "+usermsr") {
+      HasUSERMSR = true;
     } else if (Feature == "+crc32") {
       HasCRC32 = true;
     } else if (Feature == "+x87") {
@@ -869,6 +871,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
     Builder.defineMacro("__TSXLDTRK__");
   if (HasUINTR)
     Builder.defineMacro("__UINTR__");
+  if (HasUSERMSR)
+    Builder.defineMacro("__USERMSR__");
   if (HasCRC32)
     Builder.defineMacro("__CRC32__");
 
@@ -1053,6 +1057,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
       .Case("tbm", true)
       .Case("tsxldtrk", true)
       .Case("uintr", true)
+      .Case("usermsr", true)
       .Case("vaes", true)
       .Case("vpclmulqdq", true)
       .Case("wbnoinvd", true)
@@ -1162,6 +1167,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
       .Case("tbm", HasTBM)
       .Case("tsxldtrk", HasTSXLDTRK)
       .Case("uintr", HasUINTR)
+      .Case("usermsr", HasUSERMSR)
       .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 4fdc94de1e0cb4d..298db55c67442c9 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -162,6 +162,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
   bool HasAMXCOMPLEX = false;
   bool HasSERIALIZE = false;
   bool HasTSXLDTRK = false;
+  bool HasUSERMSR = false;
   bool HasUINTR = false;
   bool HasCRC32 = false;
   bool HasX87 = false;

diff  --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index 8deea823e396694..3b6fec3da2b16ff 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -224,6 +224,7 @@ set(x86_files
   tmmintrin.h
   tsxldtrkintrin.h
   uintrintrin.h
+  usermsrintrin.h
   vaesintrin.h
   vpclmulqdqintrin.h
   waitpkgintrin.h

diff  --git a/clang/lib/Headers/usermsrintrin.h b/clang/lib/Headers/usermsrintrin.h
new file mode 100644
index 000000000000000..6d1424ad3b2edd7
--- /dev/null
+++ b/clang/lib/Headers/usermsrintrin.h
@@ -0,0 +1,30 @@
+/*===--------------- usermsrintrin.h - USERMSR 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 <usermsrintrin.h> directly; include <x86gprintrin.h> instead."
+#endif // __X86GPRINTRIN_H
+
+#ifndef __USERMSRINTRIN_H
+#define __USERMSRINTRIN_H
+#ifdef __x86_64__
+
+static __inline__ unsigned long long
+    __attribute__((__always_inline__, __nodebug__, __target__("usermsr")))
+    _urdmsr(unsigned long long __A) {
+  return __builtin_ia32_urdmsr(__A);
+}
+
+static __inline__ void
+    __attribute__((__always_inline__, __nodebug__, __target__("usermsr")))
+    _uwrmsr(unsigned long long __A, unsigned long long __B) {
+  return __builtin_ia32_uwrmsr(__A, __B);
+}
+
+#endif // __x86_64__
+#endif // __USERMSRINTRIN_H

diff  --git a/clang/lib/Headers/x86gprintrin.h b/clang/lib/Headers/x86gprintrin.h
index f9a765be432219b..ed141879fbc7442 100644
--- a/clang/lib/Headers/x86gprintrin.h
+++ b/clang/lib/Headers/x86gprintrin.h
@@ -20,6 +20,11 @@
 #include <uintrintrin.h>
 #endif
 
+#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) ||      \
+    defined(__USERMSR__)
+#include <usermsrintrin.h>
+#endif
+
 #if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) ||      \
     defined(__CRC32__)
 #include <crc32intrin.h>

diff  --git a/clang/test/CodeGen/X86/usermsr-builtins-error-32.c b/clang/test/CodeGen/X86/usermsr-builtins-error-32.c
new file mode 100644
index 000000000000000..180b99a4212a157
--- /dev/null
+++ b/clang/test/CodeGen/X86/usermsr-builtins-error-32.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=i386-unknown-unknown -target-feature +usermsr \
+// RUN: -emit-llvm -fsyntax-only -verify
+
+#include <x86gprintrin.h>
+
+unsigned long long test_urdmsr(unsigned long long __A) {
+  return _urdmsr(__A); // expected-error {{call to undeclared function '_urdmsr'}}
+}
+
+void test_uwrmsr(unsigned long long __A, unsigned long long __B) {
+  // CHECK-LABEL: @test_uwrmsr(
+  // CHECK: call void @llvm.x86.uwrmsr(
+  _uwrmsr(__A, __B); // expected-error {{call to undeclared function '_uwrmsr'}}
+}

diff  --git a/clang/test/CodeGen/X86/usermsr-builtins.c b/clang/test/CodeGen/X86/usermsr-builtins.c
new file mode 100644
index 000000000000000..0d58bc98c204c35
--- /dev/null
+++ b/clang/test/CodeGen/X86/usermsr-builtins.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +usermsr \
+// RUN: -emit-llvm -o - -Wall -Werror -pedantic -Wno-gnu-statement-expression | FileCheck %s
+
+#include <x86gprintrin.h>
+
+unsigned long long test_urdmsr(unsigned long long __A) {
+  // CHECK-LABEL: @test_urdmsr(
+  // CHECK: call i64 @llvm.x86.urdmsr(
+  return _urdmsr(__A);
+}
+
+unsigned long long test_urdmsr_const(unsigned long long __A) {
+  // CHECK-LABEL: @test_urdmsr_const(
+  // CHECK: call i64 @llvm.x86.urdmsr(
+  return _urdmsr(123u);
+}
+
+void test_uwrmsr(unsigned long long __A, unsigned long long __B) {
+  // CHECK-LABEL: @test_uwrmsr(
+  // CHECK: call void @llvm.x86.uwrmsr(
+  _uwrmsr(__A, __B);
+}
+
+void test_uwrmsr_const(unsigned long long __A, unsigned long long __B) {
+  // CHECK-LABEL: @test_uwrmsr_const(
+  // CHECK: call void @llvm.x86.uwrmsr(
+  _uwrmsr(123u, __B);
+}
+

diff  --git a/clang/test/Driver/x86-target-features.c b/clang/test/Driver/x86-target-features.c
index a6ecedbb8a58e7b..464dcda504bbdc3 100644
--- a/clang/test/Driver/x86-target-features.c
+++ b/clang/test/Driver/x86-target-features.c
@@ -374,6 +374,11 @@
 // EVEX512: "-target-feature" "+evex512"
 // NO-EVEX512: "-target-feature" "-evex512"
 
+// RUN: %clang --target=i386 -musermsr %s -### -o %t.o 2>&1 | FileCheck -check-prefix=USERMSR %s
+// RUN: %clang --target=i386 -mno-usermsr %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-USERMSR %s
+// USERMSR: "-target-feature" "+usermsr"
+// NO-USERMSR: "-target-feature" "-usermsr"
+
 // RUN: %clang --target=i386 -march=i386 -mcrc32 %s -### 2>&1 | FileCheck -check-prefix=CRC32 %s
 // RUN: %clang --target=i386 -march=i386 -mno-crc32 %s -### 2>&1 | FileCheck -check-prefix=NO-CRC32 %s
 // CRC32: "-target-feature" "+crc32"

diff  --git a/clang/test/Preprocessor/x86_target_features.c b/clang/test/Preprocessor/x86_target_features.c
index 36d4af59d4c66f6..873416d79b1255c 100644
--- a/clang/test/Preprocessor/x86_target_features.c
+++ b/clang/test/Preprocessor/x86_target_features.c
@@ -750,6 +750,12 @@
 // AVXVNNIINT16NOAVX2-NOT: #define __AVX2__ 1
 // AVXVNNIINT16NOAVX2-NOT: #define __AVXVNNIINT16__ 1
 
+// RUN: %clang -target i686-unknown-linux-gnu -march=atom -musermsr -x c -E -dM -o - %s | FileCheck  -check-prefix=USERMSR %s
+// USERMSR: #define __USERMSR__ 1
+
+// RUN: %clang -target i686-unknown-linux-gnu -march=atom -mno-usermsr -x c -E -dM -o - %s | FileCheck  -check-prefix=NO-USERMSR %s
+// NO-USERMSR-NOT: #define __USERMSR__ 1
+
 // RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mcrc32 -x c -E -dM -o - %s | FileCheck -check-prefix=CRC32 %s
 
 // CRC32: #define __CRC32__ 1

diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 467b4b5320ad9f3..94b43800c17bd76 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -133,6 +133,7 @@ Changes to the X86 Backend
   benefits external projects such as Rust which aim to be binary compatible
   with C, but also fixes code generation where LLVM already assumed that the
   type matched and called into libgcc helper functions.
+* Support ISA of ``USER_MSR``.
 
 Changes to the OCaml bindings
 -----------------------------

diff  --git a/llvm/include/llvm/IR/IntrinsicsX86.td b/llvm/include/llvm/IR/IntrinsicsX86.td
index 57cd1dc47bd9fc9..fdc2b0fb7f80f12 100644
--- a/llvm/include/llvm/IR/IntrinsicsX86.td
+++ b/llvm/include/llvm/IR/IntrinsicsX86.td
@@ -5673,8 +5673,16 @@ let TargetPrefix = "x86" in {
               Intrinsic<[], [llvm_i64_ty], []>;
 }
 
+let TargetPrefix = "x86" in {
+def int_x86_urdmsr : ClangBuiltin<"__builtin_ia32_urdmsr">,
+        Intrinsic<[llvm_i64_ty], [llvm_i64_ty],
+                  [IntrInaccessibleMemOnly]>;
+def int_x86_uwrmsr : ClangBuiltin<"__builtin_ia32_uwrmsr">,
+        Intrinsic<[], [llvm_i64_ty, llvm_i64_ty],
+                  [IntrInaccessibleMemOnly]>;
+}
+
 //===----------------------------------------------------------------------===//
-// avx512_fp16: vaddph
 let TargetPrefix = "x86" in {
   def int_x86_avx512fp16_add_ph_512
       : ClangBuiltin<"__builtin_ia32_addph512">,

diff  --git a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
index 169b8e97986e154..6e08fc6a0ccb650 100644
--- a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
+++ b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
@@ -33,6 +33,7 @@ namespace X86Disassembler {
 #define THREEDNOW_MAP_SYM x86Disassembler3DNowOpcodes
 #define MAP5_SYM          x86DisassemblerMap5Opcodes
 #define MAP6_SYM          x86DisassemblerMap6Opcodes
+#define MAP7_SYM          x86DisassemblerMap7Opcodes
 
 #define INSTRUCTIONS_STR  "x86DisassemblerInstrSpecifiers"
 #define CONTEXTS_STR      "x86DisassemblerContexts"
@@ -46,6 +47,7 @@ namespace X86Disassembler {
 #define THREEDNOW_MAP_STR "x86Disassembler3DNowOpcodes"
 #define MAP5_STR          "x86DisassemblerMap5Opcodes"
 #define MAP6_STR          "x86DisassemblerMap6Opcodes"
+#define MAP7_STR          "x86DisassemblerMap7Opcodes"
 
 // Attributes of an instruction that must be known before the opcode can be
 // processed correctly.  Most of these indicate the presence of particular
@@ -296,7 +298,8 @@ enum OpcodeType {
   XOPA_MAP      = 6,
   THREEDNOW_MAP = 7,
   MAP5          = 8,
-  MAP6          = 9
+  MAP6          = 9,
+  MAP7          = 10
 };
 
 // The following structs are used for the hierarchical decode table.  After

diff  --git a/llvm/include/llvm/TargetParser/X86TargetParser.def b/llvm/include/llvm/TargetParser/X86TargetParser.def
index 85ff6996d335ae7..709ff8603b04276 100644
--- a/llvm/include/llvm/TargetParser/X86TargetParser.def
+++ b/llvm/include/llvm/TargetParser/X86TargetParser.def
@@ -241,6 +241,7 @@ X86_FEATURE       (SM3,             "sm3")
 X86_FEATURE       (SM4,             "sm4")
 X86_FEATURE       (AVXVNNIINT16,    "avxvnniint16")
 X86_FEATURE       (EVEX512,         "evex512")
+X86_FEATURE       (USERMSR,         "usermsr")
 // 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/Target/X86/Disassembler/X86Disassembler.cpp b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
index 967c7574355db65..2ec7a57093f4ba3 100644
--- a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
+++ b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
@@ -156,6 +156,9 @@ static InstrUID decode(OpcodeType type, InstructionContext insnContext,
   case MAP6:
     dec = &MAP6_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
     break;
+  case MAP7:
+    dec = &MAP7_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
+    break;
   }
 
   switch (dec->modrm_type) {
@@ -918,6 +921,9 @@ static bool readOpcode(struct InternalInstruction *insn) {
     case VEX_LOB_MAP6:
       insn->opcodeType = MAP6;
       return consume(insn, insn->opcode);
+    case VEX_LOB_MAP7:
+      insn->opcodeType = MAP7;
+      return consume(insn, insn->opcode);
     }
   } else if (insn->vectorExtensionType == TYPE_VEX_2B) {
     insn->opcodeType = TWOBYTE;
@@ -1059,6 +1065,9 @@ static int getInstructionIDWithAttrMask(uint16_t *instructionID,
   case MAP6:
     decision = &MAP6_SYM;
     break;
+  case MAP7:
+    decision = &MAP7_SYM;
+    break;
   }
 
   if (decision->opcodeDecisions[insnCtx]

diff  --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
index 95d3c8ede366f96..2d728143d3c9aa4 100644
--- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
+++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
@@ -484,7 +484,8 @@ enum VEXLeadingOpcodeByte {
   VEX_LOB_0F38 = 0x2,
   VEX_LOB_0F3A = 0x3,
   VEX_LOB_MAP5 = 0x5,
-  VEX_LOB_MAP6 = 0x6
+  VEX_LOB_MAP6 = 0x6,
+  VEX_LOB_MAP7 = 0x7
 };
 
 enum XOPMapSelect {

diff  --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index e2293fe30561fb4..1e5a3606f33a6fc 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -829,9 +829,10 @@ namespace X86II {
     /// this flag to indicate that the encoder should do the wacky 3DNow! thing.
     ThreeDNow = 7 << OpMapShift,
 
-    // MAP5, MAP6 - Prefix after the 0x0F prefix.
+    // MAP5, MAP6, MAP7 - Prefix after the 0x0F prefix.
     T_MAP5 = 8 << OpMapShift,
     T_MAP6 = 9 << OpMapShift,
+    T_MAP7 = 10 << OpMapShift,
 
     //===------------------------------------------------------------------===//
     // REX_W - REX prefixes are instruction prefixes used in 64-bit mode.

diff  --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 59a04f3167d863c..b85404be3063dae 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -89,6 +89,7 @@ class X86OpcodePrefixHelper {
   //  0b00100: Reserved for future use
   //  0b00101: VEX MAP5
   //  0b00110: VEX MAP6
+  //  0b00111: VEX MAP7
   //  0b00111-0b11111: Reserved for future use
   //  0b01000: XOP map select - 08h instructions with imm byte
   //  0b01001: XOP map select - 09h instructions with no imm byte
@@ -917,6 +918,9 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
   case X86II::T_MAP6:
     Prefix.set5M(0x6);
     break;
+  case X86II::T_MAP7:
+    Prefix.set5M(0x7);
+    break;
   }
 
   Prefix.setL(TSFlags & X86II::VEX_L);

diff  --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td
index 64f91ae90e2b0ce..f3f8d5718dfc20b 100644
--- a/llvm/lib/Target/X86/X86.td
+++ b/llvm/lib/Target/X86/X86.td
@@ -325,6 +325,8 @@ def FeatureTSXLDTRK : SubtargetFeature<"tsxldtrk", "HasTSXLDTRK", "true",
                                        "Support TSXLDTRK instructions">;
 def FeatureUINTR : SubtargetFeature<"uintr", "HasUINTR", "true",
                                     "Has UINTR Instructions">;
+def FeatureUSERMSR : SubtargetFeature<"usermsr", "HasUSERMSR", "true",
+                                      "Support USERMSR instructions">;
 def FeaturePCONFIG : SubtargetFeature<"pconfig", "HasPCONFIG", "true",
                                       "platform configuration instruction">;
 def FeatureMOVDIRI  : SubtargetFeature<"movdiri", "HasMOVDIRI", "true",

diff  --git a/llvm/lib/Target/X86/X86InstrFormats.td b/llvm/lib/Target/X86/X86InstrFormats.td
index f45869e15267c89..70ffd4175e1f145 100644
--- a/llvm/lib/Target/X86/X86InstrFormats.td
+++ b/llvm/lib/Target/X86/X86InstrFormats.td
@@ -163,6 +163,7 @@ def XOPA      : Map<6>;
 def ThreeDNow : Map<7>;
 def T_MAP5    : Map<8>;
 def T_MAP6    : Map<9>;
+def T_MAP7    : Map<10>;
 
 // Class specifying the encoding
 class Encoding<bits<2> val> {
@@ -217,6 +218,9 @@ class T_MAP6PS : T_MAP6 { Prefix OpPrefix = PS; }
 class T_MAP6PD : T_MAP6 { Prefix OpPrefix = PD; }
 class T_MAP6XS : T_MAP6 { Prefix OpPrefix = XS; }
 class T_MAP6XD : T_MAP6 { Prefix OpPrefix = XD; }
+class T_MAP7     { Map OpMap = T_MAP7; }
+class T_MAP7XS : T_MAP7 { Prefix OpPrefix = XS; } // 0xF3
+class T_MAP7XD : T_MAP7 { Prefix OpPrefix = XD; } // 0xF2
 class OBXS   { Prefix OpPrefix = XS; }
 class PS   : TB { Prefix OpPrefix = PS; }
 class PD   : TB { Prefix OpPrefix = PD; }

diff  --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td
index a20fa6a0c3b6c63..cb740bc99f7884c 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.td
+++ b/llvm/lib/Target/X86/X86InstrInfo.td
@@ -1017,6 +1017,7 @@ def HasAMXBF16   : Predicate<"Subtarget->hasAMXBF16()">;
 def HasAMXINT8   : Predicate<"Subtarget->hasAMXINT8()">;
 def HasAMXCOMPLEX : Predicate<"Subtarget->hasAMXCOMPLEX()">;
 def HasUINTR     : Predicate<"Subtarget->hasUINTR()">;
+def HasUSERMSR   : Predicate<"Subtarget->hasUSERMSR()">;
 def HasCRC32     : Predicate<"Subtarget->hasCRC32()">;
 
 def HasX86_64    : Predicate<"Subtarget->hasX86_64()">;

diff  --git a/llvm/lib/Target/X86/X86InstrSystem.td b/llvm/lib/Target/X86/X86InstrSystem.td
index 0272f7de0f9e4b5..b55956169ff2cfe 100644
--- a/llvm/lib/Target/X86/X86InstrSystem.td
+++ b/llvm/lib/Target/X86/X86InstrSystem.td
@@ -436,6 +436,22 @@ def WRMSRLIST : I<0x01, MRM_C6, (outs), (ins), "wrmsrlist", []>, XS;
 def RDMSRLIST : I<0x01, MRM_C6, (outs), (ins), "rdmsrlist", []>, XD;
 }
 
+let Predicates = [HasUSERMSR], mayLoad = 1 in {
+  def URDMSRrr : I<0xf8, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src),
+                "urdmsr\t{$src, $dst|$dst, $src}",
+                [(set GR64:$dst, (int_x86_urdmsr GR64:$src))]>, T8XD;
+  def URDMSRri : Ii32<0xf8, MRM0r, (outs GR64:$dst), (ins i64i32imm:$imm),
+                "urdmsr\t{$imm, $dst|$dst, $imm}",
+                [(set GR64:$dst, (int_x86_urdmsr i64immSExt32_su:$imm))]>, T_MAP7XD, VEX;
+}
+let Predicates = [HasUSERMSR], mayStore = 1 in {
+  def UWRMSRrr : I<0xf8, MRMSrcReg, (outs), (ins GR64:$src1, GR64:$src2),
+                "uwrmsr\t{$src1, $src2|$src2, $src1}",
+                [(int_x86_uwrmsr GR64:$src1, GR64:$src2)]>, T8XS;
+  def UWRMSRir : Ii32<0xf8, MRM0r, (outs), (ins GR64:$src, i64i32imm:$imm),
+                "uwrmsr\t{$src, $imm|$imm, $src}",
+                [(int_x86_uwrmsr GR64:$src, i64immSExt32_su:$imm)]>, T_MAP7XS, VEX;
+}
 let Defs = [RAX, RDX], Uses = [ECX] in
 def RDPMC : I<0x33, RawFrm, (outs), (ins), "rdpmc", []>, TB;
 

diff  --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp
index 436a5eb04c8d340..b320911d3ce2721 100644
--- a/llvm/lib/TargetParser/Host.cpp
+++ b/llvm/lib/TargetParser/Host.cpp
@@ -1796,6 +1796,7 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
   Features["amx-complex"] = HasLeaf7Subleaf1 && ((EDX >> 8) & 1) && HasAMXSave;
   Features["avxvnniint16"] = HasLeaf7Subleaf1 && ((EDX >> 10) & 1) && HasAVXSave;
   Features["prefetchi"]  = HasLeaf7Subleaf1 && ((EDX >> 14) & 1);
+  Features["usermsr"]  = HasLeaf7Subleaf1 && ((EDX >> 15) & 1);
 
   bool HasLeafD = MaxLevel >= 0xd &&
                   !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);

diff  --git a/llvm/lib/TargetParser/X86TargetParser.cpp b/llvm/lib/TargetParser/X86TargetParser.cpp
index b9908dd2629ff34..94849f915daa181 100644
--- a/llvm/lib/TargetParser/X86TargetParser.cpp
+++ b/llvm/lib/TargetParser/X86TargetParser.cpp
@@ -509,6 +509,7 @@ constexpr FeatureBitset ImpliedFeaturesSHSTK = {};
 constexpr FeatureBitset ImpliedFeaturesTBM = {};
 constexpr FeatureBitset ImpliedFeaturesTSXLDTRK = {};
 constexpr FeatureBitset ImpliedFeaturesUINTR = {};
+constexpr FeatureBitset ImpliedFeaturesUSERMSR = {};
 constexpr FeatureBitset ImpliedFeaturesWAITPKG = {};
 constexpr FeatureBitset ImpliedFeaturesWBNOINVD = {};
 constexpr FeatureBitset ImpliedFeaturesVZEROUPPER = {};

diff  --git a/llvm/test/CodeGen/X86/usermsr-intrinsics.ll b/llvm/test/CodeGen/X86/usermsr-intrinsics.ll
new file mode 100644
index 000000000000000..29801a494f498f8
--- /dev/null
+++ b/llvm/test/CodeGen/X86/usermsr-intrinsics.ll
@@ -0,0 +1,64 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -verify-machineinstrs -mtriple=x86_64-unknown-unknown --show-mc-encoding -mattr=+usermsr | FileCheck %s --check-prefixes=X64
+
+define i64 @test_int_x86_urdmsr(i64 %A) nounwind {
+; X64-LABEL: test_int_x86_urdmsr:
+; X64:       # %bb.0:
+; X64-NEXT:    urdmsr %rdi, %rax # encoding: [0xf2,0x0f,0x38,0xf8,0xc7]
+; X64-NEXT:    retq # encoding: [0xc3]
+  %ret = call i64 @llvm.x86.urdmsr(i64 %A)
+  ret i64 %ret
+}
+
+define i64 @test_int_x86_urdmsr_const() nounwind {
+; X64-LABEL: test_int_x86_urdmsr_const:
+; X64:       # %bb.0:
+; X64-NEXT:    urdmsr $123, %rax # encoding: [0xc4,0xe7,0x7b,0xf8,0xc0,0x7b,0x00,0x00,0x00]
+; X64-NEXT:    retq # encoding: [0xc3]
+  %ret = call i64 @llvm.x86.urdmsr(i64 123)
+  ret i64 %ret
+}
+
+define i64 @test_int_x86_urdmsr_const_i64() nounwind {
+; X64-LABEL: test_int_x86_urdmsr_const_i64:
+; X64:       # %bb.0:
+; X64-NEXT:    movabsq $8589934591, %rax # encoding: [0x48,0xb8,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00]
+; X64-NEXT:    # imm = 0x1FFFFFFFF
+; X64-NEXT:    urdmsr %rax, %rax # encoding: [0xf2,0x0f,0x38,0xf8,0xc0]
+; X64-NEXT:    retq # encoding: [0xc3]
+  %ret = call i64 @llvm.x86.urdmsr(i64 8589934591)
+  ret i64 %ret
+}
+
+declare i64 @llvm.x86.urdmsr(i64 %A)
+
+define void @test_int_x86_uwrmsr(i64 %A, i64 %B) nounwind {
+; X64-LABEL: test_int_x86_uwrmsr:
+; X64:       # %bb.0:
+; X64-NEXT:    uwrmsr %rdi, %rsi # encoding: [0xf3,0x0f,0x38,0xf8,0xfe]
+; X64-NEXT:    retq # encoding: [0xc3]
+  call void @llvm.x86.uwrmsr(i64 %A, i64 %B)
+  ret void
+}
+
+define void @test_int_x86_uwrmsr_const(i64 %A) nounwind {
+; X64-LABEL: test_int_x86_uwrmsr_const:
+; X64:       # %bb.0:
+; X64-NEXT:    uwrmsr %rdi, $123 # encoding: [0xc4,0xe7,0x7a,0xf8,0xc7,0x7b,0x00,0x00,0x00]
+; X64-NEXT:    retq # encoding: [0xc3]
+  call void @llvm.x86.uwrmsr(i64 %A, i64 123)
+  ret void
+}
+
+define void @test_int_x86_uwrmsr_const_i64(i64 %A) nounwind {
+; X64-LABEL: test_int_x86_uwrmsr_const_i64:
+; X64:       # %bb.0:
+; X64-NEXT:    movabsq $8589934591, %rax # encoding: [0x48,0xb8,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00]
+; X64-NEXT:    # imm = 0x1FFFFFFFF
+; X64-NEXT:    uwrmsr %rdi, %rax # encoding: [0xf3,0x0f,0x38,0xf8,0xf8]
+; X64-NEXT:    retq # encoding: [0xc3]
+  call void @llvm.x86.uwrmsr(i64 %A, i64 8589934591)
+  ret void
+}
+
+declare void @llvm.x86.uwrmsr(i64 %A, i64 %B)

diff  --git a/llvm/test/MC/Disassembler/X86/usermsr-64.txt b/llvm/test/MC/Disassembler/X86/usermsr-64.txt
new file mode 100644
index 000000000000000..592a1a204f5c6c5
--- /dev/null
+++ b/llvm/test/MC/Disassembler/X86/usermsr-64.txt
@@ -0,0 +1,28 @@
+# RUN: llvm-mc --disassemble %s -triple=x86_64 | FileCheck %s --check-prefixes=ATT
+# RUN: llvm-mc --disassemble %s -triple=x86_64 --output-asm-variant=1 | FileCheck %s --check-prefixes=INTEL
+
+# ATT:   urdmsr $123, %r9
+# INTEL: urdmsr r9, 123
+0xc4,0xc7,0x7b,0xf8,0xc1,0x7b,0x00,0x00,0x00
+
+# ATT:   urdmsr %r9, %r9
+# INTEL: urdmsr r9, r9
+0xf2,0x45,0x0f,0x38,0xf8,0xc9
+
+# Test if WIG is supported for this instruction/form.
+# ATT:   urdmsr %r9, %r9
+# INTEL: urdmsr r9, r9
+0xf2,0x4d,0x0f,0x38,0xf8,0xc9
+
+# ATT:   uwrmsr %r9, $123
+# INTEL: uwrmsr 123, r9
+0xc4,0xc7,0x7a,0xf8,0xc1,0x7b,0x00,0x00,0x00
+
+# ATT:   uwrmsr %r9, %r9
+# INTEL: uwrmsr r9, r9
+0xf3,0x45,0x0f,0x38,0xf8,0xc9
+
+# Test if WIG is supported for this instruction/form.
+# ATT:   uwrmsr %r9, %r9
+# INTEL: uwrmsr r9, r9
+0xf3,0x4d,0x0f,0x38,0xf8,0xc9

diff  --git a/llvm/test/MC/X86/usermsr-64-att.s b/llvm/test/MC/X86/usermsr-64-att.s
new file mode 100644
index 000000000000000..e89d0a800ab0b83
--- /dev/null
+++ b/llvm/test/MC/X86/usermsr-64-att.s
@@ -0,0 +1,18 @@
+// RUN: llvm-mc -triple x86_64 --show-encoding %s | FileCheck %s
+
+// CHECK: urdmsr $123, %r9
+// CHECK: encoding: [0xc4,0xc7,0x7b,0xf8,0xc1,0x7b,0x00,0x00,0x00]
+          urdmsr $123, %r9
+
+// CHECK: urdmsr %r9, %r9
+// CHECK: encoding: [0xf2,0x45,0x0f,0x38,0xf8,0xc9]
+          urdmsr %r9, %r9
+
+// CHECK: uwrmsr %r9, $123
+// CHECK: encoding: [0xc4,0xc7,0x7a,0xf8,0xc1,0x7b,0x00,0x00,0x00]
+          uwrmsr %r9, $123
+
+// CHECK: uwrmsr %r9, %r9
+// CHECK: encoding: [0xf3,0x45,0x0f,0x38,0xf8,0xc9]
+          uwrmsr %r9, %r9
+

diff  --git a/llvm/test/MC/X86/usermsr-64-intel.s b/llvm/test/MC/X86/usermsr-64-intel.s
new file mode 100644
index 000000000000000..13d9161080af4ac
--- /dev/null
+++ b/llvm/test/MC/X86/usermsr-64-intel.s
@@ -0,0 +1,18 @@
+// RUN: llvm-mc -triple x86_64 -x86-asm-syntax=intel -output-asm-variant=1 --show-encoding %s | FileCheck %s
+
+// CHECK: urdmsr r9, 123
+// CHECK: encoding: [0xc4,0xc7,0x7b,0xf8,0xc1,0x7b,0x00,0x00,0x00]
+          urdmsr r9, 123
+
+// CHECK: urdmsr r9, r9
+// CHECK: encoding: [0xf2,0x45,0x0f,0x38,0xf8,0xc9]
+          urdmsr r9, r9
+
+// CHECK: uwrmsr 123, r9
+// CHECK: encoding: [0xc4,0xc7,0x7a,0xf8,0xc1,0x7b,0x00,0x00,0x00]
+          uwrmsr 123, r9
+
+// CHECK: uwrmsr r9, r9
+// CHECK: encoding: [0xf3,0x45,0x0f,0x38,0xf8,0xc9]
+          uwrmsr r9, r9
+

diff  --git a/llvm/utils/TableGen/X86DisassemblerTables.cpp b/llvm/utils/TableGen/X86DisassemblerTables.cpp
index 708c92aecfc856c..ba51bf4858e19de 100644
--- a/llvm/utils/TableGen/X86DisassemblerTables.cpp
+++ b/llvm/utils/TableGen/X86DisassemblerTables.cpp
@@ -982,6 +982,7 @@ void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
   emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[7], THREEDNOW_MAP_STR);
   emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[8], MAP5_STR);
   emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[9], MAP6_STR);
+  emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[10], MAP7_STR);
 }
 
 void DisassemblerTables::emit(raw_ostream &o) const {

diff  --git a/llvm/utils/TableGen/X86DisassemblerTables.h b/llvm/utils/TableGen/X86DisassemblerTables.h
index 966f7406efec11c..4b6f6543acccfca 100644
--- a/llvm/utils/TableGen/X86DisassemblerTables.h
+++ b/llvm/utils/TableGen/X86DisassemblerTables.h
@@ -46,7 +46,8 @@ class DisassemblerTables {
   /// [7] 3dnow map opcode
   /// [8] fixed length MAP5 opcode
   /// [9] fixed length MAP6 opcode
-  std::unique_ptr<ContextDecision> Tables[10];
+  /// [10] fixed length MAP7 opcode
+  std::unique_ptr<ContextDecision> Tables[11];
 
   // Table of ModRM encodings.
   typedef std::map<std::vector<unsigned>, unsigned> ModRMMapTy;

diff  --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp
index b2f51ba016899a9..962da623b1cadc7 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -791,6 +791,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
   case X86Local::ThreeDNow: opcodeType = THREEDNOW_MAP; break;
   case X86Local::T_MAP5:    opcodeType = MAP5;          break;
   case X86Local::T_MAP6:    opcodeType = MAP6;          break;
+  case X86Local::T_MAP7:    opcodeType = MAP7;          break;
   }
 
   std::unique_ptr<ModRMFilter> filter;

diff  --git a/llvm/utils/TableGen/X86RecognizableInstr.h b/llvm/utils/TableGen/X86RecognizableInstr.h
index 5efacdb27465bfc..38bca87bfe614c3 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.h
+++ b/llvm/utils/TableGen/X86RecognizableInstr.h
@@ -137,7 +137,7 @@ namespace X86Local {
 
   enum {
     OB = 0, TB = 1, T8 = 2, TA = 3, XOP8 = 4, XOP9 = 5, XOPA = 6, ThreeDNow = 7,
-    T_MAP5 = 8, T_MAP6 = 9
+    T_MAP5 = 8, T_MAP6 = 9, T_MAP7 = 10
   };
 
   enum {


        


More information about the cfe-commits mailing list