1 //===-- TargetTest.cpp -----------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
14 #include "MCTargetDesc/X86MCTargetDesc.h"
15 #include "llvm/MC/TargetRegistry.h"
16 #include "llvm/Support/TargetSelect.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
20 #include "llvm/MC/MCInstPrinter.h"
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();
32 bool operator==(const MCInst
&a
, const MCInst
&b
) {
33 if (a
.getOpcode() != b
.getOpcode())
35 if (a
.getNumOperands() != b
.getNumOperands())
37 for (unsigned I
= 0; I
< a
.getNumOperands(); ++I
) {
38 if (!(a
.getOperand(I
) == b
.getOperand(I
)))
49 void InitializeX86ExegesisTarget();
54 using testing::ElementsAre
;
55 using testing::ElementsAreArray
;
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
,
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),
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
{
108 X86TargetTest(const char *Features
)
109 : State(cantFail(LLVMState::Create(kTriple
, "core2", Features
))) {}
111 static void SetUpTestCase() {
112 LLVMInitializeX86TargetInfo();
113 LLVMInitializeX86Target();
114 LLVMInitializeX86TargetMC();
115 InitializeX86ExegesisTarget();
118 std::vector
<MCInst
> setRegTo(unsigned Reg
, const APInt
&Value
) {
119 return State
.getExegesisTarget().setRegTo(State
.getSubtargetInfo(), Reg
,
123 const Instruction
&getInstr(unsigned OpCode
) {
124 return State
.getIC().getInstr(OpCode
);
130 class X86Core2TargetTest
: public X86TargetTest
{
132 X86Core2TargetTest() : X86TargetTest("") {}
135 class X86Core2AvxTargetTest
: public X86TargetTest
{
137 X86Core2AvxTargetTest() : X86TargetTest("+avx") {}
140 class X86Core2Avx512TargetTest
: public X86TargetTest
{
142 X86Core2Avx512TargetTest() : X86TargetTest("+avx512vl") {}
145 TEST_F(X86Core2TargetTest
, NoHighByteRegs
) {
146 EXPECT_TRUE(State
.getRATC().reservedRegisters().test(X86::AH
));
149 TEST_F(X86Core2TargetTest
, SetFlags
) {
150 const unsigned Reg
= X86::EFLAGS
;
151 EXPECT_THAT(setRegTo(Reg
, APInt(64, 0x1111222233334444ULL
)),
152 ElementsAre(IsStackAllocate(8),
153 IsMovValueToStack(X86::MOV32mi
, 0x33334444UL
, 0),
154 IsMovValueToStack(X86::MOV32mi
, 0x11112222UL
, 4),
155 OpcodeIs(X86::POPF64
)));
158 TEST_F(X86Core2TargetTest
, SetRegToGR8Value
) {
159 const uint8_t Value
= 0xFFU
;
160 const unsigned Reg
= X86::AL
;
161 EXPECT_THAT(setRegTo(Reg
, APInt(8, Value
)),
162 ElementsAre(IsMovImmediate(X86::MOV8ri
, Reg
, Value
)));
165 TEST_F(X86Core2TargetTest
, SetRegToGR16Value
) {
166 const uint16_t Value
= 0xFFFFU
;
167 const unsigned Reg
= X86::BX
;
168 EXPECT_THAT(setRegTo(Reg
, APInt(16, Value
)),
169 ElementsAre(IsMovImmediate(X86::MOV16ri
, Reg
, Value
)));
172 TEST_F(X86Core2TargetTest
, SetRegToGR32Value
) {
173 const uint32_t Value
= 0x7FFFFU
;
174 const unsigned Reg
= X86::ECX
;
175 EXPECT_THAT(setRegTo(Reg
, APInt(32, Value
)),
176 ElementsAre(IsMovImmediate(X86::MOV32ri
, Reg
, Value
)));
179 TEST_F(X86Core2TargetTest
, SetRegToGR64Value
) {
180 const uint64_t Value
= 0x7FFFFFFFFFFFFFFFULL
;
181 const unsigned Reg
= X86::RDX
;
182 EXPECT_THAT(setRegTo(Reg
, APInt(64, Value
)),
183 ElementsAre(IsMovImmediate(X86::MOV64ri
, Reg
, Value
)));
186 TEST_F(X86Core2TargetTest
, SetRegToVR64Value
) {
187 EXPECT_THAT(setRegTo(X86::MM0
, APInt(64, 0x1111222233334444ULL
)),
188 ElementsAre(IsStackAllocate(8),
189 IsMovValueToStack(X86::MOV32mi
, 0x33334444UL
, 0),
190 IsMovValueToStack(X86::MOV32mi
, 0x11112222UL
, 4),
191 IsMovValueFromStack(X86::MMX_MOVQ64rm
, X86::MM0
),
192 IsStackDeallocate(8)));
195 TEST_F(X86Core2TargetTest
, SetRegToVR128Value_Use_MOVDQUrm
) {
197 setRegTo(X86::XMM0
, APInt(128, "11112222333344445555666677778888", 16)),
198 ElementsAre(IsStackAllocate(16),
199 IsMovValueToStack(X86::MOV32mi
, 0x77778888UL
, 0),
200 IsMovValueToStack(X86::MOV32mi
, 0x55556666UL
, 4),
201 IsMovValueToStack(X86::MOV32mi
, 0x33334444UL
, 8),
202 IsMovValueToStack(X86::MOV32mi
, 0x11112222UL
, 12),
203 IsMovValueFromStack(X86::MOVDQUrm
, X86::XMM0
),
204 IsStackDeallocate(16)));
207 TEST_F(X86Core2AvxTargetTest
, SetRegToVR128Value_Use_VMOVDQUrm
) {
209 setRegTo(X86::XMM0
, APInt(128, "11112222333344445555666677778888", 16)),
210 ElementsAre(IsStackAllocate(16),
211 IsMovValueToStack(X86::MOV32mi
, 0x77778888UL
, 0),
212 IsMovValueToStack(X86::MOV32mi
, 0x55556666UL
, 4),
213 IsMovValueToStack(X86::MOV32mi
, 0x33334444UL
, 8),
214 IsMovValueToStack(X86::MOV32mi
, 0x11112222UL
, 12),
215 IsMovValueFromStack(X86::VMOVDQUrm
, X86::XMM0
),
216 IsStackDeallocate(16)));
219 TEST_F(X86Core2Avx512TargetTest
, SetRegToVR128Value_Use_VMOVDQU32Z128rm
) {
221 setRegTo(X86::XMM0
, APInt(128, "11112222333344445555666677778888", 16)),
222 ElementsAre(IsStackAllocate(16),
223 IsMovValueToStack(X86::MOV32mi
, 0x77778888UL
, 0),
224 IsMovValueToStack(X86::MOV32mi
, 0x55556666UL
, 4),
225 IsMovValueToStack(X86::MOV32mi
, 0x33334444UL
, 8),
226 IsMovValueToStack(X86::MOV32mi
, 0x11112222UL
, 12),
227 IsMovValueFromStack(X86::VMOVDQU32Z128rm
, X86::XMM0
),
228 IsStackDeallocate(16)));
231 TEST_F(X86Core2AvxTargetTest
, SetRegToVR256Value_Use_VMOVDQUYrm
) {
232 const char ValueStr
[] =
233 "1111111122222222333333334444444455555555666666667777777788888888";
235 setRegTo(X86::YMM0
, APInt(256, ValueStr
, 16)),
236 ElementsAreArray({IsStackAllocate(32),
237 IsMovValueToStack(X86::MOV32mi
, 0x88888888UL
, 0),
238 IsMovValueToStack(X86::MOV32mi
, 0x77777777UL
, 4),
239 IsMovValueToStack(X86::MOV32mi
, 0x66666666UL
, 8),
240 IsMovValueToStack(X86::MOV32mi
, 0x55555555UL
, 12),
241 IsMovValueToStack(X86::MOV32mi
, 0x44444444UL
, 16),
242 IsMovValueToStack(X86::MOV32mi
, 0x33333333UL
, 20),
243 IsMovValueToStack(X86::MOV32mi
, 0x22222222UL
, 24),
244 IsMovValueToStack(X86::MOV32mi
, 0x11111111UL
, 28),
245 IsMovValueFromStack(X86::VMOVDQUYrm
, X86::YMM0
),
246 IsStackDeallocate(32)}));
249 TEST_F(X86Core2Avx512TargetTest
, SetRegToVR256Value_Use_VMOVDQU32Z256rm
) {
250 const char ValueStr
[] =
251 "1111111122222222333333334444444455555555666666667777777788888888";
253 setRegTo(X86::YMM0
, APInt(256, ValueStr
, 16)),
254 ElementsAreArray({IsStackAllocate(32),
255 IsMovValueToStack(X86::MOV32mi
, 0x88888888UL
, 0),
256 IsMovValueToStack(X86::MOV32mi
, 0x77777777UL
, 4),
257 IsMovValueToStack(X86::MOV32mi
, 0x66666666UL
, 8),
258 IsMovValueToStack(X86::MOV32mi
, 0x55555555UL
, 12),
259 IsMovValueToStack(X86::MOV32mi
, 0x44444444UL
, 16),
260 IsMovValueToStack(X86::MOV32mi
, 0x33333333UL
, 20),
261 IsMovValueToStack(X86::MOV32mi
, 0x22222222UL
, 24),
262 IsMovValueToStack(X86::MOV32mi
, 0x11111111UL
, 28),
263 IsMovValueFromStack(X86::VMOVDQU32Z256rm
, X86::YMM0
),
264 IsStackDeallocate(32)}));
267 TEST_F(X86Core2Avx512TargetTest
, SetRegToVR512Value
) {
268 const char ValueStr
[] =
269 "1111111122222222333333334444444455555555666666667777777788888888"
270 "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000";
272 setRegTo(X86::ZMM0
, APInt(512, ValueStr
, 16)),
273 ElementsAreArray({IsStackAllocate(64),
274 IsMovValueToStack(X86::MOV32mi
, 0x00000000UL
, 0),
275 IsMovValueToStack(X86::MOV32mi
, 0xFFFFFFFFUL
, 4),
276 IsMovValueToStack(X86::MOV32mi
, 0xEEEEEEEEUL
, 8),
277 IsMovValueToStack(X86::MOV32mi
, 0xDDDDDDDDUL
, 12),
278 IsMovValueToStack(X86::MOV32mi
, 0xCCCCCCCCUL
, 16),
279 IsMovValueToStack(X86::MOV32mi
, 0xBBBBBBBBUL
, 20),
280 IsMovValueToStack(X86::MOV32mi
, 0xAAAAAAAAUL
, 24),
281 IsMovValueToStack(X86::MOV32mi
, 0x99999999UL
, 28),
282 IsMovValueToStack(X86::MOV32mi
, 0x88888888UL
, 32),
283 IsMovValueToStack(X86::MOV32mi
, 0x77777777UL
, 36),
284 IsMovValueToStack(X86::MOV32mi
, 0x66666666UL
, 40),
285 IsMovValueToStack(X86::MOV32mi
, 0x55555555UL
, 44),
286 IsMovValueToStack(X86::MOV32mi
, 0x44444444UL
, 48),
287 IsMovValueToStack(X86::MOV32mi
, 0x33333333UL
, 52),
288 IsMovValueToStack(X86::MOV32mi
, 0x22222222UL
, 56),
289 IsMovValueToStack(X86::MOV32mi
, 0x11111111UL
, 60),
290 IsMovValueFromStack(X86::VMOVDQU32Zrm
, X86::ZMM0
),
291 IsStackDeallocate(64)}));
294 // Note: We always put 80 bits on the stack independently of the size of the
295 // value. This uses a bit more space but makes the code simpler.
297 TEST_F(X86Core2TargetTest
, SetRegToST0_32Bits
) {
298 EXPECT_THAT(setRegTo(X86::ST0
, APInt(32, 0x11112222ULL
)),
299 ElementsAre(IsStackAllocate(10),
300 IsMovValueToStack(X86::MOV32mi
, 0x11112222UL
, 0),
301 IsMovValueToStack(X86::MOV32mi
, 0x00000000UL
, 4),
302 IsMovValueToStack(X86::MOV16mi
, 0x0000UL
, 8),
303 OpcodeIs(X86::LD_F80m
), IsStackDeallocate(10)));
306 TEST_F(X86Core2TargetTest
, SetRegToST1_32Bits
) {
307 const MCInst CopySt0ToSt1
= MCInstBuilder(X86::ST_Frr
).addReg(X86::ST1
);
308 EXPECT_THAT(setRegTo(X86::ST1
, APInt(32, 0x11112222ULL
)),
309 ElementsAre(IsStackAllocate(10),
310 IsMovValueToStack(X86::MOV32mi
, 0x11112222UL
, 0),
311 IsMovValueToStack(X86::MOV32mi
, 0x00000000UL
, 4),
312 IsMovValueToStack(X86::MOV16mi
, 0x0000UL
, 8),
313 OpcodeIs(X86::LD_F80m
), CopySt0ToSt1
,
314 IsStackDeallocate(10)));
317 TEST_F(X86Core2TargetTest
, SetRegToST0_64Bits
) {
318 EXPECT_THAT(setRegTo(X86::ST0
, APInt(64, 0x1111222233334444ULL
)),
319 ElementsAre(IsStackAllocate(10),
320 IsMovValueToStack(X86::MOV32mi
, 0x33334444UL
, 0),
321 IsMovValueToStack(X86::MOV32mi
, 0x11112222UL
, 4),
322 IsMovValueToStack(X86::MOV16mi
, 0x0000UL
, 8),
323 OpcodeIs(X86::LD_F80m
), IsStackDeallocate(10)));
326 TEST_F(X86Core2TargetTest
, SetRegToST0_80Bits
) {
327 EXPECT_THAT(setRegTo(X86::ST0
, APInt(80, "11112222333344445555", 16)),
328 ElementsAre(IsStackAllocate(10),
329 IsMovValueToStack(X86::MOV32mi
, 0x44445555UL
, 0),
330 IsMovValueToStack(X86::MOV32mi
, 0x22223333UL
, 4),
331 IsMovValueToStack(X86::MOV16mi
, 0x1111UL
, 8),
332 OpcodeIs(X86::LD_F80m
), IsStackDeallocate(10)));
335 TEST_F(X86Core2TargetTest
, SetRegToFP0_80Bits
) {
336 EXPECT_THAT(setRegTo(X86::FP0
, APInt(80, "11112222333344445555", 16)),
337 ElementsAre(IsStackAllocate(10),
338 IsMovValueToStack(X86::MOV32mi
, 0x44445555UL
, 0),
339 IsMovValueToStack(X86::MOV32mi
, 0x22223333UL
, 4),
340 IsMovValueToStack(X86::MOV16mi
, 0x1111UL
, 8),
341 OpcodeIs(X86::LD_Fp80m
), IsStackDeallocate(10)));
344 TEST_F(X86Core2TargetTest
, SetRegToFP1_32Bits
) {
345 EXPECT_THAT(setRegTo(X86::FP1
, APInt(32, 0x11112222ULL
)),
346 ElementsAre(IsStackAllocate(10),
347 IsMovValueToStack(X86::MOV32mi
, 0x11112222UL
, 0),
348 IsMovValueToStack(X86::MOV32mi
, 0x00000000UL
, 4),
349 IsMovValueToStack(X86::MOV16mi
, 0x0000UL
, 8),
350 OpcodeIs(X86::LD_Fp80m
), IsStackDeallocate(10)));
353 TEST_F(X86Core2TargetTest
, SetRegToFP1_4Bits
) {
354 EXPECT_THAT(setRegTo(X86::FP1
, APInt(4, 0x1ULL
)),
355 ElementsAre(IsStackAllocate(10),
356 IsMovValueToStack(X86::MOV32mi
, 0x00000001UL
, 0),
357 IsMovValueToStack(X86::MOV32mi
, 0x00000000UL
, 4),
358 IsMovValueToStack(X86::MOV16mi
, 0x0000UL
, 8),
359 OpcodeIs(X86::LD_Fp80m
), IsStackDeallocate(10)));
362 TEST_F(X86Core2Avx512TargetTest
, FillMemoryOperands_ADD64rm
) {
363 const Instruction
&I
= getInstr(X86::ADD64rm
);
364 InstructionTemplate
IT(&I
);
365 constexpr const int kOffset
= 42;
366 State
.getExegesisTarget().fillMemoryOperands(IT
, X86::RDI
, kOffset
);
367 // Memory is operands 2-6.
368 EXPECT_THAT(IT
.getValueFor(I
.Operands
[2]), IsReg(X86::RDI
));
369 EXPECT_THAT(IT
.getValueFor(I
.Operands
[3]), IsImm(1));
370 EXPECT_THAT(IT
.getValueFor(I
.Operands
[4]), IsReg(0));
371 EXPECT_THAT(IT
.getValueFor(I
.Operands
[5]), IsImm(kOffset
));
372 EXPECT_THAT(IT
.getValueFor(I
.Operands
[6]), IsReg(0));
375 TEST_F(X86Core2Avx512TargetTest
, FillMemoryOperands_VGATHERDPSZ128rm
) {
376 const Instruction
&I
= getInstr(X86::VGATHERDPSZ128rm
);
377 InstructionTemplate
IT(&I
);
378 constexpr const int kOffset
= 42;
379 State
.getExegesisTarget().fillMemoryOperands(IT
, X86::RDI
, kOffset
);
380 // Memory is operands 4-8.
381 EXPECT_THAT(IT
.getValueFor(I
.Operands
[4]), IsReg(X86::RDI
));
382 EXPECT_THAT(IT
.getValueFor(I
.Operands
[5]), IsImm(1));
383 EXPECT_THAT(IT
.getValueFor(I
.Operands
[6]), IsReg(0));
384 EXPECT_THAT(IT
.getValueFor(I
.Operands
[7]), IsImm(kOffset
));
385 EXPECT_THAT(IT
.getValueFor(I
.Operands
[8]), IsReg(0));
388 TEST_F(X86Core2TargetTest
, AllowAsBackToBack
) {
390 State
.getExegesisTarget().allowAsBackToBack(getInstr(X86::ADD64rr
)));
392 State
.getExegesisTarget().allowAsBackToBack(getInstr(X86::LEA64r
)));
396 } // namespace exegesis