xref: /llvm-project/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp (revision fa6e976602a41dad849d6e99692db437d328354b)
1 //===-- TargetTest.cpp -----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Target.h"
10 
11 #include <cassert>
12 #include <memory>
13 
14 #include "MCTargetDesc/X86MCTargetDesc.h"
15 #include "MmapUtils.h"
16 #include "SubprocessMemory.h"
17 #include "TestBase.h"
18 #include "llvm/MC/TargetRegistry.h"
19 #include "llvm/Support/TargetSelect.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 
23 #include "llvm/MC/MCInstPrinter.h"
24 
25 #ifdef __linux__
26 #include <sys/mman.h>
27 #include <sys/syscall.h>
28 #endif // __linux__
29 
30 namespace llvm {
31 
32 bool operator==(const MCOperand &a, const MCOperand &b) {
33   if (a.isImm() && b.isImm())
34     return a.getImm() == b.getImm();
35   if (a.isReg() && b.isReg())
36     return a.getReg() == b.getReg();
37   return false;
38 }
39 
40 bool operator==(const MCInst &a, const MCInst &b) {
41   if (a.getOpcode() != b.getOpcode())
42     return false;
43   if (a.getNumOperands() != b.getNumOperands())
44     return false;
45   for (unsigned I = 0; I < a.getNumOperands(); ++I) {
46     if (!(a.getOperand(I) == b.getOperand(I)))
47       return false;
48   }
49   return true;
50 }
51 
52 } // namespace llvm
53 
54 namespace llvm {
55 namespace exegesis {
56 
57 void InitializeX86ExegesisTarget();
58 
59 namespace {
60 
61 using testing::AllOf;
62 using testing::ElementsAre;
63 using testing::ElementsAreArray;
64 using testing::Eq;
65 using testing::IsEmpty;
66 using testing::Matcher;
67 using testing::Property;
68 
69 Matcher<MCOperand> IsImm(int64_t Value) {
70   return AllOf(Property(&MCOperand::isImm, Eq(true)),
71                Property(&MCOperand::getImm, Eq(Value)));
72 }
73 
74 Matcher<MCOperand> IsReg(unsigned Reg) {
75   return AllOf(Property(&MCOperand::isReg, Eq(true)),
76                Property(&MCOperand::getReg, Eq(Reg)));
77 }
78 
79 Matcher<MCInst> OpcodeIs(unsigned Opcode) {
80   return Property(&MCInst::getOpcode, Eq(Opcode));
81 }
82 
83 Matcher<MCInst> IsMovImmediate(unsigned Opcode, int64_t Reg, int64_t Value) {
84   return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg), IsImm(Value)));
85 }
86 
87 #ifdef __linux__
88 Matcher<MCInst> IsMovRegToReg(unsigned Opcode, int64_t Reg1, int64_t Reg2) {
89   return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg1), IsReg(Reg2)));
90 }
91 #endif
92 
93 Matcher<MCInst> IsMovValueToStack(unsigned Opcode, int64_t Value,
94                                   size_t Offset) {
95   return AllOf(OpcodeIs(Opcode),
96                ElementsAre(IsReg(X86::RSP), IsImm(1), IsReg(0), IsImm(Offset),
97                            IsReg(0), IsImm(Value)));
98 }
99 
100 Matcher<MCInst> IsMovValueFromStack(unsigned Opcode, unsigned Reg) {
101   return AllOf(OpcodeIs(Opcode),
102                ElementsAre(IsReg(Reg), IsReg(X86::RSP), IsImm(1), IsReg(0),
103                            IsImm(0), IsReg(0)));
104 }
105 
106 Matcher<MCInst> IsStackAllocate(unsigned Size) {
107   return AllOf(OpcodeIs(X86::SUB64ri8),
108                ElementsAre(IsReg(X86::RSP), IsReg(X86::RSP), IsImm(Size)));
109 }
110 
111 Matcher<MCInst> IsStackDeallocate(unsigned Size) {
112   return AllOf(OpcodeIs(X86::ADD64ri8),
113                ElementsAre(IsReg(X86::RSP), IsReg(X86::RSP), IsImm(Size)));
114 }
115 
116 class X86TargetTest : public X86TestBase {
117 protected:
118   X86TargetTest(const char *Features) : X86TestBase("core2", Features) {}
119 
120   std::vector<MCInst> setRegTo(unsigned Reg, const APInt &Value) {
121     return State.getExegesisTarget().setRegTo(State.getSubtargetInfo(), Reg,
122                                               Value);
123   }
124 
125   const Instruction &getInstr(unsigned OpCode) {
126     return State.getIC().getInstr(OpCode);
127   }
128 };
129 
130 class X86Core2TargetTest : public X86TargetTest {
131 public:
132   X86Core2TargetTest() : X86TargetTest("") {}
133 };
134 
135 class X86Core2AvxTargetTest : public X86TargetTest {
136 public:
137   X86Core2AvxTargetTest() : X86TargetTest("+avx") {}
138 };
139 
140 class X86Core2Avx512TargetTest : public X86TargetTest {
141 public:
142   X86Core2Avx512TargetTest() : X86TargetTest("+avx512vl") {}
143 };
144 
145 class X86Core2Avx512DQTargetTest : public X86TargetTest {
146 public:
147   X86Core2Avx512DQTargetTest() : X86TargetTest("+avx512dq") {}
148 };
149 
150 class X86Core2Avx512BWTargetTest : public X86TargetTest {
151 public:
152   X86Core2Avx512BWTargetTest() : X86TargetTest("+avx512bw") {}
153 };
154 
155 class X86Core2Avx512DQBWTargetTest : public X86TargetTest {
156 public:
157   X86Core2Avx512DQBWTargetTest() : X86TargetTest("+avx512dq,+avx512bw") {}
158 };
159 
160 TEST_F(X86Core2TargetTest, NoHighByteRegs) {
161   EXPECT_TRUE(State.getRATC().reservedRegisters().test(X86::AH));
162 }
163 
164 TEST_F(X86Core2TargetTest, SetFlags) {
165   const unsigned Reg = X86::EFLAGS;
166   EXPECT_THAT(setRegTo(Reg, APInt(64, 0x1111222233334444ULL)),
167               ElementsAre(IsStackAllocate(8),
168                           IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0),
169                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4),
170                           OpcodeIs(X86::POPF64)));
171 }
172 
173 TEST_F(X86Core2TargetTest, SetRegToGR8Value) {
174   const uint8_t Value = 0xFFU;
175   const unsigned Reg = X86::AL;
176   EXPECT_THAT(setRegTo(Reg, APInt(8, Value)),
177               ElementsAre(IsMovImmediate(X86::MOV8ri, Reg, Value)));
178 }
179 
180 TEST_F(X86Core2TargetTest, SetRegToGR16Value) {
181   const uint16_t Value = 0xFFFFU;
182   const unsigned Reg = X86::BX;
183   EXPECT_THAT(setRegTo(Reg, APInt(16, Value)),
184               ElementsAre(IsMovImmediate(X86::MOV16ri, Reg, Value)));
185 }
186 
187 TEST_F(X86Core2TargetTest, SetRegToGR32Value) {
188   const uint32_t Value = 0x7FFFFU;
189   const unsigned Reg = X86::ECX;
190   EXPECT_THAT(setRegTo(Reg, APInt(32, Value)),
191               ElementsAre(IsMovImmediate(X86::MOV32ri, Reg, Value)));
192 }
193 
194 TEST_F(X86Core2TargetTest, SetRegToGR64Value) {
195   const uint64_t Value = 0x7FFFFFFFFFFFFFFFULL;
196   const unsigned Reg = X86::RDX;
197   EXPECT_THAT(setRegTo(Reg, APInt(64, Value)),
198               ElementsAre(IsMovImmediate(X86::MOV64ri, Reg, Value)));
199 }
200 
201 TEST_F(X86Core2TargetTest, SetRegToVR64Value) {
202   EXPECT_THAT(setRegTo(X86::MM0, APInt(64, 0x1111222233334444ULL)),
203               ElementsAre(IsStackAllocate(8),
204                           IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0),
205                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4),
206                           IsMovValueFromStack(X86::MMX_MOVQ64rm, X86::MM0),
207                           IsStackDeallocate(8)));
208 }
209 
210 TEST_F(X86Core2TargetTest, SetRegToVR128Value_Use_MOVDQUrm) {
211   EXPECT_THAT(
212       setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)),
213       ElementsAre(IsStackAllocate(16),
214                   IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0),
215                   IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4),
216                   IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8),
217                   IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12),
218                   IsMovValueFromStack(X86::MOVDQUrm, X86::XMM0),
219                   IsStackDeallocate(16)));
220 }
221 
222 TEST_F(X86Core2AvxTargetTest, SetRegToVR128Value_Use_VMOVDQUrm) {
223   EXPECT_THAT(
224       setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)),
225       ElementsAre(IsStackAllocate(16),
226                   IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0),
227                   IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4),
228                   IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8),
229                   IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12),
230                   IsMovValueFromStack(X86::VMOVDQUrm, X86::XMM0),
231                   IsStackDeallocate(16)));
232 }
233 
234 TEST_F(X86Core2Avx512TargetTest,
235        SetRegToVR128ValueHighXMM_Use_VMOVDQU32Z128rm) {
236   EXPECT_THAT(
237       setRegTo(X86::XMM16, APInt(128, "11112222333344445555666677778888", 16)),
238       ElementsAre(IsStackAllocate(16),
239                   IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0),
240                   IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4),
241                   IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8),
242                   IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12),
243                   IsMovValueFromStack(X86::VMOVDQU32Z128rm, X86::XMM16),
244                   IsStackDeallocate(16)));
245 }
246 
247 TEST_F(X86Core2Avx512TargetTest, SetRegToVR128ValueLowXMM_Use_VMOVDQUrm) {
248   EXPECT_THAT(
249       setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)),
250       ElementsAre(IsStackAllocate(16),
251                   IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0),
252                   IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4),
253                   IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8),
254                   IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12),
255                   IsMovValueFromStack(X86::VMOVDQUrm, X86::XMM0),
256                   IsStackDeallocate(16)));
257 }
258 
259 TEST_F(X86Core2AvxTargetTest, SetRegToVR256Value_Use_VMOVDQUYrm) {
260   const char ValueStr[] =
261       "1111111122222222333333334444444455555555666666667777777788888888";
262   EXPECT_THAT(
263       setRegTo(X86::YMM0, APInt(256, ValueStr, 16)),
264       ElementsAreArray({IsStackAllocate(32),
265                         IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0),
266                         IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4),
267                         IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8),
268                         IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12),
269                         IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16),
270                         IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20),
271                         IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24),
272                         IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28),
273                         IsMovValueFromStack(X86::VMOVDQUYrm, X86::YMM0),
274                         IsStackDeallocate(32)}));
275 }
276 
277 TEST_F(X86Core2Avx512TargetTest,
278        SetRegToVR256ValueHighYMM_Use_VMOVDQU32Z256rm) {
279   const char ValueStr[] =
280       "1111111122222222333333334444444455555555666666667777777788888888";
281   EXPECT_THAT(
282       setRegTo(X86::YMM16, APInt(256, ValueStr, 16)),
283       ElementsAreArray({IsStackAllocate(32),
284                         IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0),
285                         IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4),
286                         IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8),
287                         IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12),
288                         IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16),
289                         IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20),
290                         IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24),
291                         IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28),
292                         IsMovValueFromStack(X86::VMOVDQU32Z256rm, X86::YMM16),
293                         IsStackDeallocate(32)}));
294 }
295 
296 TEST_F(X86Core2Avx512TargetTest, SetRegToVR256ValueLowYMM_Use_VMOVDQUYrm) {
297   const char ValueStr[] =
298       "1111111122222222333333334444444455555555666666667777777788888888";
299   EXPECT_THAT(
300       setRegTo(X86::YMM0, APInt(256, ValueStr, 16)),
301       ElementsAreArray({IsStackAllocate(32),
302                         IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0),
303                         IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4),
304                         IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8),
305                         IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12),
306                         IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16),
307                         IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20),
308                         IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24),
309                         IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28),
310                         IsMovValueFromStack(X86::VMOVDQUYrm, X86::YMM0),
311                         IsStackDeallocate(32)}));
312 }
313 
314 TEST_F(X86Core2Avx512TargetTest, SetRegToVR512Value) {
315   const char ValueStr[] =
316       "1111111122222222333333334444444455555555666666667777777788888888"
317       "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000";
318   EXPECT_THAT(
319       setRegTo(X86::ZMM0, APInt(512, ValueStr, 16)),
320       ElementsAreArray({IsStackAllocate(64),
321                         IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 0),
322                         IsMovValueToStack(X86::MOV32mi, 0xFFFFFFFFUL, 4),
323                         IsMovValueToStack(X86::MOV32mi, 0xEEEEEEEEUL, 8),
324                         IsMovValueToStack(X86::MOV32mi, 0xDDDDDDDDUL, 12),
325                         IsMovValueToStack(X86::MOV32mi, 0xCCCCCCCCUL, 16),
326                         IsMovValueToStack(X86::MOV32mi, 0xBBBBBBBBUL, 20),
327                         IsMovValueToStack(X86::MOV32mi, 0xAAAAAAAAUL, 24),
328                         IsMovValueToStack(X86::MOV32mi, 0x99999999UL, 28),
329                         IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 32),
330                         IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 36),
331                         IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 40),
332                         IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 44),
333                         IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 48),
334                         IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 52),
335                         IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 56),
336                         IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 60),
337                         IsMovValueFromStack(X86::VMOVDQU32Zrm, X86::ZMM0),
338                         IsStackDeallocate(64)}));
339 }
340 
341 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_16Bits) {
342   const uint16_t Value = 0xABCDU;
343   const unsigned Reg = X86::K0;
344   const unsigned RegBitWidth = 16;
345   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
346               ElementsAre(IsStackAllocate(2),
347                           IsMovValueToStack(X86::MOV16mi, Value, 0),
348                           IsMovValueFromStack(X86::KMOVWkm, Reg),
349                           IsStackDeallocate(2)));
350 }
351 
352 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_16Bits) {
353   const uint16_t Value = 0xABCDU;
354   const unsigned Reg = X86::K0;
355   const unsigned RegBitWidth = 16;
356   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
357               ElementsAre(IsStackAllocate(2),
358                           IsMovValueToStack(X86::MOV16mi, Value, 0),
359                           IsMovValueFromStack(X86::KMOVWkm, Reg),
360                           IsStackDeallocate(2)));
361 }
362 
363 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_16Bits) {
364   const uint16_t Value = 0xABCDU;
365   const unsigned Reg = X86::K0;
366   const unsigned RegBitWidth = 16;
367   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
368               ElementsAre(IsStackAllocate(RegBitWidth / 8),
369                           IsMovValueToStack(X86::MOV16mi, Value, 0),
370                           IsMovValueFromStack(X86::KMOVWkm, Reg),
371                           IsStackDeallocate(RegBitWidth / 8)));
372 }
373 
374 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_16Bits) {
375   const uint16_t Value = 0xABCDU;
376   const unsigned Reg = X86::K0;
377   const unsigned RegBitWidth = 16;
378   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
379               ElementsAre(IsStackAllocate(RegBitWidth / 8),
380                           IsMovValueToStack(X86::MOV16mi, Value, 0),
381                           IsMovValueFromStack(X86::KMOVWkm, Reg),
382                           IsStackDeallocate(RegBitWidth / 8)));
383 }
384 
385 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_8Bits) {
386   const uint8_t Value = 0xABU;
387   const unsigned Reg = X86::K0;
388   const unsigned RegBitWidth = 8;
389   EXPECT_THAT(
390       setRegTo(Reg, APInt(RegBitWidth, Value)),
391       ElementsAre(IsStackAllocate(2),
392                   IsMovValueToStack(
393                       X86::MOV16mi,
394                       APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0),
395                   IsMovValueFromStack(X86::KMOVWkm, Reg),
396                   IsStackDeallocate(2)));
397 }
398 
399 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_8Bits) {
400   const uint8_t Value = 0xABU;
401   const unsigned Reg = X86::K0;
402   const unsigned RegBitWidth = 8;
403   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
404               ElementsAre(IsStackAllocate(RegBitWidth / 8),
405                           IsMovValueToStack(X86::MOV8mi, Value, 0),
406                           IsMovValueFromStack(X86::KMOVBkm, Reg),
407                           IsStackDeallocate(RegBitWidth / 8)));
408 }
409 
410 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_8Bits) {
411   const uint8_t Value = 0xABU;
412   const unsigned Reg = X86::K0;
413   const unsigned RegBitWidth = 8;
414   EXPECT_THAT(
415       setRegTo(Reg, APInt(RegBitWidth, Value)),
416       ElementsAre(IsStackAllocate(2),
417                   IsMovValueToStack(
418                       X86::MOV16mi,
419                       APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0),
420                   IsMovValueFromStack(X86::KMOVWkm, Reg),
421                   IsStackDeallocate(2)));
422 }
423 
424 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_8Bits) {
425   const uint8_t Value = 0xABU;
426   const unsigned Reg = X86::K0;
427   const unsigned RegBitWidth = 8;
428   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
429               ElementsAre(IsStackAllocate(RegBitWidth / 8),
430                           IsMovValueToStack(X86::MOV8mi, Value, 0),
431                           IsMovValueFromStack(X86::KMOVBkm, Reg),
432                           IsStackDeallocate(RegBitWidth / 8)));
433 }
434 
435 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_32Bits) {
436   const uint32_t Value = 0xABCDCABDU;
437   const unsigned Reg = X86::K0;
438   const unsigned RegBitWidth = 32;
439   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
440 }
441 
442 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_32Bits) {
443   const uint32_t Value = 0xABCDCABDU;
444   const unsigned Reg = X86::K0;
445   const unsigned RegBitWidth = 32;
446   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
447 }
448 
449 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_32Bits) {
450   const uint32_t Value = 0xABCDCABDU;
451   const unsigned Reg = X86::K0;
452   const unsigned RegBitWidth = 32;
453   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
454               ElementsAre(IsStackAllocate(RegBitWidth / 8),
455                           IsMovValueToStack(X86::MOV32mi, Value, 0),
456                           IsMovValueFromStack(X86::KMOVDkm, Reg),
457                           IsStackDeallocate(RegBitWidth / 8)));
458 }
459 
460 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_32Bits) {
461   const uint32_t Value = 0xABCDCABDU;
462   const unsigned Reg = X86::K0;
463   const unsigned RegBitWidth = 32;
464   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
465               ElementsAre(IsStackAllocate(RegBitWidth / 8),
466                           IsMovValueToStack(X86::MOV32mi, Value, 0),
467                           IsMovValueFromStack(X86::KMOVDkm, Reg),
468                           IsStackDeallocate(RegBitWidth / 8)));
469 }
470 
471 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_64Bits) {
472   const uint64_t Value = 0xABCDABCDCABDCABDU;
473   const unsigned Reg = X86::K0;
474   const unsigned RegBitWidth = 64;
475   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
476 }
477 
478 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_64Bits) {
479   const uint64_t Value = 0xABCDABCDCABDCABDU;
480   const unsigned Reg = X86::K0;
481   const unsigned RegBitWidth = 64;
482   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
483 }
484 
485 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_64Bits) {
486   const uint64_t Value = 0xABCDABCDCABDCABDUL;
487   const unsigned Reg = X86::K0;
488   const unsigned RegBitWidth = 64;
489   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
490               ElementsAre(IsStackAllocate(RegBitWidth / 8),
491                           IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0),
492                           IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4),
493                           IsMovValueFromStack(X86::KMOVQkm, Reg),
494                           IsStackDeallocate(RegBitWidth / 8)));
495 }
496 
497 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_64Bits) {
498   const uint64_t Value = 0xABCDABCDCABDCABDU;
499   const unsigned Reg = X86::K0;
500   const unsigned RegBitWidth = 64;
501   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
502               ElementsAre(IsStackAllocate(RegBitWidth / 8),
503                           IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0),
504                           IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4),
505                           IsMovValueFromStack(X86::KMOVQkm, Reg),
506                           IsStackDeallocate(RegBitWidth / 8)));
507 }
508 
509 // Note: We always put 80 bits on the stack independently of the size of the
510 // value. This uses a bit more space but makes the code simpler.
511 
512 TEST_F(X86Core2TargetTest, SetRegToST0_32Bits) {
513   EXPECT_THAT(setRegTo(X86::ST0, APInt(32, 0x11112222ULL)),
514               ElementsAre(IsStackAllocate(10),
515                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
516                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
517                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
518                           OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
519 }
520 
521 TEST_F(X86Core2TargetTest, SetRegToST1_32Bits) {
522   const MCInst CopySt0ToSt1 = MCInstBuilder(X86::ST_Frr).addReg(X86::ST1);
523   EXPECT_THAT(setRegTo(X86::ST1, APInt(32, 0x11112222ULL)),
524               ElementsAre(IsStackAllocate(10),
525                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
526                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
527                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
528                           OpcodeIs(X86::LD_F80m), CopySt0ToSt1,
529                           IsStackDeallocate(10)));
530 }
531 
532 TEST_F(X86Core2TargetTest, SetRegToST0_64Bits) {
533   EXPECT_THAT(setRegTo(X86::ST0, APInt(64, 0x1111222233334444ULL)),
534               ElementsAre(IsStackAllocate(10),
535                           IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0),
536                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4),
537                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
538                           OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
539 }
540 
541 TEST_F(X86Core2TargetTest, SetRegToST0_80Bits) {
542   EXPECT_THAT(setRegTo(X86::ST0, APInt(80, "11112222333344445555", 16)),
543               ElementsAre(IsStackAllocate(10),
544                           IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0),
545                           IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4),
546                           IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8),
547                           OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
548 }
549 
550 TEST_F(X86Core2TargetTest, SetRegToFP0_80Bits) {
551   EXPECT_THAT(setRegTo(X86::FP0, APInt(80, "11112222333344445555", 16)),
552               ElementsAre(IsStackAllocate(10),
553                           IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0),
554                           IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4),
555                           IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8),
556                           OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
557 }
558 
559 TEST_F(X86Core2TargetTest, SetRegToFP1_32Bits) {
560   EXPECT_THAT(setRegTo(X86::FP1, APInt(32, 0x11112222ULL)),
561               ElementsAre(IsStackAllocate(10),
562                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
563                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
564                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
565                           OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
566 }
567 
568 TEST_F(X86Core2TargetTest, SetRegToFP1_4Bits) {
569   EXPECT_THAT(setRegTo(X86::FP1, APInt(4, 0x1ULL)),
570               ElementsAre(IsStackAllocate(10),
571                           IsMovValueToStack(X86::MOV32mi, 0x00000001UL, 0),
572                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
573                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
574                           OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
575 }
576 
577 TEST_F(X86Core2TargetTest, SetRegToDf1) {
578   EXPECT_THAT(setRegTo(X86::DF, APInt(1, 1)), ElementsAre(OpcodeIs(X86::STD)));
579 }
580 
581 TEST_F(X86Core2TargetTest, SetRegToDf0) {
582   EXPECT_THAT(setRegTo(X86::DF, APInt(1, 0)), ElementsAre(OpcodeIs(X86::CLD)));
583 }
584 
585 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_ADD64rm) {
586   const Instruction &I = getInstr(X86::ADD64rm);
587   InstructionTemplate IT(&I);
588   constexpr const int kOffset = 42;
589   State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset);
590   // Memory is operands 2-6.
591   EXPECT_THAT(IT.getValueFor(I.Operands[2]), IsReg(X86::RDI));
592   EXPECT_THAT(IT.getValueFor(I.Operands[3]), IsImm(1));
593   EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(0));
594   EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(kOffset));
595   EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0));
596 }
597 
598 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_VGATHERDPSZ128rm) {
599   const Instruction &I = getInstr(X86::VGATHERDPSZ128rm);
600   InstructionTemplate IT(&I);
601   constexpr const int kOffset = 42;
602   State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset);
603   // Memory is operands 4-8.
604   EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(X86::RDI));
605   EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(1));
606   EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0));
607   EXPECT_THAT(IT.getValueFor(I.Operands[7]), IsImm(kOffset));
608   EXPECT_THAT(IT.getValueFor(I.Operands[8]), IsReg(0));
609 }
610 
611 TEST_F(X86Core2TargetTest, AllowAsBackToBack) {
612   EXPECT_TRUE(
613       State.getExegesisTarget().allowAsBackToBack(getInstr(X86::ADD64rr)));
614   EXPECT_FALSE(
615       State.getExegesisTarget().allowAsBackToBack(getInstr(X86::LEA64r)));
616 }
617 
618 #ifdef __linux__
619 TEST_F(X86Core2TargetTest, GenerateLowerMunmapTest) {
620   std::vector<MCInst> GeneratedCode;
621   State.getExegesisTarget().generateLowerMunmap(GeneratedCode);
622   EXPECT_THAT(GeneratedCode,
623               ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0),
624                           OpcodeIs(X86::LEA64r), OpcodeIs(X86::SHR64ri),
625                           OpcodeIs(X86::SHL64ri), OpcodeIs(X86::SUB64ri32),
626                           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap),
627                           OpcodeIs(X86::SYSCALL)));
628 }
629 
630 #ifdef __arm__
631 static constexpr const uintptr_t VAddressSpaceCeiling = 0xC0000000;
632 #else
633 static constexpr const uintptr_t VAddressSpaceCeiling = 0x0000800000000000;
634 #endif
635 
636 TEST_F(X86Core2TargetTest, GenerateUpperMunmapTest) {
637   std::vector<MCInst> GeneratedCode;
638   State.getExegesisTarget().generateUpperMunmap(GeneratedCode);
639   EXPECT_THAT(
640       GeneratedCode,
641       ElementsAreArray({OpcodeIs(X86::LEA64r), OpcodeIs(X86::MOV64rr),
642                         OpcodeIs(X86::ADD64rr), OpcodeIs(X86::SHR64ri),
643                         OpcodeIs(X86::SHL64ri), OpcodeIs(X86::ADD64ri32),
644                         IsMovImmediate(X86::MOV64ri, X86::RSI,
645                                        VAddressSpaceCeiling - getpagesize()),
646                         OpcodeIs(X86::SUB64rr),
647                         IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap),
648                         OpcodeIs(X86::SYSCALL)}));
649 }
650 
651 TEST_F(X86Core2TargetTest, GenerateExitSyscallTest) {
652   EXPECT_THAT(State.getExegesisTarget().generateExitSyscall(127),
653               ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 127),
654                           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_exit),
655                           OpcodeIs(X86::SYSCALL)));
656 }
657 
658 TEST_F(X86Core2TargetTest, GenerateMmapTest) {
659   EXPECT_THAT(State.getExegesisTarget().generateMmap(0x1000, 4096, 0x2000),
660               ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0x1000),
661                           IsMovImmediate(X86::MOV64ri, X86::RSI, 4096),
662                           IsMovImmediate(X86::MOV64ri, X86::RDX,
663                                          PROT_READ | PROT_WRITE),
664                           IsMovImmediate(X86::MOV64ri, X86::R10,
665                                          MAP_SHARED | MAP_FIXED_NOREPLACE),
666                           IsMovImmediate(X86::MOV64ri, X86::R8, 0x2000),
667                           OpcodeIs(X86::MOV32rm),
668                           IsMovImmediate(X86::MOV64ri, X86::R9, 0),
669                           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap),
670                           OpcodeIs(X86::SYSCALL)));
671 }
672 
673 TEST_F(X86Core2TargetTest, GenerateMmapAuxMemTest) {
674   std::vector<MCInst> GeneratedCode;
675   State.getExegesisTarget().generateMmapAuxMem(GeneratedCode);
676   EXPECT_THAT(
677       GeneratedCode,
678       ElementsAre(
679           IsMovImmediate(
680               X86::MOV64ri, X86::RDI,
681               State.getExegesisTarget().getAuxiliaryMemoryStartAddress()),
682           IsMovImmediate(X86::MOV64ri, X86::RSI,
683                          SubprocessMemory::AuxiliaryMemorySize),
684           IsMovImmediate(X86::MOV64ri, X86::RDX, PROT_READ | PROT_WRITE),
685           IsMovImmediate(X86::MOV64ri, X86::R10,
686                          MAP_SHARED | MAP_FIXED_NOREPLACE),
687           OpcodeIs(X86::MOV64rr), IsMovImmediate(X86::MOV64ri, X86::R9, 0),
688           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap),
689           OpcodeIs(X86::SYSCALL)));
690 }
691 
692 TEST_F(X86Core2TargetTest, MoveArgumentRegistersTest) {
693   std::vector<MCInst> GeneratedCode;
694   State.getExegesisTarget().moveArgumentRegisters(GeneratedCode);
695   EXPECT_THAT(GeneratedCode,
696               ElementsAre(IsMovRegToReg(X86::MOV64rr, X86::R12, X86::RDI),
697                           IsMovRegToReg(X86::MOV64rr, X86::R13, X86::RSI)));
698 }
699 #endif // __linux__
700 
701 } // namespace
702 } // namespace exegesis
703 } // namespace llvm
704