xref: /llvm-project/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp (revision 01a92f06f23585f15b3e83b7c378d0df2d91e06b)
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 #ifdef __linux__
89 Matcher<MCInst> IsMovRegToReg(unsigned Opcode, int64_t Reg1, int64_t Reg2) {
90   return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg1), IsReg(Reg2)));
91 }
92 #endif
93 
94 Matcher<MCInst> IsMovValueToStack(unsigned Opcode, int64_t Value,
95                                   size_t Offset) {
96   return AllOf(OpcodeIs(Opcode),
97                ElementsAre(IsReg(X86::RSP), IsImm(1), IsReg(0), IsImm(Offset),
98                            IsReg(0), IsImm(Value)));
99 }
100 
101 Matcher<MCInst> IsMovValueFromStack(unsigned Opcode, unsigned Reg) {
102   return AllOf(OpcodeIs(Opcode),
103                ElementsAre(IsReg(Reg), IsReg(X86::RSP), IsImm(1), IsReg(0),
104                            IsImm(0), IsReg(0)));
105 }
106 
107 Matcher<MCInst> IsStackAllocate(unsigned Size) {
108   return AllOf(OpcodeIs(X86::SUB64ri8),
109                ElementsAre(IsReg(X86::RSP), IsReg(X86::RSP), IsImm(Size)));
110 }
111 
112 Matcher<MCInst> IsStackDeallocate(unsigned Size) {
113   return AllOf(OpcodeIs(X86::ADD64ri8),
114                ElementsAre(IsReg(X86::RSP), IsReg(X86::RSP), IsImm(Size)));
115 }
116 
117 constexpr const char kTriple[] = "x86_64-unknown-linux";
118 
119 class X86TargetTest : public ::testing::Test {
120 protected:
121   X86TargetTest(const char *Features)
122       : State(cantFail(LLVMState::Create(kTriple, "core2", Features))) {}
123 
124   static void SetUpTestCase() {
125     LLVMInitializeX86TargetInfo();
126     LLVMInitializeX86Target();
127     LLVMInitializeX86TargetMC();
128     InitializeX86ExegesisTarget();
129   }
130 
131   std::vector<MCInst> setRegTo(unsigned Reg, const APInt &Value) {
132     return State.getExegesisTarget().setRegTo(State.getSubtargetInfo(), Reg,
133                                               Value);
134   }
135 
136   const Instruction &getInstr(unsigned OpCode) {
137     return State.getIC().getInstr(OpCode);
138   }
139 
140   LLVMState State;
141 };
142 
143 class X86Core2TargetTest : public X86TargetTest {
144 public:
145   X86Core2TargetTest() : X86TargetTest("") {}
146 };
147 
148 class X86Core2AvxTargetTest : public X86TargetTest {
149 public:
150   X86Core2AvxTargetTest() : X86TargetTest("+avx") {}
151 };
152 
153 class X86Core2Avx512TargetTest : public X86TargetTest {
154 public:
155   X86Core2Avx512TargetTest() : X86TargetTest("+avx512vl") {}
156 };
157 
158 class X86Core2Avx512DQTargetTest : public X86TargetTest {
159 public:
160   X86Core2Avx512DQTargetTest() : X86TargetTest("+avx512dq") {}
161 };
162 
163 class X86Core2Avx512BWTargetTest : public X86TargetTest {
164 public:
165   X86Core2Avx512BWTargetTest() : X86TargetTest("+avx512bw") {}
166 };
167 
168 class X86Core2Avx512DQBWTargetTest : public X86TargetTest {
169 public:
170   X86Core2Avx512DQBWTargetTest() : X86TargetTest("+avx512dq,+avx512bw") {}
171 };
172 
173 TEST_F(X86Core2TargetTest, NoHighByteRegs) {
174   EXPECT_TRUE(State.getRATC().reservedRegisters().test(X86::AH));
175 }
176 
177 TEST_F(X86Core2TargetTest, SetFlags) {
178   const unsigned Reg = X86::EFLAGS;
179   EXPECT_THAT(setRegTo(Reg, APInt(64, 0x1111222233334444ULL)),
180               ElementsAre(IsStackAllocate(8),
181                           IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0),
182                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4),
183                           OpcodeIs(X86::POPF64)));
184 }
185 
186 TEST_F(X86Core2TargetTest, SetRegToGR8Value) {
187   const uint8_t Value = 0xFFU;
188   const unsigned Reg = X86::AL;
189   EXPECT_THAT(setRegTo(Reg, APInt(8, Value)),
190               ElementsAre(IsMovImmediate(X86::MOV8ri, Reg, Value)));
191 }
192 
193 TEST_F(X86Core2TargetTest, SetRegToGR16Value) {
194   const uint16_t Value = 0xFFFFU;
195   const unsigned Reg = X86::BX;
196   EXPECT_THAT(setRegTo(Reg, APInt(16, Value)),
197               ElementsAre(IsMovImmediate(X86::MOV16ri, Reg, Value)));
198 }
199 
200 TEST_F(X86Core2TargetTest, SetRegToGR32Value) {
201   const uint32_t Value = 0x7FFFFU;
202   const unsigned Reg = X86::ECX;
203   EXPECT_THAT(setRegTo(Reg, APInt(32, Value)),
204               ElementsAre(IsMovImmediate(X86::MOV32ri, Reg, Value)));
205 }
206 
207 TEST_F(X86Core2TargetTest, SetRegToGR64Value) {
208   const uint64_t Value = 0x7FFFFFFFFFFFFFFFULL;
209   const unsigned Reg = X86::RDX;
210   EXPECT_THAT(setRegTo(Reg, APInt(64, Value)),
211               ElementsAre(IsMovImmediate(X86::MOV64ri, Reg, Value)));
212 }
213 
214 TEST_F(X86Core2TargetTest, SetRegToVR64Value) {
215   EXPECT_THAT(setRegTo(X86::MM0, APInt(64, 0x1111222233334444ULL)),
216               ElementsAre(IsStackAllocate(8),
217                           IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0),
218                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4),
219                           IsMovValueFromStack(X86::MMX_MOVQ64rm, X86::MM0),
220                           IsStackDeallocate(8)));
221 }
222 
223 TEST_F(X86Core2TargetTest, SetRegToVR128Value_Use_MOVDQUrm) {
224   EXPECT_THAT(
225       setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)),
226       ElementsAre(IsStackAllocate(16),
227                   IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0),
228                   IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4),
229                   IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8),
230                   IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12),
231                   IsMovValueFromStack(X86::MOVDQUrm, X86::XMM0),
232                   IsStackDeallocate(16)));
233 }
234 
235 TEST_F(X86Core2AvxTargetTest, SetRegToVR128Value_Use_VMOVDQUrm) {
236   EXPECT_THAT(
237       setRegTo(X86::XMM0, 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::VMOVDQUrm, X86::XMM0),
244                   IsStackDeallocate(16)));
245 }
246 
247 TEST_F(X86Core2Avx512TargetTest, SetRegToVR128Value_Use_VMOVDQU32Z128rm) {
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::VMOVDQU32Z128rm, 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, SetRegToVR256Value_Use_VMOVDQU32Z256rm) {
278   const char ValueStr[] =
279       "1111111122222222333333334444444455555555666666667777777788888888";
280   EXPECT_THAT(
281       setRegTo(X86::YMM0, APInt(256, ValueStr, 16)),
282       ElementsAreArray({IsStackAllocate(32),
283                         IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0),
284                         IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4),
285                         IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8),
286                         IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12),
287                         IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16),
288                         IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20),
289                         IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24),
290                         IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28),
291                         IsMovValueFromStack(X86::VMOVDQU32Z256rm, X86::YMM0),
292                         IsStackDeallocate(32)}));
293 }
294 
295 TEST_F(X86Core2Avx512TargetTest, SetRegToVR512Value) {
296   const char ValueStr[] =
297       "1111111122222222333333334444444455555555666666667777777788888888"
298       "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000";
299   EXPECT_THAT(
300       setRegTo(X86::ZMM0, APInt(512, ValueStr, 16)),
301       ElementsAreArray({IsStackAllocate(64),
302                         IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 0),
303                         IsMovValueToStack(X86::MOV32mi, 0xFFFFFFFFUL, 4),
304                         IsMovValueToStack(X86::MOV32mi, 0xEEEEEEEEUL, 8),
305                         IsMovValueToStack(X86::MOV32mi, 0xDDDDDDDDUL, 12),
306                         IsMovValueToStack(X86::MOV32mi, 0xCCCCCCCCUL, 16),
307                         IsMovValueToStack(X86::MOV32mi, 0xBBBBBBBBUL, 20),
308                         IsMovValueToStack(X86::MOV32mi, 0xAAAAAAAAUL, 24),
309                         IsMovValueToStack(X86::MOV32mi, 0x99999999UL, 28),
310                         IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 32),
311                         IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 36),
312                         IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 40),
313                         IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 44),
314                         IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 48),
315                         IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 52),
316                         IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 56),
317                         IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 60),
318                         IsMovValueFromStack(X86::VMOVDQU32Zrm, X86::ZMM0),
319                         IsStackDeallocate(64)}));
320 }
321 
322 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_16Bits) {
323   const uint16_t Value = 0xABCDU;
324   const unsigned Reg = X86::K0;
325   const unsigned RegBitWidth = 16;
326   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
327               ElementsAre(IsStackAllocate(2),
328                           IsMovValueToStack(X86::MOV16mi, Value, 0),
329                           IsMovValueFromStack(X86::KMOVWkm, Reg),
330                           IsStackDeallocate(2)));
331 }
332 
333 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_16Bits) {
334   const uint16_t Value = 0xABCDU;
335   const unsigned Reg = X86::K0;
336   const unsigned RegBitWidth = 16;
337   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
338               ElementsAre(IsStackAllocate(2),
339                           IsMovValueToStack(X86::MOV16mi, Value, 0),
340                           IsMovValueFromStack(X86::KMOVWkm, Reg),
341                           IsStackDeallocate(2)));
342 }
343 
344 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_16Bits) {
345   const uint16_t Value = 0xABCDU;
346   const unsigned Reg = X86::K0;
347   const unsigned RegBitWidth = 16;
348   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
349               ElementsAre(IsStackAllocate(RegBitWidth / 8),
350                           IsMovValueToStack(X86::MOV16mi, Value, 0),
351                           IsMovValueFromStack(X86::KMOVWkm, Reg),
352                           IsStackDeallocate(RegBitWidth / 8)));
353 }
354 
355 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_16Bits) {
356   const uint16_t Value = 0xABCDU;
357   const unsigned Reg = X86::K0;
358   const unsigned RegBitWidth = 16;
359   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
360               ElementsAre(IsStackAllocate(RegBitWidth / 8),
361                           IsMovValueToStack(X86::MOV16mi, Value, 0),
362                           IsMovValueFromStack(X86::KMOVWkm, Reg),
363                           IsStackDeallocate(RegBitWidth / 8)));
364 }
365 
366 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_8Bits) {
367   const uint8_t Value = 0xABU;
368   const unsigned Reg = X86::K0;
369   const unsigned RegBitWidth = 8;
370   EXPECT_THAT(
371       setRegTo(Reg, APInt(RegBitWidth, Value)),
372       ElementsAre(IsStackAllocate(2),
373                   IsMovValueToStack(
374                       X86::MOV16mi,
375                       APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0),
376                   IsMovValueFromStack(X86::KMOVWkm, Reg),
377                   IsStackDeallocate(2)));
378 }
379 
380 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_8Bits) {
381   const uint8_t Value = 0xABU;
382   const unsigned Reg = X86::K0;
383   const unsigned RegBitWidth = 8;
384   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
385               ElementsAre(IsStackAllocate(RegBitWidth / 8),
386                           IsMovValueToStack(X86::MOV8mi, Value, 0),
387                           IsMovValueFromStack(X86::KMOVBkm, Reg),
388                           IsStackDeallocate(RegBitWidth / 8)));
389 }
390 
391 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_8Bits) {
392   const uint8_t Value = 0xABU;
393   const unsigned Reg = X86::K0;
394   const unsigned RegBitWidth = 8;
395   EXPECT_THAT(
396       setRegTo(Reg, APInt(RegBitWidth, Value)),
397       ElementsAre(IsStackAllocate(2),
398                   IsMovValueToStack(
399                       X86::MOV16mi,
400                       APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0),
401                   IsMovValueFromStack(X86::KMOVWkm, Reg),
402                   IsStackDeallocate(2)));
403 }
404 
405 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_8Bits) {
406   const uint8_t Value = 0xABU;
407   const unsigned Reg = X86::K0;
408   const unsigned RegBitWidth = 8;
409   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
410               ElementsAre(IsStackAllocate(RegBitWidth / 8),
411                           IsMovValueToStack(X86::MOV8mi, Value, 0),
412                           IsMovValueFromStack(X86::KMOVBkm, Reg),
413                           IsStackDeallocate(RegBitWidth / 8)));
414 }
415 
416 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_32Bits) {
417   const uint32_t Value = 0xABCDCABDU;
418   const unsigned Reg = X86::K0;
419   const unsigned RegBitWidth = 32;
420   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
421 }
422 
423 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_32Bits) {
424   const uint32_t Value = 0xABCDCABDU;
425   const unsigned Reg = X86::K0;
426   const unsigned RegBitWidth = 32;
427   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
428 }
429 
430 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_32Bits) {
431   const uint32_t Value = 0xABCDCABDU;
432   const unsigned Reg = X86::K0;
433   const unsigned RegBitWidth = 32;
434   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
435               ElementsAre(IsStackAllocate(RegBitWidth / 8),
436                           IsMovValueToStack(X86::MOV32mi, Value, 0),
437                           IsMovValueFromStack(X86::KMOVDkm, Reg),
438                           IsStackDeallocate(RegBitWidth / 8)));
439 }
440 
441 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_32Bits) {
442   const uint32_t Value = 0xABCDCABDU;
443   const unsigned Reg = X86::K0;
444   const unsigned RegBitWidth = 32;
445   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
446               ElementsAre(IsStackAllocate(RegBitWidth / 8),
447                           IsMovValueToStack(X86::MOV32mi, Value, 0),
448                           IsMovValueFromStack(X86::KMOVDkm, Reg),
449                           IsStackDeallocate(RegBitWidth / 8)));
450 }
451 
452 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_64Bits) {
453   const uint64_t Value = 0xABCDABCDCABDCABDU;
454   const unsigned Reg = X86::K0;
455   const unsigned RegBitWidth = 64;
456   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
457 }
458 
459 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_64Bits) {
460   const uint64_t Value = 0xABCDABCDCABDCABDU;
461   const unsigned Reg = X86::K0;
462   const unsigned RegBitWidth = 64;
463   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
464 }
465 
466 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_64Bits) {
467   const uint64_t Value = 0xABCDABCDCABDCABDUL;
468   const unsigned Reg = X86::K0;
469   const unsigned RegBitWidth = 64;
470   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
471               ElementsAre(IsStackAllocate(RegBitWidth / 8),
472                           IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0),
473                           IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4),
474                           IsMovValueFromStack(X86::KMOVQkm, Reg),
475                           IsStackDeallocate(RegBitWidth / 8)));
476 }
477 
478 TEST_F(X86Core2Avx512DQBWTargetTest, 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)),
483               ElementsAre(IsStackAllocate(RegBitWidth / 8),
484                           IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0),
485                           IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4),
486                           IsMovValueFromStack(X86::KMOVQkm, Reg),
487                           IsStackDeallocate(RegBitWidth / 8)));
488 }
489 
490 // Note: We always put 80 bits on the stack independently of the size of the
491 // value. This uses a bit more space but makes the code simpler.
492 
493 TEST_F(X86Core2TargetTest, SetRegToST0_32Bits) {
494   EXPECT_THAT(setRegTo(X86::ST0, APInt(32, 0x11112222ULL)),
495               ElementsAre(IsStackAllocate(10),
496                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
497                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
498                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
499                           OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
500 }
501 
502 TEST_F(X86Core2TargetTest, SetRegToST1_32Bits) {
503   const MCInst CopySt0ToSt1 = MCInstBuilder(X86::ST_Frr).addReg(X86::ST1);
504   EXPECT_THAT(setRegTo(X86::ST1, APInt(32, 0x11112222ULL)),
505               ElementsAre(IsStackAllocate(10),
506                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
507                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
508                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
509                           OpcodeIs(X86::LD_F80m), CopySt0ToSt1,
510                           IsStackDeallocate(10)));
511 }
512 
513 TEST_F(X86Core2TargetTest, SetRegToST0_64Bits) {
514   EXPECT_THAT(setRegTo(X86::ST0, APInt(64, 0x1111222233334444ULL)),
515               ElementsAre(IsStackAllocate(10),
516                           IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0),
517                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4),
518                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
519                           OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
520 }
521 
522 TEST_F(X86Core2TargetTest, SetRegToST0_80Bits) {
523   EXPECT_THAT(setRegTo(X86::ST0, APInt(80, "11112222333344445555", 16)),
524               ElementsAre(IsStackAllocate(10),
525                           IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0),
526                           IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4),
527                           IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8),
528                           OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
529 }
530 
531 TEST_F(X86Core2TargetTest, SetRegToFP0_80Bits) {
532   EXPECT_THAT(setRegTo(X86::FP0, APInt(80, "11112222333344445555", 16)),
533               ElementsAre(IsStackAllocate(10),
534                           IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0),
535                           IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4),
536                           IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8),
537                           OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
538 }
539 
540 TEST_F(X86Core2TargetTest, SetRegToFP1_32Bits) {
541   EXPECT_THAT(setRegTo(X86::FP1, APInt(32, 0x11112222ULL)),
542               ElementsAre(IsStackAllocate(10),
543                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
544                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
545                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
546                           OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
547 }
548 
549 TEST_F(X86Core2TargetTest, SetRegToFP1_4Bits) {
550   EXPECT_THAT(setRegTo(X86::FP1, APInt(4, 0x1ULL)),
551               ElementsAre(IsStackAllocate(10),
552                           IsMovValueToStack(X86::MOV32mi, 0x00000001UL, 0),
553                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
554                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
555                           OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
556 }
557 
558 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_ADD64rm) {
559   const Instruction &I = getInstr(X86::ADD64rm);
560   InstructionTemplate IT(&I);
561   constexpr const int kOffset = 42;
562   State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset);
563   // Memory is operands 2-6.
564   EXPECT_THAT(IT.getValueFor(I.Operands[2]), IsReg(X86::RDI));
565   EXPECT_THAT(IT.getValueFor(I.Operands[3]), IsImm(1));
566   EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(0));
567   EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(kOffset));
568   EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0));
569 }
570 
571 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_VGATHERDPSZ128rm) {
572   const Instruction &I = getInstr(X86::VGATHERDPSZ128rm);
573   InstructionTemplate IT(&I);
574   constexpr const int kOffset = 42;
575   State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset);
576   // Memory is operands 4-8.
577   EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(X86::RDI));
578   EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(1));
579   EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0));
580   EXPECT_THAT(IT.getValueFor(I.Operands[7]), IsImm(kOffset));
581   EXPECT_THAT(IT.getValueFor(I.Operands[8]), IsReg(0));
582 }
583 
584 TEST_F(X86Core2TargetTest, AllowAsBackToBack) {
585   EXPECT_TRUE(
586       State.getExegesisTarget().allowAsBackToBack(getInstr(X86::ADD64rr)));
587   EXPECT_FALSE(
588       State.getExegesisTarget().allowAsBackToBack(getInstr(X86::LEA64r)));
589 }
590 
591 #ifdef __linux__
592 TEST_F(X86Core2TargetTest, GenerateLowerMunmapTest) {
593   std::vector<MCInst> GeneratedCode;
594   State.getExegesisTarget().generateLowerMunmap(GeneratedCode);
595   EXPECT_THAT(GeneratedCode,
596               ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0),
597                           OpcodeIs(X86::LEA64r), OpcodeIs(X86::SHR64ri),
598                           OpcodeIs(X86::SHL64ri), OpcodeIs(X86::SUB64ri32),
599                           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap),
600                           OpcodeIs(X86::SYSCALL)));
601 }
602 
603 #ifdef __arm__
604 static constexpr const intptr_t VAddressSpaceCeiling = 0xC0000000;
605 #else
606 static constexpr const intptr_t VAddressSpaceCeiling = 0x0000800000000000;
607 #endif
608 
609 TEST_F(X86Core2TargetTest, GenerateUpperMunmapTest) {
610   std::vector<MCInst> GeneratedCode;
611   State.getExegesisTarget().generateUpperMunmap(GeneratedCode);
612   EXPECT_THAT(
613       GeneratedCode,
614       ElementsAreArray({OpcodeIs(X86::LEA64r), OpcodeIs(X86::MOV64rr),
615                         OpcodeIs(X86::ADD64rr), OpcodeIs(X86::SHR64ri),
616                         OpcodeIs(X86::SHL64ri), OpcodeIs(X86::ADD64ri32),
617                         IsMovImmediate(X86::MOV64ri, X86::RSI,
618                                        VAddressSpaceCeiling - getpagesize()),
619                         OpcodeIs(X86::SUB64rr),
620                         IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap),
621                         OpcodeIs(X86::SYSCALL)}));
622 }
623 
624 TEST_F(X86Core2TargetTest, GenerateExitSyscallTest) {
625   EXPECT_THAT(State.getExegesisTarget().generateExitSyscall(127),
626               ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 127),
627                           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_exit),
628                           OpcodeIs(X86::SYSCALL)));
629 }
630 
631 // Before kernel 4.17, Linux did not support MAP_FIXED_NOREPLACE, so if it is
632 // not available, simplfy define it as MAP_FIXED which performs the same
633 // function but does not guarantee existing mappings won't get clobbered.
634 #ifndef MAP_FIXED_NOREPLACE
635 #define MAP_FIXED_NOREPLACE MAP_FIXED
636 #endif
637 
638 // Some 32-bit architectures don't have mmap and define mmap2 instead. The only
639 // difference between the two syscalls is that mmap2's offset parameter is in
640 // terms 4096 byte offsets rather than individual bytes, so for our purposes
641 // they are effectively the same as all ofsets here are set to 0.
642 #if defined(SYS_mmap2) && !defined(SYS_mmap)
643 #define SYS_mmap SYS_mmap2
644 #endif
645 
646 TEST_F(X86Core2TargetTest, GenerateMmapTest) {
647   EXPECT_THAT(State.getExegesisTarget().generateMmap(0x1000, 4096, 0x2000),
648               ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0x1000),
649                           IsMovImmediate(X86::MOV64ri, X86::RSI, 4096),
650                           IsMovImmediate(X86::MOV64ri, X86::RDX,
651                                          PROT_READ | PROT_WRITE),
652                           IsMovImmediate(X86::MOV64ri, X86::R10,
653                                          MAP_SHARED | MAP_FIXED_NOREPLACE),
654                           IsMovImmediate(X86::MOV64ri, X86::R8, 0x2000),
655                           OpcodeIs(X86::MOV32rm),
656                           IsMovImmediate(X86::MOV64ri, X86::R9, 0),
657                           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap),
658                           OpcodeIs(X86::SYSCALL)));
659 }
660 
661 TEST_F(X86Core2TargetTest, GenerateMmapAuxMemTest) {
662   std::vector<MCInst> GeneratedCode;
663   State.getExegesisTarget().generateMmapAuxMem(GeneratedCode);
664   EXPECT_THAT(
665       GeneratedCode,
666       ElementsAre(
667           IsMovImmediate(
668               X86::MOV64ri, X86::RDI,
669               State.getExegesisTarget().getAuxiliaryMemoryStartAddress()),
670           IsMovImmediate(X86::MOV64ri, X86::RSI,
671                          SubprocessMemory::AuxiliaryMemorySize),
672           IsMovImmediate(X86::MOV64ri, X86::RDX, PROT_READ | PROT_WRITE),
673           IsMovImmediate(X86::MOV64ri, X86::R10,
674                          MAP_SHARED | MAP_FIXED_NOREPLACE),
675           OpcodeIs(X86::MOV64rr), IsMovImmediate(X86::MOV64ri, X86::R9, 0),
676           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap),
677           OpcodeIs(X86::SYSCALL)));
678 }
679 
680 TEST_F(X86Core2TargetTest, MoveArgumentRegistersTest) {
681   std::vector<MCInst> GeneratedCode;
682   State.getExegesisTarget().moveArgumentRegisters(GeneratedCode);
683   EXPECT_THAT(GeneratedCode,
684               ElementsAre(IsMovRegToReg(X86::MOV64rr, X86::R12, X86::RDI),
685                           IsMovRegToReg(X86::MOV64rr, X86::R13, X86::RSI)));
686 }
687 #endif // __linux__
688 
689 } // namespace
690 } // namespace exegesis
691 } // namespace llvm
692