[llvm] 6fb3c3a - [llvm-exegesis] `ExegesisX86Target::setRegTo()`: support mask (K) regs

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 10 18:03:28 PST 2022


Author: Roman Lebedev
Date: 2022-12-11T05:03:00+03:00
New Revision: 6fb3c3a3cb72d932868a31f0a2139df9af292aa6

URL: https://github.com/llvm/llvm-project/commit/6fb3c3a3cb72d932868a31f0a2139df9af292aa6
DIFF: https://github.com/llvm/llvm-project/commit/6fb3c3a3cb72d932868a31f0a2139df9af292aa6.diff

LOG: [llvm-exegesis] `ExegesisX86Target::setRegTo()`: support mask (K) regs

This only supports the obvious case, where the requested width
is supported by the available ISA sed, and there is
an appropriate, or wider, `KMOV?` instruction.

This doesn't deal with the 32/64 bit mask without BW instruction set.

This was the missing functionality that was
causing crashes in fd52305fdc7572534867247c8fb66093faf52e5c.

Added: 
    

Modified: 
    llvm/tools/llvm-exegesis/lib/X86/Target.cpp
    llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index 8ab6a67662118..3770431613e58 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -880,6 +880,35 @@ std::vector<MCInst> ExegesisX86Target::setRegTo(const MCSubtargetInfo &STI,
     return {loadImmediate(Reg, 32, Value)};
   if (X86::GR64RegClass.contains(Reg))
     return {loadImmediate(Reg, 64, Value)};
+  if (X86::VK8RegClass.contains(Reg) || X86::VK16RegClass.contains(Reg) ||
+      X86::VK32RegClass.contains(Reg) || X86::VK64RegClass.contains(Reg)) {
+    switch (Value.getBitWidth()) {
+    case 8:
+      if (STI.getFeatureBits()[X86::FeatureDQI]) {
+        ConstantInliner CI(Value);
+        return CI.loadAndFinalize(Reg, Value.getBitWidth(), X86::KMOVBkm);
+      }
+      [[fallthrough]];
+    case 16:
+      if (STI.getFeatureBits()[X86::FeatureAVX512]) {
+        ConstantInliner CI(Value.zextOrTrunc(16));
+        return CI.loadAndFinalize(Reg, 16, X86::KMOVWkm);
+      }
+      break;
+    case 32:
+      if (STI.getFeatureBits()[X86::FeatureBWI]) {
+        ConstantInliner CI(Value);
+        return CI.loadAndFinalize(Reg, Value.getBitWidth(), X86::KMOVDkm);
+      }
+      break;
+    case 64:
+      if (STI.getFeatureBits()[X86::FeatureBWI]) {
+        ConstantInliner CI(Value);
+        return CI.loadAndFinalize(Reg, Value.getBitWidth(), X86::KMOVQkm);
+      }
+      break;
+    }
+  }
   ConstantInliner CI(Value);
   if (X86::VR64RegClass.contains(Reg))
     return CI.loadAndFinalize(Reg, 64, X86::MMX_MOVQ64rm);

diff  --git a/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
index a76dddc69e60e..cc3882a4b013c 100644
--- a/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
+++ b/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
@@ -55,6 +55,7 @@ using testing::ElementsAre;
 using testing::ElementsAreArray;
 using testing::Eq;
 using testing::Gt;
+using testing::IsEmpty;
 using testing::Matcher;
 using testing::NotNull;
 using testing::Property;
@@ -142,6 +143,21 @@ class X86Core2Avx512TargetTest : public X86TargetTest {
   X86Core2Avx512TargetTest() : X86TargetTest("+avx512vl") {}
 };
 
+class X86Core2Avx512DQTargetTest : public X86TargetTest {
+public:
+  X86Core2Avx512DQTargetTest() : X86TargetTest("+avx512dq") {}
+};
+
+class X86Core2Avx512BWTargetTest : public X86TargetTest {
+public:
+  X86Core2Avx512BWTargetTest() : X86TargetTest("+avx512bw") {}
+};
+
+class X86Core2Avx512DQBWTargetTest : public X86TargetTest {
+public:
+  X86Core2Avx512DQBWTargetTest() : X86TargetTest("+avx512dq,+avx512bw") {}
+};
+
 TEST_F(X86Core2TargetTest, NoHighByteRegs) {
   EXPECT_TRUE(State.getRATC().reservedRegisters().test(X86::AH));
 }
@@ -291,6 +307,174 @@ TEST_F(X86Core2Avx512TargetTest, SetRegToVR512Value) {
                         IsStackDeallocate(64)}));
 }
 
