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