[Alignment] Migrate Attribute::getWith(Stack)Alignment
[llvm-core.git] / unittests / tools / llvm-exegesis / X86 / TargetTest.cpp
blobe15b7f2dbba359c9a3d1e243678bf1fb4189a805
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 Matcher<MCOperand> IsImm(int64_t Value) {
64 return AllOf(Property(&MCOperand::isImm, Eq(true)),
65 Property(&MCOperand::getImm, Eq(Value)));
68 Matcher<MCOperand> IsReg(unsigned Reg) {
69 return AllOf(Property(&MCOperand::isReg, Eq(true)),
70 Property(&MCOperand::getReg, Eq(Reg)));
73 Matcher<MCInst> OpcodeIs(unsigned Opcode) {
74 return Property(&MCInst::getOpcode, Eq(Opcode));
77 Matcher<MCInst> IsMovImmediate(unsigned Opcode, int64_t Reg, int64_t Value) {
78 return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg), IsImm(Value)));
81 Matcher<MCInst> IsMovValueToStack(unsigned Opcode, int64_t Value,
82 size_t Offset) {
83 return AllOf(OpcodeIs(Opcode),
84 ElementsAre(IsReg(X86::RSP), IsImm(1), IsReg(0), IsImm(Offset),
85 IsReg(0), IsImm(Value)));
88 Matcher<MCInst> IsMovValueFromStack(unsigned Opcode, unsigned Reg) {
89 return AllOf(OpcodeIs(Opcode),
90 ElementsAre(IsReg(Reg), IsReg(X86::RSP), IsImm(1), IsReg(0),
91 IsImm(0), IsReg(0)));
94 Matcher<MCInst> IsStackAllocate(unsigned Size) {
95 return AllOf(OpcodeIs(X86::SUB64ri8),
96 ElementsAre(IsReg(X86::RSP), IsReg(X86::RSP), IsImm(Size)));
99 Matcher<MCInst> IsStackDeallocate(unsigned Size) {
100 return AllOf(OpcodeIs(X86::ADD64ri8),
101 ElementsAre(IsReg(X86::RSP), IsReg(X86::RSP), IsImm(Size)));
104 constexpr const char kTriple[] = "x86_64-unknown-linux";
106 class X86TargetTest : public ::testing::Test {
107 protected:
108 X86TargetTest(const char *Features) : State(kTriple, "core2", Features) {}
110 static void SetUpTestCase() {
111 LLVMInitializeX86TargetInfo();
112 LLVMInitializeX86Target();
113 LLVMInitializeX86TargetMC();
114 InitializeX86ExegesisTarget();
117 std::vector<MCInst> setRegTo(unsigned Reg, const APInt &Value) {
118 return State.getExegesisTarget().setRegTo(State.getSubtargetInfo(), Reg,
119 Value);
122 LLVMState State;
125 class Core2TargetTest : public X86TargetTest {
126 public:
127 Core2TargetTest() : X86TargetTest("") {}
130 class Core2AvxTargetTest : public X86TargetTest {
131 public:
132 Core2AvxTargetTest() : X86TargetTest("+avx") {}
135 class Core2Avx512TargetTest : public X86TargetTest {
136 public:
137 Core2Avx512TargetTest() : X86TargetTest("+avx512vl") {}
140 TEST_F(Core2TargetTest, NoHighByteRegs) {
141 EXPECT_TRUE(State.getRATC().reservedRegisters().test(X86::AH));
144 TEST_F(Core2TargetTest, SetFlags) {
145 const unsigned Reg = X86::EFLAGS;
146 EXPECT_THAT(setRegTo(Reg, APInt(64, 0x1111222233334444ULL)),
147 ElementsAre(IsStackAllocate(8),
148 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0),
149 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4),
150 OpcodeIs(X86::POPF64)));
153 TEST_F(Core2TargetTest, SetRegToGR8Value) {
154 const uint8_t Value = 0xFFU;
155 const unsigned Reg = X86::AL;
156 EXPECT_THAT(setRegTo(Reg, APInt(8, Value)),
157 ElementsAre(IsMovImmediate(X86::MOV8ri, Reg, Value)));
160 TEST_F(Core2TargetTest, SetRegToGR16Value) {
161 const uint16_t Value = 0xFFFFU;
162 const unsigned Reg = X86::BX;
163 EXPECT_THAT(setRegTo(Reg, APInt(16, Value)),
164 ElementsAre(IsMovImmediate(X86::MOV16ri, Reg, Value)));
167 TEST_F(Core2TargetTest, SetRegToGR32Value) {
168 const uint32_t Value = 0x7FFFFU;
169 const unsigned Reg = X86::ECX;
170 EXPECT_THAT(setRegTo(Reg, APInt(32, Value)),
171 ElementsAre(IsMovImmediate(X86::MOV32ri, Reg, Value)));
174 TEST_F(Core2TargetTest, SetRegToGR64Value) {
175 const uint64_t Value = 0x7FFFFFFFFFFFFFFFULL;
176 const unsigned Reg = X86::RDX;
177 EXPECT_THAT(setRegTo(Reg, APInt(64, Value)),
178 ElementsAre(IsMovImmediate(X86::MOV64ri, Reg, Value)));
181 TEST_F(Core2TargetTest, SetRegToVR64Value) {
182 EXPECT_THAT(setRegTo(X86::MM0, APInt(64, 0x1111222233334444ULL)),
183 ElementsAre(IsStackAllocate(8),
184 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0),
185 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4),
186 IsMovValueFromStack(X86::MMX_MOVQ64rm, X86::MM0),
187 IsStackDeallocate(8)));
190 TEST_F(Core2TargetTest, SetRegToVR128Value_Use_MOVDQUrm) {
191 EXPECT_THAT(
192 setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)),
193 ElementsAre(IsStackAllocate(16),
194 IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0),
195 IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4),
196 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8),
197 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12),
198 IsMovValueFromStack(X86::MOVDQUrm, X86::XMM0),
199 IsStackDeallocate(16)));
202 TEST_F(Core2AvxTargetTest, SetRegToVR128Value_Use_VMOVDQUrm) {
203 EXPECT_THAT(
204 setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)),
205 ElementsAre(IsStackAllocate(16),
206 IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0),
207 IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4),
208 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8),
209 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12),
210 IsMovValueFromStack(X86::VMOVDQUrm, X86::XMM0),
211 IsStackDeallocate(16)));
214 TEST_F(Core2Avx512TargetTest, SetRegToVR128Value_Use_VMOVDQU32Z128rm) {
215 EXPECT_THAT(
216 setRegTo(X86::XMM0, APInt(128, "11112222333344445555666677778888", 16)),
217 ElementsAre(IsStackAllocate(16),
218 IsMovValueToStack(X86::MOV32mi, 0x77778888UL, 0),
219 IsMovValueToStack(X86::MOV32mi, 0x55556666UL, 4),
220 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 8),
221 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 12),
222 IsMovValueFromStack(X86::VMOVDQU32Z128rm, X86::XMM0),
223 IsStackDeallocate(16)));
226 TEST_F(Core2AvxTargetTest, SetRegToVR256Value_Use_VMOVDQUYrm) {
227 const char ValueStr[] =
228 "1111111122222222333333334444444455555555666666667777777788888888";
229 EXPECT_THAT(
230 setRegTo(X86::YMM0, APInt(256, ValueStr, 16)),
231 ElementsAreArray({IsStackAllocate(32),
232 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0),
233 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4),
234 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8),
235 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12),
236 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16),
237 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20),
238 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24),
239 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28),
240 IsMovValueFromStack(X86::VMOVDQUYrm, X86::YMM0),
241 IsStackDeallocate(32)}));
244 TEST_F(Core2Avx512TargetTest, SetRegToVR256Value_Use_VMOVDQU32Z256rm) {
245 const char ValueStr[] =
246 "1111111122222222333333334444444455555555666666667777777788888888";
247 EXPECT_THAT(
248 setRegTo(X86::YMM0, APInt(256, ValueStr, 16)),
249 ElementsAreArray({IsStackAllocate(32),
250 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 0),
251 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 4),
252 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 8),
253 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 12),
254 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 16),
255 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 20),
256 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 24),
257 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 28),
258 IsMovValueFromStack(X86::VMOVDQU32Z256rm, X86::YMM0),
259 IsStackDeallocate(32)}));
262 TEST_F(Core2Avx512TargetTest, SetRegToVR512Value) {
263 const char ValueStr[] =
264 "1111111122222222333333334444444455555555666666667777777788888888"
265 "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000";
266 EXPECT_THAT(
267 setRegTo(X86::ZMM0, APInt(512, ValueStr, 16)),
268 ElementsAreArray({IsStackAllocate(64),
269 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 0),
270 IsMovValueToStack(X86::MOV32mi, 0xFFFFFFFFUL, 4),
271 IsMovValueToStack(X86::MOV32mi, 0xEEEEEEEEUL, 8),
272 IsMovValueToStack(X86::MOV32mi, 0xDDDDDDDDUL, 12),
273 IsMovValueToStack(X86::MOV32mi, 0xCCCCCCCCUL, 16),
274 IsMovValueToStack(X86::MOV32mi, 0xBBBBBBBBUL, 20),
275 IsMovValueToStack(X86::MOV32mi, 0xAAAAAAAAUL, 24),
276 IsMovValueToStack(X86::MOV32mi, 0x99999999UL, 28),
277 IsMovValueToStack(X86::MOV32mi, 0x88888888UL, 32),
278 IsMovValueToStack(X86::MOV32mi, 0x77777777UL, 36),
279 IsMovValueToStack(X86::MOV32mi, 0x66666666UL, 40),
280 IsMovValueToStack(X86::MOV32mi, 0x55555555UL, 44),
281 IsMovValueToStack(X86::MOV32mi, 0x44444444UL, 48),
282 IsMovValueToStack(X86::MOV32mi, 0x33333333UL, 52),
283 IsMovValueToStack(X86::MOV32mi, 0x22222222UL, 56),
284 IsMovValueToStack(X86::MOV32mi, 0x11111111UL, 60),
285 IsMovValueFromStack(X86::VMOVDQU32Zrm, X86::ZMM0),
286 IsStackDeallocate(64)}));
289 // Note: We always put 80 bits on the stack independently of the size of the
290 // value. This uses a bit more space but makes the code simpler.
292 TEST_F(Core2TargetTest, SetRegToST0_32Bits) {
293 EXPECT_THAT(setRegTo(X86::ST0, APInt(32, 0x11112222ULL)),
294 ElementsAre(IsStackAllocate(10),
295 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
296 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
297 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
298 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
301 TEST_F(Core2TargetTest, SetRegToST1_32Bits) {
302 const MCInst CopySt0ToSt1 = MCInstBuilder(X86::ST_Frr).addReg(X86::ST1);
303 EXPECT_THAT(setRegTo(X86::ST1, APInt(32, 0x11112222ULL)),
304 ElementsAre(IsStackAllocate(10),
305 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
306 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
307 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
308 OpcodeIs(X86::LD_F80m), CopySt0ToSt1,
309 IsStackDeallocate(10)));
312 TEST_F(Core2TargetTest, SetRegToST0_64Bits) {
313 EXPECT_THAT(setRegTo(X86::ST0, APInt(64, 0x1111222233334444ULL)),
314 ElementsAre(IsStackAllocate(10),
315 IsMovValueToStack(X86::MOV32mi, 0x33334444UL, 0),
316 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 4),
317 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
318 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
321 TEST_F(Core2TargetTest, SetRegToST0_80Bits) {
322 EXPECT_THAT(setRegTo(X86::ST0, APInt(80, "11112222333344445555", 16)),
323 ElementsAre(IsStackAllocate(10),
324 IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0),
325 IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4),
326 IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8),
327 OpcodeIs(X86::LD_F80m), IsStackDeallocate(10)));
330 TEST_F(Core2TargetTest, SetRegToFP0_80Bits) {
331 EXPECT_THAT(setRegTo(X86::FP0, APInt(80, "11112222333344445555", 16)),
332 ElementsAre(IsStackAllocate(10),
333 IsMovValueToStack(X86::MOV32mi, 0x44445555UL, 0),
334 IsMovValueToStack(X86::MOV32mi, 0x22223333UL, 4),
335 IsMovValueToStack(X86::MOV16mi, 0x1111UL, 8),
336 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
339 TEST_F(Core2TargetTest, SetRegToFP1_32Bits) {
340 EXPECT_THAT(setRegTo(X86::FP1, APInt(32, 0x11112222ULL)),
341 ElementsAre(IsStackAllocate(10),
342 IsMovValueToStack(X86::MOV32mi, 0x11112222UL, 0),
343 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
344 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
345 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
348 TEST_F(Core2TargetTest, SetRegToFP1_4Bits) {
349 EXPECT_THAT(setRegTo(X86::FP1, APInt(4, 0x1ULL)),
350 ElementsAre(IsStackAllocate(10),
351 IsMovValueToStack(X86::MOV32mi, 0x00000001UL, 0),
352 IsMovValueToStack(X86::MOV32mi, 0x00000000UL, 4),
353 IsMovValueToStack(X86::MOV16mi, 0x0000UL, 8),
354 OpcodeIs(X86::LD_Fp80m), IsStackDeallocate(10)));
357 TEST_F(Core2Avx512TargetTest, FillMemoryOperands_ADD64rm) {
358 Instruction I(State.getInstrInfo(), State.getRATC(), X86::ADD64rm);
359 InstructionTemplate IT(I);
360 constexpr const int kOffset = 42;
361 State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset);
362 // Memory is operands 2-6.
363 EXPECT_THAT(IT.getValueFor(I.Operands[2]), IsReg(X86::RDI));
364 EXPECT_THAT(IT.getValueFor(I.Operands[3]), IsImm(1));
365 EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(0));
366 EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(kOffset));
367 EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0));
370 TEST_F(Core2Avx512TargetTest, FillMemoryOperands_VGATHERDPSZ128rm) {
371 Instruction I(State.getInstrInfo(), State.getRATC(), X86::VGATHERDPSZ128rm);
372 InstructionTemplate IT(I);
373 constexpr const int kOffset = 42;
374 State.getExegesisTarget().fillMemoryOperands(IT, X86::RDI, kOffset);
375 // Memory is operands 4-8.
376 EXPECT_THAT(IT.getValueFor(I.Operands[4]), IsReg(X86::RDI));
377 EXPECT_THAT(IT.getValueFor(I.Operands[5]), IsImm(1));
378 EXPECT_THAT(IT.getValueFor(I.Operands[6]), IsReg(0));
379 EXPECT_THAT(IT.getValueFor(I.Operands[7]), IsImm(kOffset));
380 EXPECT_THAT(IT.getValueFor(I.Operands[8]), IsReg(0));
383 } // namespace
384 } // namespace exegesis
385 } // namespace llvm