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/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"
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
) : 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
,
125 class Core2TargetTest
: public X86TargetTest
{
127 Core2TargetTest() : X86TargetTest("") {}
130 class Core2AvxTargetTest
: public X86TargetTest
{
132 Core2AvxTargetTest() : X86TargetTest("+avx") {}
135 class Core2Avx512TargetTest
: public X86TargetTest
{
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
) {
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
) {
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
) {
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";
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";
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";
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));
384 } // namespace exegesis