[yaml2obj/obj2yaml] - Add support for .stack_sizes sections.
[llvm-complete.git] / unittests / tools / llvm-exegesis / X86 / TargetTest.cpp
blob344ec6027d2fbe97937de88bf3a1f2a892341751
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 //===----------------------------------------------------------------------===//
9 #include "Target.h"
11 #include <cassert>
12 #include <memory>
14 #include "MCTargetDesc/X86MCTargetDesc.h"
15 #include "llvm/Support/TargetRegistry.h"
16 #include "llvm/Support/TargetSelect.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
20 #include "llvm/MC/MCInstPrinter.h"
22 namespace llvm {
24 bool operator==(const MCOperand &a, const MCOperand &b) {
25 if (a.isImm() && b.isImm())
26 return a.getImm() == b.getImm();
27 if (a.isReg() && b.isReg())
28 return a.getReg() == b.getReg();
29 return false;
32 bool operator==(const MCInst &a, const MCInst &b) {
33 if (a.getOpcode() != b.getOpcode())
34 return false;
35 if (a.getNumOperands() != b.getNumOperands())
36 return false;
37 for (unsigned I = 0; I < a.getNumOperands(); ++I) {
38 if (!(a.getOperand(I) == b.getOperand(I)))
39 return false;
41 return true;
44 } // namespace llvm
46 namespace llvm {
47 namespace exegesis {
49 void InitializeX86ExegesisTarget();
51 namespace {
53 using testing::AllOf;
54 using testing::ElementsAre;
55 using testing::ElementsAreArray;
56 using testing::Eq;
57 using testing::Gt;
58 using testing::Matcher;
59 using testing::NotNull;
60 using testing::Property;
61 using testing::SizeIs;
63 using llvm::APInt;
64 using llvm::MCInst;
65 using llvm::MCInstBuilder;
66 using llvm::MCOperand;
68 Matcher<MCOperand> IsImm(int64_t Value) {
69 return AllOf(Property(&MCOperand::isImm, Eq(true)),
70 Property(&MCOperand::getImm, Eq(Value)));
73 Matcher<MCOperand> IsReg(unsigned Reg) {
74 return AllOf(Property(&MCOperand::isReg, Eq(true)),
75 Property(&MCOperand::getReg, Eq(Reg)));
78 Matcher<MCInst> OpcodeIs(unsigned Opcode) {
79 return Property(&MCInst::getOpcode, Eq(Opcode));
82 Matcher<MCInst> IsMovImmediate(unsigned Opcode, int64_t Reg, int64_t Value) {
83 return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg), IsImm(Value)));
86 Matcher<MCInst> IsMovValueToStack(unsigned Opcode, int64_t Value,
87 size_t Offset) {
88 return AllOf(OpcodeIs(Opcode),
89 ElementsAre(IsReg(llvm::X86::RSP), IsImm(1), IsReg(0),
90 IsImm(Offset), IsReg(0), IsImm(Value)));
93 Matcher<MCInst> IsMovValueFromStack(unsigned Opcode, unsigned Reg) {
94 return AllOf(OpcodeIs(Opcode),
95 ElementsAre(IsReg(Reg), IsReg(llvm::X86::RSP), IsImm(1),
96 IsReg(0), IsImm(0), IsReg(0)));
99 Matcher<MCInst> IsStackAllocate(unsigned Size) {
100 return AllOf(
101 OpcodeIs(llvm::X86::SUB64ri8),
102 ElementsAre(IsReg(llvm::X86::RSP), IsReg(llvm::X86::RSP), IsImm(Size)));
105 Matcher<MCInst> IsStackDeallocate(unsigned Size) {
106 return AllOf(
107 OpcodeIs(llvm::X86::ADD64ri8),
108 ElementsAre(IsReg(llvm::X86::RSP), IsReg(llvm::X86::RSP), IsImm(Size)));
111 constexpr const char kTriple[] = "x86_64-unknown-linux";
113 class X86TargetTest : public ::testing::Test {
114 protected:
115 X86TargetTest(const char *Features) : State(kTriple, "core2", Features) {}
117 static void SetUpTestCase() {
118 LLVMInitializeX86TargetInfo();
119 LLVMInitializeX86Target();
120 LLVMInitializeX86TargetMC();
121 InitializeX86ExegesisTarget();
124 std::vector<MCInst> setRegTo(unsigned Reg, const APInt &Value) {
125 return State.getExegesisTarget().setRegTo(State.getSubtargetInfo(), Reg,
126 Value);
129 LLVMState State;
132 class Core2TargetTest : public X86TargetTest {
133 public:
134 Core2TargetTest() : X86TargetTest("") {}
137 class Core2AvxTargetTest : public X86TargetTest {
138 public:
139 Core2AvxTargetTest() : X86TargetTest("+avx") {}
142 class Core2Avx512TargetTest : public X86TargetTest {
143 public:
144 Core2Avx512TargetTest() : X86TargetTest("+avx512vl") {}
147 TEST_F(Core2TargetTest, NoHighByteRegs) {
148 EXPECT_TRUE(State.getRATC().reservedRegisters().test(X86::AH));
151 TEST_F(Core2TargetTest, SetFlags) {
152 const unsigned Reg = llvm::X86::EFLAGS;
153 EXPECT_THAT(
154 setRegTo(Reg, APInt(64, 0x1111222233334444ULL)),
155 ElementsAre(IsStackAllocate(8),
156 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
157 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
158 OpcodeIs(llvm::X86::POPF64)));
161 TEST_F(Core2TargetTest, SetRegToGR8Value) {
162 const uint8_t Value = 0xFFU;
163 const unsigned Reg = llvm::X86::AL;
164 EXPECT_THAT(setRegTo(Reg, APInt(8, Value)),
165 ElementsAre(IsMovImmediate(llvm::X86::MOV8ri, Reg, Value)));
168 TEST_F(Core2TargetTest, SetRegToGR16Value) {
169 const uint16_t Value = 0xFFFFU;
170 const unsigned Reg = llvm::X86::BX;
171 EXPECT_THAT(setRegTo(Reg, APInt(16, Value)),
172 ElementsAre(IsMovImmediate(llvm::X86::MOV16ri, Reg, Value)));
175 TEST_F(Core2TargetTest, SetRegToGR32Value) {
176 const uint32_t Value = 0x7FFFFU;
177 const unsigned Reg = llvm::X86::ECX;
178 EXPECT_THAT(setRegTo(Reg, APInt(32, Value)),
179 ElementsAre(IsMovImmediate(llvm::X86::MOV32ri, Reg, Value)));
182 TEST_F(Core2TargetTest, SetRegToGR64Value) {
183 const uint64_t Value = 0x7FFFFFFFFFFFFFFFULL;
184 const unsigned Reg = llvm::X86::RDX;
185 EXPECT_THAT(setRegTo(Reg, APInt(64, Value)),
186 ElementsAre(IsMovImmediate(llvm::X86::MOV64ri, Reg, Value)));
189 TEST_F(Core2TargetTest, SetRegToVR64Value) {
190 EXPECT_THAT(
191 setRegTo(llvm::X86::MM0, APInt(64, 0x1111222233334444ULL)),
192 ElementsAre(IsStackAllocate(8),
193 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
194 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
195 IsMovValueFromStack(llvm::X86::MMX_MOVQ64rm, llvm::X86::MM0),
196 IsStackDeallocate(8)));
199 TEST_F(Core2TargetTest, SetRegToVR128Value_Use_MOVDQUrm) {
200 EXPECT_THAT(
201 setRegTo(llvm::X86::XMM0,
202 APInt(128, "11112222333344445555666677778888", 16)),
203 ElementsAre(IsStackAllocate(16),
204 IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
205 IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
206 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
207 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
208 IsMovValueFromStack(llvm::X86::MOVDQUrm, llvm::X86::XMM0),
209 IsStackDeallocate(16)));
212 TEST_F(Core2AvxTargetTest, SetRegToVR128Value_Use_VMOVDQUrm) {
213 EXPECT_THAT(
214 setRegTo(llvm::X86::XMM0,
215 APInt(128, "11112222333344445555666677778888", 16)),
216 ElementsAre(IsStackAllocate(16),
217 IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
218 IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
219 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
220 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
221 IsMovValueFromStack(llvm::X86::VMOVDQUrm, llvm::X86::XMM0),
222 IsStackDeallocate(16)));
225 TEST_F(Core2Avx512TargetTest, SetRegToVR128Value_Use_VMOVDQU32Z128rm) {
226 EXPECT_THAT(
227 setRegTo(llvm::X86::XMM0,
228 APInt(128, "11112222333344445555666677778888", 16)),
229 ElementsAre(
230 IsStackAllocate(16),
231 IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
232 IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
233 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
234 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
235 IsMovValueFromStack(llvm::X86::VMOVDQU32Z128rm, llvm::X86::XMM0),
236 IsStackDeallocate(16)));
239 TEST_F(Core2AvxTargetTest, SetRegToVR256Value_Use_VMOVDQUYrm) {
240 const char ValueStr[] =
241 "1111111122222222333333334444444455555555666666667777777788888888";
242 EXPECT_THAT(setRegTo(llvm::X86::YMM0, APInt(256, ValueStr, 16)),
243 ElementsAreArray(
244 {IsStackAllocate(32),
245 IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 0),
246 IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 4),
247 IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 8),
248 IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 12),
249 IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 16),
250 IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 20),
251 IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 24),
252 IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 28),
253 IsMovValueFromStack(llvm::X86::VMOVDQUYrm, llvm::X86::YMM0),
254 IsStackDeallocate(32)}));
257 TEST_F(Core2Avx512TargetTest, SetRegToVR256Value_Use_VMOVDQU32Z256rm) {
258 const char ValueStr[] =
259 "1111111122222222333333334444444455555555666666667777777788888888";
260 EXPECT_THAT(
261 setRegTo(llvm::X86::YMM0, APInt(256, ValueStr, 16)),
262 ElementsAreArray(
263 {IsStackAllocate(32),
264 IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 0),
265 IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 4),
266 IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 8),
267 IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 12),
268 IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 16),
269 IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 20),
270 IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 24),
271 IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 28),
272 IsMovValueFromStack(llvm::X86::VMOVDQU32Z256rm, llvm::X86::YMM0),
273 IsStackDeallocate(32)}));
276 TEST_F(Core2Avx512TargetTest, SetRegToVR512Value) {
277 const char ValueStr[] =
278 "1111111122222222333333334444444455555555666666667777777788888888"
279 "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000";
280 EXPECT_THAT(
281 setRegTo(llvm::X86::ZMM0, APInt(512, ValueStr, 16)),
282 ElementsAreArray(
283 {IsStackAllocate(64),
284 IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 0),
285 IsMovValueToStack(llvm::X86::MOV32mi, 0xFFFFFFFFUL, 4),
286 IsMovValueToStack(llvm::X86::MOV32mi, 0xEEEEEEEEUL, 8),
287 IsMovValueToStack(llvm::X86::MOV32mi, 0xDDDDDDDDUL, 12),
288 IsMovValueToStack(llvm::X86::MOV32mi, 0xCCCCCCCCUL, 16),
289 IsMovValueToStack(llvm::X86::MOV32mi, 0xBBBBBBBBUL, 20),
290 IsMovValueToStack(llvm::X86::MOV32mi, 0xAAAAAAAAUL, 24),
291 IsMovValueToStack(llvm::X86::MOV32mi, 0x99999999UL, 28),
292 IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 32),
293 IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 36),
294 IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 40),
295 IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 44),
296 IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 48),
297 IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 52),
298 IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 56),
299 IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 60),
300 IsMovValueFromStack(llvm::X86::VMOVDQU32Zrm, llvm::X86::ZMM0),
301 IsStackDeallocate(64)}));
304 // Note: We always put 80 bits on the stack independently of the size of the
305 // value. This uses a bit more space but makes the code simpler.
307 TEST_F(Core2TargetTest, SetRegToST0_32Bits) {
308 EXPECT_THAT(
309 setRegTo(llvm::X86::ST0, APInt(32, 0x11112222ULL)),
310 ElementsAre(IsStackAllocate(10),
311 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0),
312 IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 4),
313 IsMovValueToStack(llvm::X86::MOV16mi, 0x0000UL, 8),
314 OpcodeIs(llvm::X86::LD_F80m), IsStackDeallocate(10)));
317 TEST_F(Core2TargetTest, SetRegToST1_32Bits) {
318 const MCInst CopySt0ToSt1 =
319 llvm::MCInstBuilder(llvm::X86::ST_Frr).addReg(llvm::X86::ST1);
320 EXPECT_THAT(
321 setRegTo(llvm::X86::ST1, APInt(32, 0x11112222ULL)),
322 ElementsAre(IsStackAllocate(10),
323 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0),
324 IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 4),
325 IsMovValueToStack(llvm::X86::MOV16mi, 0x0000UL, 8),
326 OpcodeIs(llvm::X86::LD_F80m), CopySt0ToSt1,
327 IsStackDeallocate(10)));
330 TEST_F(Core2TargetTest, SetRegToST0_64Bits) {
331 EXPECT_THAT(
332 setRegTo(llvm::X86::ST0, APInt(64, 0x1111222233334444ULL)),
333 ElementsAre(IsStackAllocate(10),
334 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
335 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
336 IsMovValueToStack(llvm::X86::MOV16mi, 0x0000UL, 8),
337 OpcodeIs(llvm::X86::LD_F80m), IsStackDeallocate(10)));
340 TEST_F(Core2TargetTest, SetRegToST0_80Bits) {
341 EXPECT_THAT(
342 setRegTo(llvm::X86::ST0, APInt(80, "11112222333344445555", 16)),
343 ElementsAre(IsStackAllocate(10),
344 IsMovValueToStack(llvm::X86::MOV32mi, 0x44445555UL, 0),
345 IsMovValueToStack(llvm::X86::MOV32mi, 0x22223333UL, 4),
346 IsMovValueToStack(llvm::X86::MOV16mi, 0x1111UL, 8),
347 OpcodeIs(llvm::X86::LD_F80m), IsStackDeallocate(10)));
350 TEST_F(Core2TargetTest, SetRegToFP0_80Bits) {
351 EXPECT_THAT(
352 setRegTo(llvm::X86::FP0, APInt(80, "11112222333344445555", 16)),
353 ElementsAre(IsStackAllocate(10),
354 IsMovValueToStack(llvm::X86::MOV32mi, 0x44445555UL, 0),
355 IsMovValueToStack(llvm::X86::MOV32mi, 0x22223333UL, 4),
356 IsMovValueToStack(llvm::X86::MOV16mi, 0x1111UL, 8),
357 OpcodeIs(llvm::X86::LD_Fp80m), IsStackDeallocate(10)));
360 TEST_F(Core2TargetTest, SetRegToFP1_32Bits) {
361 EXPECT_THAT(
362 setRegTo(llvm::X86::FP1, APInt(32, 0x11112222ULL)),
363 ElementsAre(IsStackAllocate(10),
364 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0),
365 IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 4),
366 IsMovValueToStack(llvm::X86::MOV16mi, 0x0000UL, 8),
367 OpcodeIs(llvm::X86::LD_Fp80m), IsStackDeallocate(10)));
370 TEST_F(Core2TargetTest, SetRegToFP1_4Bits) {
371 EXPECT_THAT(
372 setRegTo(llvm::X86::FP1, APInt(4, 0x1ULL)),
373 ElementsAre(IsStackAllocate(10),
374 IsMovValueToStack(llvm::X86::MOV32mi, 0x00000001UL, 0),
375 IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 4),
376 IsMovValueToStack(llvm::X86::MOV16mi, 0x0000UL, 8),
377 OpcodeIs(llvm::X86::LD_Fp80m), IsStackDeallocate(10)));
380 TEST_F(Core2Avx512TargetTest, FillMemoryOperands_ADD64rm) {
381 Instruction I(State.getInstrInfo(), State.getRATC(), X86::ADD64rm);
382 InstructionTemplate IT(I);
383 constexpr const int kOffset = 42;
384 State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset);
385 // Memory is operands 2-6.
386 EXPECT_THAT(IT.getValueFor(I.Operands[2]), IsReg(X86::RDI));
387 EXPECT_THAT(IT.getValueFor(I.Operands[3]), IsImm(1));
388 EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(0));
389 EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(kOffset));
390 EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0));
393 TEST_F(Core2Avx512TargetTest, FillMemoryOperands_VGATHERDPSZ128rm) {
394 Instruction I(State.getInstrInfo(), State.getRATC(), X86::VGATHERDPSZ128rm);
395 InstructionTemplate IT(I);
396 constexpr const int kOffset = 42;
397 State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset);
398 // Memory is operands 4-8.
399 EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(X86::RDI));
400 EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(1));
401 EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0));
402 EXPECT_THAT(IT.getValueFor(I.Operands[7]), IsImm(kOffset));
403 EXPECT_THAT(IT.getValueFor(I.Operands[8]), IsReg(0));
406 } // namespace
407 } // namespace exegesis
408 } // namespace llvm