+TEST_F(X86Core2Avx512TargetTest, SetRegToK0_16Bits) {
+  const uint16_t Value = 0xABCDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 16;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
+              ElementsAre(IsStackAllocate(2),
+                          IsMovValueToStack(X86::MOV16mi, Value, 0),
+                          IsMovValueFromStack(X86::KMOVWkm, Reg),
+                          IsStackDeallocate(2)));
+}
+
+TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_16Bits) {
+  const uint16_t Value = 0xABCDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 16;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
+              ElementsAre(IsStackAllocate(2),
+                          IsMovValueToStack(X86::MOV16mi, Value, 0),
+                          IsMovValueFromStack(X86::KMOVWkm, Reg),
+                          IsStackDeallocate(2)));
+}
+
+TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_16Bits) {
+  const uint16_t Value = 0xABCDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 16;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
+              ElementsAre(IsStackAllocate(RegBitWidth / 8),
+                          IsMovValueToStack(X86::MOV16mi, Value, 0),
+                          IsMovValueFromStack(X86::KMOVWkm, Reg),
+                          IsStackDeallocate(RegBitWidth / 8)));
+}
+
+TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_16Bits) {
+  const uint16_t Value = 0xABCDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 16;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
+              ElementsAre(IsStackAllocate(RegBitWidth / 8),
+                          IsMovValueToStack(X86::MOV16mi, Value, 0),
+                          IsMovValueFromStack(X86::KMOVWkm, Reg),
+                          IsStackDeallocate(RegBitWidth / 8)));
+}
+
+TEST_F(X86Core2Avx512TargetTest, SetRegToK0_8Bits) {
+  const uint8_t Value = 0xABU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 8;
+  EXPECT_THAT(
+      setRegTo(Reg, APInt(RegBitWidth, Value)),
+      ElementsAre(IsStackAllocate(2),
+                  IsMovValueToStack(
+                      X86::MOV16mi,
+                      APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0),
+                  IsMovValueFromStack(X86::KMOVWkm, Reg),
+                  IsStackDeallocate(2)));
+}
+
+TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_8Bits) {
+  const uint8_t Value = 0xABU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 8;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
+              ElementsAre(IsStackAllocate(RegBitWidth / 8),
+                          IsMovValueToStack(X86::MOV8mi, Value, 0),
+                          IsMovValueFromStack(X86::KMOVBkm, Reg),
+                          IsStackDeallocate(RegBitWidth / 8)));
+}
+
+TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_8Bits) {
+  const uint8_t Value = 0xABU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 8;
+  EXPECT_THAT(
+      setRegTo(Reg, APInt(RegBitWidth, Value)),
+      ElementsAre(IsStackAllocate(2),
+                  IsMovValueToStack(
+                      X86::MOV16mi,
+                      APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0),
+                  IsMovValueFromStack(X86::KMOVWkm, Reg),
+                  IsStackDeallocate(2)));
+}
+
+TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_8Bits) {
+  const uint8_t Value = 0xABU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 8;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
+              ElementsAre(IsStackAllocate(RegBitWidth / 8),
+                          IsMovValueToStack(X86::MOV8mi, Value, 0),
+                          IsMovValueFromStack(X86::KMOVBkm, Reg),
+                          IsStackDeallocate(RegBitWidth / 8)));
+}
+
+TEST_F(X86Core2Avx512TargetTest, SetRegToK0_32Bits) {
+  const uint32_t Value = 0xABCDCABDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 32;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
+}
+
+TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_32Bits) {
+  const uint32_t Value = 0xABCDCABDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 32;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
+}
+
+TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_32Bits) {
+  const uint32_t Value = 0xABCDCABDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 32;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
+              ElementsAre(IsStackAllocate(RegBitWidth / 8),
+                          IsMovValueToStack(X86::MOV32mi, Value, 0),
+                          IsMovValueFromStack(X86::KMOVDkm, Reg),
+                          IsStackDeallocate(RegBitWidth / 8)));
+}
+
+TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_32Bits) {
+  const uint32_t Value = 0xABCDCABDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 32;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
+              ElementsAre(IsStackAllocate(RegBitWidth / 8),
+                          IsMovValueToStack(X86::MOV32mi, Value, 0),
+                          IsMovValueFromStack(X86::KMOVDkm, Reg),
+                          IsStackDeallocate(RegBitWidth / 8)));
+}
+
+TEST_F(X86Core2Avx512TargetTest, SetRegToK0_64Bits) {
+  const uint64_t Value = 0xABCDABCDCABDCABDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 64;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
+}
+
+TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_64Bits) {
+  const uint64_t Value = 0xABCDABCDCABDCABDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 64;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
+}
+
+TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_64Bits) {
+  const uint64_t Value = 0xABCDABCDCABDCABDUL;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 64;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
+              ElementsAre(IsStackAllocate(RegBitWidth / 8),
+                          IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0),
+                          IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4),
+                          IsMovValueFromStack(X86::KMOVQkm, Reg),
+                          IsStackDeallocate(RegBitWidth / 8)));
+}
+
+TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_64Bits) {
+  const uint64_t Value = 0xABCDABCDCABDCABDU;
+  const unsigned Reg = X86::K0;
+  const unsigned RegBitWidth = 64;
+  EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
+              ElementsAre(IsStackAllocate(RegBitWidth / 8),
+                          IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0),
+                          IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4),
+                          IsMovValueFromStack(X86::KMOVQkm, Reg),
+                          IsStackDeallocate(RegBitWidth / 8)));
+}
+
 // Note: We always put 80 bits on the stack independently of the size of the
 // value. This uses a bit more space but makes the code simpler.
 


        


More information about the llvm-commits mailing list