xref: /llvm-project/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp (revision 842fd1537521d38913aec5c9a081afedf97d88fe)
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 "llvm/MC/TargetRegistry.h"
18 #include "llvm/Support/TargetSelect.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 
22 #include "llvm/MC/MCInstPrinter.h"
23 
24 #ifdef __linux__
25 #include <sys/mman.h>
26 #include <sys/syscall.h>
27 #endif // __linux__
28 
29 namespace llvm {
30 
31 bool operator==(const MCOperand &a, const MCOperand &b) {
32   if (a.isImm() && b.isImm())
33     return a.getImm() == b.getImm();
34   if (a.isReg() && b.isReg())
35     return a.getReg() == b.getReg();
36   return false;
37 }
38 
39 bool operator==(const MCInst &a, const MCInst &b) {
40   if (a.getOpcode() != b.getOpcode())
41     return false;
42   if (a.getNumOperands() != b.getNumOperands())
43     return false;
44   for (unsigned I = 0; I < a.getNumOperands(); ++I) {
45     if (!(a.getOperand(I) == b.getOperand(I)))
46       return false;
47   }
48   return true;
49 }
50 
51 } // namespace llvm
52 
53 namespace llvm {
54 namespace exegesis {
55 
56 void InitializeX86ExegesisTarget();
57 
58 namespace {
59 
60 using testing::AllOf;
61 using testing::ElementsAre;
62 using testing::ElementsAreArray;
63 using testing::Eq;
64 using testing::IsEmpty;
65 using testing::Matcher;
66 using testing::Property;
67 
68 Matcher<MCOperand> IsImm(int64_t Value) {
69   return AllOf(Property(&MCOperand::isImm, Eq(true)),
70                Property(&MCOperand::getImm, Eq(Value)));
71 }
72 
73 Matcher<MCOperand> IsReg(unsigned Reg) {
74   return AllOf(Property(&MCOperand::isReg, Eq(true)),
75                Property(&MCOperand::getReg, Eq(Reg)));
76 }
77 
78 Matcher<MCInst> OpcodeIs(unsigned Opcode) {
79   return Property(&MCInst::getOpcode, Eq(Opcode));
80 }
81 
82 Matcher<MCInst> IsMovImmediate(unsigned Opcode, int64_t Reg, int64_t Value) {
83   return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg), IsImm(Value)));
84 }
85 
86 #ifdef __linux__
87 Matcher<MCInst> IsMovRegToReg(unsigned Opcode, int64_t Reg1, int64_t Reg2) {
88   return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg1), IsReg(Reg2)));
89 }
90 #endif
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,
246        SetRegToVR128ValueHighXMM_Use_VMOVDQU32Z128rm) {
247   EXPECT_THAT(
248       setRegTo(X86::XMM16, APInt(128, "11112222333344445555666677778888", 16)),
249       ElementsAre(IsStackAllocate(16),
250                   IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0),
251                   IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4),
252                   IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8),
253                   IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12),
254                   IsMovValueFromStack(X86::VMOVDQU32Z128rm, X86::XMM16),
255                   IsStackDeallocate(16)));
256 }
257 
258 TEST_F(X86Core2Avx512TargetTest, SetRegToVR128ValueLowXMM_Use_VMOVDQUrm) {
259   EXPECT_THAT(
260       setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)),
261       ElementsAre(IsStackAllocate(16),
262                   IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0),
263                   IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4),
264                   IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8),
265                   IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12),
266                   IsMovValueFromStack(X86::VMOVDQUrm, X86::XMM0),
267                   IsStackDeallocate(16)));
268 }
269 
270 TEST_F(X86Core2AvxTargetTest, SetRegToVR256Value_Use_VMOVDQUYrm) {
271   const char ValueStr[] =
272       "1111111122222222333333334444444455555555666666667777777788888888";
273   EXPECT_THAT(
274       setRegTo(X86::YMM0, APInt(256, ValueStr, 16)),
275       ElementsAreArray({IsStackAllocate(32),
276                         IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0),
277                         IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4),
278                         IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8),
279                         IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12),
280                         IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16),
281                         IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20),
282                         IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24),
283                         IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28),
284                         IsMovValueFromStack(X86::VMOVDQUYrm, X86::YMM0),
285                         IsStackDeallocate(32)}));
286 }
287 
288 TEST_F(X86Core2Avx512TargetTest,
289        SetRegToVR256ValueHighYMM_Use_VMOVDQU32Z256rm) {
290   const char ValueStr[] =
291       "1111111122222222333333334444444455555555666666667777777788888888";
292   EXPECT_THAT(
293       setRegTo(X86::YMM16, APInt(256, ValueStr, 16)),
294       ElementsAreArray({IsStackAllocate(32),
295                         IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0),
296                         IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4),
297                         IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8),
298                         IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12),
299                         IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16),
300                         IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20),
301                         IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24),
302                         IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28),
303                         IsMovValueFromStack(X86::VMOVDQU32Z256rm, X86::YMM16),
304                         IsStackDeallocate(32)}));
305 }
306 
307 TEST_F(X86Core2Avx512TargetTest, SetRegToVR256ValueLowYMM_Use_VMOVDQUYrm) {
308   const char ValueStr[] =
309       "1111111122222222333333334444444455555555666666667777777788888888";
310   EXPECT_THAT(
311       setRegTo(X86::YMM0, APInt(256, ValueStr, 16)),
312       ElementsAreArray({IsStackAllocate(32),
313                         IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0),
314                         IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4),
315                         IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8),
316                         IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12),
317                         IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16),
318                         IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20),
319                         IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24),
320                         IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28),
321                         IsMovValueFromStack(X86::VMOVDQUYrm, X86::YMM0),
322                         IsStackDeallocate(32)}));
323 }
324 
325 TEST_F(X86Core2Avx512TargetTest, SetRegToVR512Value) {
326   const char ValueStr[] =
327       "1111111122222222333333334444444455555555666666667777777788888888"
328       "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000";
329   EXPECT_THAT(
330       setRegTo(X86::ZMM0, APInt(512, ValueStr, 16)),
331       ElementsAreArray({IsStackAllocate(64),
332                         IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 0),
333                         IsMovValueToStack(X86::MOV32mi, 0xFFFFFFFFUL, 4),
334                         IsMovValueToStack(X86::MOV32mi, 0xEEEEEEEEUL, 8),
335                         IsMovValueToStack(X86::MOV32mi, 0xDDDDDDDDUL, 12),
336                         IsMovValueToStack(X86::MOV32mi, 0xCCCCCCCCUL, 16),
337                         IsMovValueToStack(X86::MOV32mi, 0xBBBBBBBBUL, 20),
338                         IsMovValueToStack(X86::MOV32mi, 0xAAAAAAAAUL, 24),
339                         IsMovValueToStack(X86::MOV32mi, 0x99999999UL, 28),
340                         IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 32),
341                         IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 36),
342                         IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 40),
343                         IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 44),
344                         IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 48),
345                         IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 52),
346                         IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 56),
347                         IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 60),
348                         IsMovValueFromStack(X86::VMOVDQU32Zrm, X86::ZMM0),
349                         IsStackDeallocate(64)}));
350 }
351 
352 TEST_F(X86Core2Avx512TargetTest, 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(X86Core2Avx512DQTargetTest, 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(2),
369                           IsMovValueToStack(X86::MOV16mi, Value, 0),
370                           IsMovValueFromStack(X86::KMOVWkm, Reg),
371                           IsStackDeallocate(2)));
372 }
373 
374 TEST_F(X86Core2Avx512BWTargetTest, 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(X86Core2Avx512DQBWTargetTest, SetRegToK0_16Bits) {
386   const uint16_t Value = 0xABCDU;
387   const unsigned Reg = X86::K0;
388   const unsigned RegBitWidth = 16;
389   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
390               ElementsAre(IsStackAllocate(RegBitWidth / 8),
391                           IsMovValueToStack(X86::MOV16mi, Value, 0),
392                           IsMovValueFromStack(X86::KMOVWkm, Reg),
393                           IsStackDeallocate(RegBitWidth / 8)));
394 }
395 
396 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_8Bits) {
397   const uint8_t Value = 0xABU;
398   const unsigned Reg = X86::K0;
399   const unsigned RegBitWidth = 8;
400   EXPECT_THAT(
401       setRegTo(Reg, APInt(RegBitWidth, Value)),
402       ElementsAre(IsStackAllocate(2),
403                   IsMovValueToStack(
404                       X86::MOV16mi,
405                       APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0),
406                   IsMovValueFromStack(X86::KMOVWkm, Reg),
407                   IsStackDeallocate(2)));
408 }
409 
410 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_8Bits) {
411   const uint8_t Value = 0xABU;
412   const unsigned Reg = X86::K0;
413   const unsigned RegBitWidth = 8;
414   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
415               ElementsAre(IsStackAllocate(RegBitWidth / 8),
416                           IsMovValueToStack(X86::MOV8mi, Value, 0),
417                           IsMovValueFromStack(X86::KMOVBkm, Reg),
418                           IsStackDeallocate(RegBitWidth / 8)));
419 }
420 
421 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_8Bits) {
422   const uint8_t Value = 0xABU;
423   const unsigned Reg = X86::K0;
424   const unsigned RegBitWidth = 8;
425   EXPECT_THAT(
426       setRegTo(Reg, APInt(RegBitWidth, Value)),
427       ElementsAre(IsStackAllocate(2),
428                   IsMovValueToStack(
429                       X86::MOV16mi,
430                       APInt(RegBitWidth, Value).zext(16).getZExtValue(), 0),
431                   IsMovValueFromStack(X86::KMOVWkm, Reg),
432                   IsStackDeallocate(2)));
433 }
434 
435 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_8Bits) {
436   const uint8_t Value = 0xABU;
437   const unsigned Reg = X86::K0;
438   const unsigned RegBitWidth = 8;
439   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
440               ElementsAre(IsStackAllocate(RegBitWidth / 8),
441                           IsMovValueToStack(X86::MOV8mi, Value, 0),
442                           IsMovValueFromStack(X86::KMOVBkm, Reg),
443                           IsStackDeallocate(RegBitWidth / 8)));
444 }
445 
446 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_32Bits) {
447   const uint32_t Value = 0xABCDCABDU;
448   const unsigned Reg = X86::K0;
449   const unsigned RegBitWidth = 32;
450   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
451 }
452 
453 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_32Bits) {
454   const uint32_t Value = 0xABCDCABDU;
455   const unsigned Reg = X86::K0;
456   const unsigned RegBitWidth = 32;
457   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
458 }
459 
460 TEST_F(X86Core2Avx512BWTargetTest, 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(X86Core2Avx512DQBWTargetTest, SetRegToK0_32Bits) {
472   const uint32_t Value = 0xABCDCABDU;
473   const unsigned Reg = X86::K0;
474   const unsigned RegBitWidth = 32;
475   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
476               ElementsAre(IsStackAllocate(RegBitWidth / 8),
477                           IsMovValueToStack(X86::MOV32mi, Value, 0),
478                           IsMovValueFromStack(X86::KMOVDkm, Reg),
479                           IsStackDeallocate(RegBitWidth / 8)));
480 }
481 
482 TEST_F(X86Core2Avx512TargetTest, SetRegToK0_64Bits) {
483   const uint64_t Value = 0xABCDABCDCABDCABDU;
484   const unsigned Reg = X86::K0;
485   const unsigned RegBitWidth = 64;
486   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
487 }
488 
489 TEST_F(X86Core2Avx512DQTargetTest, SetRegToK0_64Bits) {
490   const uint64_t Value = 0xABCDABCDCABDCABDU;
491   const unsigned Reg = X86::K0;
492   const unsigned RegBitWidth = 64;
493   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)), IsEmpty());
494 }
495 
496 TEST_F(X86Core2Avx512BWTargetTest, SetRegToK0_64Bits) {
497   const uint64_t Value = 0xABCDABCDCABDCABDUL;
498   const unsigned Reg = X86::K0;
499   const unsigned RegBitWidth = 64;
500   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
501               ElementsAre(IsStackAllocate(RegBitWidth / 8),
502                           IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0),
503                           IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4),
504                           IsMovValueFromStack(X86::KMOVQkm, Reg),
505                           IsStackDeallocate(RegBitWidth / 8)));
506 }
507 
508 TEST_F(X86Core2Avx512DQBWTargetTest, SetRegToK0_64Bits) {
509   const uint64_t Value = 0xABCDABCDCABDCABDU;
510   const unsigned Reg = X86::K0;
511   const unsigned RegBitWidth = 64;
512   EXPECT_THAT(setRegTo(Reg, APInt(RegBitWidth, Value)),
513               ElementsAre(IsStackAllocate(RegBitWidth / 8),
514                           IsMovValueToStack(X86::MOV32mi, 0XCABDCABDUL, 0),
515                           IsMovValueToStack(X86::MOV32mi, 0xABCDABCDUL, 4),
516                           IsMovValueFromStack(X86::KMOVQkm, Reg),
517                           IsStackDeallocate(RegBitWidth / 8)));
518 }
519 
520 // Note: We always put 80 bits on the stack independently of the size of the
521 // value. This uses a bit more space but makes the code simpler.
522 
523 TEST_F(X86Core2TargetTest, SetRegToST0_32Bits) {
524   EXPECT_THAT(setRegTo(X86::ST0, APInt(32, 0x11112222ULL)),
525               ElementsAre(IsStackAllocate(10),
526                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
527                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
528                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
529                           OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
530 }
531 
532 TEST_F(X86Core2TargetTest, SetRegToST1_32Bits) {
533   const MCInst CopySt0ToSt1 = MCInstBuilder(X86::ST_Frr).addReg(X86::ST1);
534   EXPECT_THAT(setRegTo(X86::ST1, APInt(32, 0x11112222ULL)),
535               ElementsAre(IsStackAllocate(10),
536                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
537                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
538                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
539                           OpcodeIs(X86::LD_F80m), CopySt0ToSt1,
540                           IsStackDeallocate(10)));
541 }
542 
543 TEST_F(X86Core2TargetTest, SetRegToST0_64Bits) {
544   EXPECT_THAT(setRegTo(X86::ST0, APInt(64, 0x1111222233334444ULL)),
545               ElementsAre(IsStackAllocate(10),
546                           IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0),
547                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4),
548                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
549                           OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
550 }
551 
552 TEST_F(X86Core2TargetTest, SetRegToST0_80Bits) {
553   EXPECT_THAT(setRegTo(X86::ST0, APInt(80, "11112222333344445555", 16)),
554               ElementsAre(IsStackAllocate(10),
555                           IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0),
556                           IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4),
557                           IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8),
558                           OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
559 }
560 
561 TEST_F(X86Core2TargetTest, SetRegToFP0_80Bits) {
562   EXPECT_THAT(setRegTo(X86::FP0, APInt(80, "11112222333344445555", 16)),
563               ElementsAre(IsStackAllocate(10),
564                           IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0),
565                           IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4),
566                           IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8),
567                           OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
568 }
569 
570 TEST_F(X86Core2TargetTest, SetRegToFP1_32Bits) {
571   EXPECT_THAT(setRegTo(X86::FP1, APInt(32, 0x11112222ULL)),
572               ElementsAre(IsStackAllocate(10),
573                           IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
574                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
575                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
576                           OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
577 }
578 
579 TEST_F(X86Core2TargetTest, SetRegToFP1_4Bits) {
580   EXPECT_THAT(setRegTo(X86::FP1, APInt(4, 0x1ULL)),
581               ElementsAre(IsStackAllocate(10),
582                           IsMovValueToStack(X86::MOV32mi, 0x00000001UL, 0),
583                           IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
584                           IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
585                           OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
586 }
587 
588 TEST_F(X86Core2TargetTest, SetRegToDf1) {
589   EXPECT_THAT(setRegTo(X86::DF, APInt(1, 1)), ElementsAre(OpcodeIs(X86::STD)));
590 }
591 
592 TEST_F(X86Core2TargetTest, SetRegToDf0) {
593   EXPECT_THAT(setRegTo(X86::DF, APInt(1, 0)), ElementsAre(OpcodeIs(X86::CLD)));
594 }
595 
596 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_ADD64rm) {
597   const Instruction &I = getInstr(X86::ADD64rm);
598   InstructionTemplate IT(&I);
599   constexpr const int kOffset = 42;
600   State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset);
601   // Memory is operands 2-6.
602   EXPECT_THAT(IT.getValueFor(I.Operands[2]), IsReg(X86::RDI));
603   EXPECT_THAT(IT.getValueFor(I.Operands[3]), IsImm(1));
604   EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(0));
605   EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(kOffset));
606   EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0));
607 }
608 
609 TEST_F(X86Core2Avx512TargetTest, FillMemoryOperands_VGATHERDPSZ128rm) {
610   const Instruction &I = getInstr(X86::VGATHERDPSZ128rm);
611   InstructionTemplate IT(&I);
612   constexpr const int kOffset = 42;
613   State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset);
614   // Memory is operands 4-8.
615   EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(X86::RDI));
616   EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(1));
617   EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0));
618   EXPECT_THAT(IT.getValueFor(I.Operands[7]), IsImm(kOffset));
619   EXPECT_THAT(IT.getValueFor(I.Operands[8]), IsReg(0));
620 }
621 
622 TEST_F(X86Core2TargetTest, AllowAsBackToBack) {
623   EXPECT_TRUE(
624       State.getExegesisTarget().allowAsBackToBack(getInstr(X86::ADD64rr)));
625   EXPECT_FALSE(
626       State.getExegesisTarget().allowAsBackToBack(getInstr(X86::LEA64r)));
627 }
628 
629 #ifdef __linux__
630 TEST_F(X86Core2TargetTest, GenerateLowerMunmapTest) {
631   std::vector<MCInst> GeneratedCode;
632   State.getExegesisTarget().generateLowerMunmap(GeneratedCode);
633   EXPECT_THAT(GeneratedCode,
634               ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0),
635                           OpcodeIs(X86::LEA64r), OpcodeIs(X86::SHR64ri),
636                           OpcodeIs(X86::SHL64ri), OpcodeIs(X86::SUB64ri32),
637                           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap),
638                           OpcodeIs(X86::SYSCALL)));
639 }
640 
641 #ifdef __arm__
642 static constexpr const uintptr_t VAddressSpaceCeiling = 0xC0000000;
643 #else
644 static constexpr const uintptr_t VAddressSpaceCeiling = 0x0000800000000000;
645 #endif
646 
647 TEST_F(X86Core2TargetTest, GenerateUpperMunmapTest) {
648   std::vector<MCInst> GeneratedCode;
649   State.getExegesisTarget().generateUpperMunmap(GeneratedCode);
650   EXPECT_THAT(
651       GeneratedCode,
652       ElementsAreArray({OpcodeIs(X86::LEA64r), OpcodeIs(X86::MOV64rr),
653                         OpcodeIs(X86::ADD64rr), OpcodeIs(X86::SHR64ri),
654                         OpcodeIs(X86::SHL64ri), OpcodeIs(X86::ADD64ri32),
655                         IsMovImmediate(X86::MOV64ri, X86::RSI,
656                                        VAddressSpaceCeiling - getpagesize()),
657                         OpcodeIs(X86::SUB64rr),
658                         IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_munmap),
659                         OpcodeIs(X86::SYSCALL)}));
660 }
661 
662 TEST_F(X86Core2TargetTest, GenerateExitSyscallTest) {
663   EXPECT_THAT(State.getExegesisTarget().generateExitSyscall(127),
664               ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 127),
665                           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_exit),
666                           OpcodeIs(X86::SYSCALL)));
667 }
668 
669 TEST_F(X86Core2TargetTest, GenerateMmapTest) {
670   EXPECT_THAT(State.getExegesisTarget().generateMmap(0x1000, 4096, 0x2000),
671               ElementsAre(IsMovImmediate(X86::MOV64ri, X86::RDI, 0x1000),
672                           IsMovImmediate(X86::MOV64ri, X86::RSI, 4096),
673                           IsMovImmediate(X86::MOV64ri, X86::RDX,
674                                          PROT_READ | PROT_WRITE),
675                           IsMovImmediate(X86::MOV64ri, X86::R10,
676                                          MAP_SHARED | MAP_FIXED_NOREPLACE),
677                           IsMovImmediate(X86::MOV64ri, X86::R8, 0x2000),
678                           OpcodeIs(X86::MOV32rm),
679                           IsMovImmediate(X86::MOV64ri, X86::R9, 0),
680                           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap),
681                           OpcodeIs(X86::SYSCALL)));
682 }
683 
684 TEST_F(X86Core2TargetTest, GenerateMmapAuxMemTest) {
685   std::vector<MCInst> GeneratedCode;
686   State.getExegesisTarget().generateMmapAuxMem(GeneratedCode);
687   EXPECT_THAT(
688       GeneratedCode,
689       ElementsAre(
690           IsMovImmediate(
691               X86::MOV64ri, X86::RDI,
692               State.getExegesisTarget().getAuxiliaryMemoryStartAddress()),
693           IsMovImmediate(X86::MOV64ri, X86::RSI,
694                          SubprocessMemory::AuxiliaryMemorySize),
695           IsMovImmediate(X86::MOV64ri, X86::RDX, PROT_READ | PROT_WRITE),
696           IsMovImmediate(X86::MOV64ri, X86::R10,
697                          MAP_SHARED | MAP_FIXED_NOREPLACE),
698           OpcodeIs(X86::MOV64rr), IsMovImmediate(X86::MOV64ri, X86::R9, 0),
699           IsMovImmediate(X86::MOV64ri, X86::RAX, SYS_mmap),
700           OpcodeIs(X86::SYSCALL)));
701 }
702 
703 TEST_F(X86Core2TargetTest, MoveArgumentRegistersTest) {
704   std::vector<MCInst> GeneratedCode;
705   State.getExegesisTarget().moveArgumentRegisters(GeneratedCode);
706   EXPECT_THAT(GeneratedCode,
707               ElementsAre(IsMovRegToReg(X86::MOV64rr, X86::R12, X86::RDI),
708                           IsMovRegToReg(X86::MOV64rr, X86::R13, X86::RSI)));
709 }
710 #endif // __linux__
711 
712 } // namespace
713 } // namespace exegesis
714 } // namespace llvm
715