[llvm-exegesis] Improve Register Setup.
[llvm-core.git] / unittests / tools / llvm-exegesis / X86 / TargetTest.cpp
blob4d50b0427ed00d09955efda779ddc79b2c480ac5
1 #include "Target.h"
3 #include <cassert>
4 #include <memory>
6 #include "MCTargetDesc/X86MCTargetDesc.h"
7 #include "llvm/Support/TargetRegistry.h"
8 #include "llvm/Support/TargetSelect.h"
9 #include "gmock/gmock.h"
10 #include "gtest/gtest.h"
12 #include "llvm/MC/MCInstPrinter.h"
14 namespace llvm {
16 bool operator==(const MCOperand &a, const MCOperand &b) {
17 if (a.isImm() && b.isImm())
18 return a.getImm() == b.getImm();
19 if (a.isReg() && b.isReg())
20 return a.getReg() == b.getReg();
21 return false;
24 bool operator==(const MCInst &a, const MCInst &b) {
25 if (a.getOpcode() != b.getOpcode())
26 return false;
27 if (a.getNumOperands() != b.getNumOperands())
28 return false;
29 for (unsigned I = 0; I < a.getNumOperands(); ++I) {
30 if (!(a.getOperand(I) == b.getOperand(I)))
31 return false;
33 return true;
36 } // namespace llvm
38 namespace exegesis {
40 void InitializeX86ExegesisTarget();
42 namespace {
44 using testing::AllOf;
45 using testing::ElementsAre;
46 using testing::ElementsAreArray;
47 using testing::Eq;
48 using testing::Gt;
49 using testing::Matcher;
50 using testing::NotNull;
51 using testing::Property;
52 using testing::SizeIs;
54 using llvm::APInt;
55 using llvm::MCInst;
56 using llvm::MCInstBuilder;
57 using llvm::MCOperand;
59 Matcher<MCOperand> IsImm(int64_t Value) {
60 return AllOf(Property(&MCOperand::isImm, Eq(true)),
61 Property(&MCOperand::getImm, Eq(Value)));
64 Matcher<MCOperand> IsReg(unsigned Reg) {
65 return AllOf(Property(&MCOperand::isReg, Eq(true)),
66 Property(&MCOperand::getReg, Eq(Reg)));
69 Matcher<MCInst> OpcodeIs(unsigned Opcode) {
70 return Property(&MCInst::getOpcode, Eq(Opcode));
73 Matcher<MCInst> IsMovImmediate(unsigned Opcode, int64_t Reg, int64_t Value) {
74 return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg), IsImm(Value)));
77 Matcher<MCInst> IsMovValueToStack(unsigned Opcode, int64_t Value,
78 size_t Offset) {
79 return AllOf(OpcodeIs(Opcode),
80 ElementsAre(IsReg(llvm::X86::RSP), IsImm(1), IsReg(0),
81 IsImm(Offset), IsReg(0), IsImm(Value)));
84 Matcher<MCInst> IsMovValueFromStack(unsigned Opcode, unsigned Reg) {
85 return AllOf(OpcodeIs(Opcode),
86 ElementsAre(IsReg(Reg), IsReg(llvm::X86::RSP), IsImm(1),
87 IsReg(0), IsImm(0), IsReg(0)));
90 Matcher<MCInst> IsStackAllocate(unsigned Size) {
91 return AllOf(
92 OpcodeIs(llvm::X86::SUB64ri8),
93 ElementsAre(IsReg(llvm::X86::RSP), IsReg(llvm::X86::RSP), IsImm(Size)));
96 Matcher<MCInst> IsStackDeallocate(unsigned Size) {
97 return AllOf(
98 OpcodeIs(llvm::X86::ADD64ri8),
99 ElementsAre(IsReg(llvm::X86::RSP), IsReg(llvm::X86::RSP), IsImm(Size)));
102 constexpr const char kTriple[] = "x86_64-unknown-linux";
103 constexpr const char kFeaturesEmpty[] = "";
104 constexpr const char kFeaturesAvx[] = "+avx";
105 constexpr const char kFeaturesAvx512VL[] = "+avx512vl";
106 constexpr const char kCpuCore2[] = "core2";
108 template <const char *CPU, const char *Features>
109 class X86TargetTest : public ::testing::Test {
110 protected:
111 X86TargetTest()
112 : ExegesisTarget_(ExegesisTarget::lookup(llvm::Triple(kTriple))) {
113 EXPECT_THAT(ExegesisTarget_, NotNull());
114 std::string error;
115 Target_ = llvm::TargetRegistry::lookupTarget(kTriple, error);
116 EXPECT_THAT(Target_, NotNull());
117 STI_.reset(Target_->createMCSubtargetInfo(kTriple, kCpuCore2, Features));
120 static void SetUpTestCase() {
121 LLVMInitializeX86TargetInfo();
122 LLVMInitializeX86Target();
123 LLVMInitializeX86TargetMC();
124 InitializeX86ExegesisTarget();
127 std::vector<MCInst> setRegTo(unsigned Reg, const APInt &Value) {
128 return ExegesisTarget_->setRegTo(*STI_, Reg, Value);
131 const llvm::Target *Target_;
132 const ExegesisTarget *const ExegesisTarget_;
133 std::unique_ptr<llvm::MCSubtargetInfo> STI_;
136 using Core2TargetTest = X86TargetTest<kCpuCore2, kFeaturesEmpty>;
137 using Core2AvxTargetTest = X86TargetTest<kCpuCore2, kFeaturesAvx>;
138 using Core2Avx512TargetTest = X86TargetTest<kCpuCore2, kFeaturesAvx512VL>;
140 TEST_F(Core2TargetTest, SetFlags) {
141 const unsigned Reg = llvm::X86::EFLAGS;
142 EXPECT_THAT(
143 setRegTo(Reg, APInt(64, 0x1111222233334444ULL)),
144 ElementsAre(IsStackAllocate(8),
145 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
146 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
147 OpcodeIs(llvm::X86::POPF64)));
150 TEST_F(Core2TargetTest, SetRegToGR8Value) {
151 const uint8_t Value = 0xFFU;
152 const unsigned Reg = llvm::X86::AL;
153 EXPECT_THAT(setRegTo(Reg, APInt(8, Value)),
154 ElementsAre(IsMovImmediate(llvm::X86::MOV8ri, Reg, Value)));
157 TEST_F(Core2TargetTest, SetRegToGR16Value) {
158 const uint16_t Value = 0xFFFFU;
159 const unsigned Reg = llvm::X86::BX;
160 EXPECT_THAT(setRegTo(Reg, APInt(16, Value)),
161 ElementsAre(IsMovImmediate(llvm::X86::MOV16ri, Reg, Value)));
164 TEST_F(Core2TargetTest, SetRegToGR32Value) {
165 const uint32_t Value = 0x7FFFFU;
166 const unsigned Reg = llvm::X86::ECX;
167 EXPECT_THAT(setRegTo(Reg, APInt(32, Value)),
168 ElementsAre(IsMovImmediate(llvm::X86::MOV32ri, Reg, Value)));
171 TEST_F(Core2TargetTest, SetRegToGR64Value) {
172 const uint64_t Value = 0x7FFFFFFFFFFFFFFFULL;
173 const unsigned Reg = llvm::X86::RDX;
174 EXPECT_THAT(setRegTo(Reg, APInt(64, Value)),
175 ElementsAre(IsMovImmediate(llvm::X86::MOV64ri, Reg, Value)));
178 TEST_F(Core2TargetTest, SetRegToVR64Value) {
179 EXPECT_THAT(
180 setRegTo(llvm::X86::MM0, APInt(64, 0x1111222233334444ULL)),
181 ElementsAre(IsStackAllocate(8),
182 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
183 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
184 IsMovValueFromStack(llvm::X86::MMX_MOVQ64rm, llvm::X86::MM0),
185 IsStackDeallocate(8)));
188 TEST_F(Core2TargetTest, SetRegToVR128Value_Use_MOVDQUrm) {
189 EXPECT_THAT(
190 setRegTo(llvm::X86::XMM0,
191 APInt(128, "11112222333344445555666677778888", 16)),
192 ElementsAre(IsStackAllocate(16),
193 IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
194 IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
195 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
196 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
197 IsMovValueFromStack(llvm::X86::MOVDQUrm, llvm::X86::XMM0),
198 IsStackDeallocate(16)));
201 TEST_F(Core2AvxTargetTest, SetRegToVR128Value_Use_VMOVDQUrm) {
202 EXPECT_THAT(
203 setRegTo(llvm::X86::XMM0,
204 APInt(128, "11112222333344445555666677778888", 16)),
205 ElementsAre(IsStackAllocate(16),
206 IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
207 IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
208 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
209 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
210 IsMovValueFromStack(llvm::X86::VMOVDQUrm, llvm::X86::XMM0),
211 IsStackDeallocate(16)));
214 TEST_F(Core2Avx512TargetTest, SetRegToVR128Value_Use_VMOVDQU32Z128rm) {
215 EXPECT_THAT(
216 setRegTo(llvm::X86::XMM0,
217 APInt(128, "11112222333344445555666677778888", 16)),
218 ElementsAre(
219 IsStackAllocate(16),
220 IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
221 IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
222 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
223 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
224 IsMovValueFromStack(llvm::X86::VMOVDQU32Z128rm, llvm::X86::XMM0),
225 IsStackDeallocate(16)));
228 TEST_F(Core2AvxTargetTest, SetRegToVR256Value_Use_VMOVDQUYrm) {
229 const char ValueStr[] =
230 "1111111122222222333333334444444455555555666666667777777788888888";
231 EXPECT_THAT(setRegTo(llvm::X86::YMM0, APInt(256, ValueStr, 16)),
232 ElementsAreArray(
233 {IsStackAllocate(32),
234 IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 0),
235 IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 4),
236 IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 8),
237 IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 12),
238 IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 16),
239 IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 20),
240 IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 24),
241 IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 28),
242 IsMovValueFromStack(llvm::X86::VMOVDQUYrm, llvm::X86::YMM0),
243 IsStackDeallocate(32)}));
246 TEST_F(Core2Avx512TargetTest, SetRegToVR256Value_Use_VMOVDQU32Z256rm) {
247 const char ValueStr[] =
248 "1111111122222222333333334444444455555555666666667777777788888888";
249 EXPECT_THAT(
250 setRegTo(llvm::X86::YMM0, APInt(256, ValueStr, 16)),
251 ElementsAreArray(
252 {IsStackAllocate(32),
253 IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 0),
254 IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 4),
255 IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 8),
256 IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 12),
257 IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 16),
258 IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 20),
259 IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 24),
260 IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 28),
261 IsMovValueFromStack(llvm::X86::VMOVDQU32Z256rm, llvm::X86::YMM0),
262 IsStackDeallocate(32)}));
265 TEST_F(Core2Avx512TargetTest, SetRegToVR512Value) {
266 const char ValueStr[] =
267 "1111111122222222333333334444444455555555666666667777777788888888"
268 "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000";
269 EXPECT_THAT(
270 setRegTo(llvm::X86::ZMM0, APInt(512, ValueStr, 16)),
271 ElementsAreArray(
272 {IsStackAllocate(64),
273 IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 0),
274 IsMovValueToStack(llvm::X86::MOV32mi, 0xFFFFFFFFUL, 4),
275 IsMovValueToStack(llvm::X86::MOV32mi, 0xEEEEEEEEUL, 8),
276 IsMovValueToStack(llvm::X86::MOV32mi, 0xDDDDDDDDUL, 12),
277 IsMovValueToStack(llvm::X86::MOV32mi, 0xCCCCCCCCUL, 16),
278 IsMovValueToStack(llvm::X86::MOV32mi, 0xBBBBBBBBUL, 20),
279 IsMovValueToStack(llvm::X86::MOV32mi, 0xAAAAAAAAUL, 24),
280 IsMovValueToStack(llvm::X86::MOV32mi, 0x99999999UL, 28),
281 IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 32),
282 IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 36),
283 IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 40),
284 IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 44),
285 IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 48),
286 IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 52),
287 IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 56),
288 IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 60),
289 IsMovValueFromStack(llvm::X86::VMOVDQU32Zrm, llvm::X86::ZMM0),
290 IsStackDeallocate(64)}));
293 TEST_F(Core2TargetTest, SetRegToST0_32Bits) {
294 EXPECT_THAT(
295 setRegTo(llvm::X86::ST0, APInt(32, 0x11112222ULL)),
296 ElementsAre(IsStackAllocate(4),
297 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0),
298 OpcodeIs(llvm::X86::LD_F32m), IsStackDeallocate(4)));
301 TEST_F(Core2TargetTest, SetRegToST1_32Bits) {
302 const MCInst CopySt0ToSt1 =
303 llvm::MCInstBuilder(llvm::X86::ST_Frr).addReg(llvm::X86::ST1);
304 EXPECT_THAT(
305 setRegTo(llvm::X86::ST1, APInt(32, 0x11112222ULL)),
306 ElementsAre(IsStackAllocate(4),
307 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0),
308 OpcodeIs(llvm::X86::LD_F32m), CopySt0ToSt1,
309 IsStackDeallocate(4)));
312 TEST_F(Core2TargetTest, SetRegToST0_64Bits) {
313 EXPECT_THAT(
314 setRegTo(llvm::X86::ST0, APInt(64, 0x1111222233334444ULL)),
315 ElementsAre(IsStackAllocate(8),
316 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
317 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
318 OpcodeIs(llvm::X86::LD_F64m), IsStackDeallocate(8)));
321 TEST_F(Core2TargetTest, SetRegToST0_80Bits) {
322 EXPECT_THAT(
323 setRegTo(llvm::X86::ST0, APInt(80, "11112222333344445555", 16)),
324 ElementsAre(IsStackAllocate(10),
325 IsMovValueToStack(llvm::X86::MOV32mi, 0x44445555UL, 0),
326 IsMovValueToStack(llvm::X86::MOV32mi, 0x22223333UL, 4),
327 IsMovValueToStack(llvm::X86::MOV16mi, 0x1111UL, 8),
328 OpcodeIs(llvm::X86::LD_F80m), IsStackDeallocate(10)));
331 } // namespace
332 } // namespace exegesis