blob: c60f003c727737b272b7df22749c92965c65e779 [file] [log] [blame]
Clement Courbet44b4c542018-06-19 11:28:59 +00001#include "Target.h"
2
3#include <cassert>
4#include <memory>
5
Clement Courbeta51efc22018-06-25 13:12:02 +00006#include "MCTargetDesc/X86MCTargetDesc.h"
Clement Courbete7851692018-07-03 06:17:05 +00007#include "llvm/Support/TargetRegistry.h"
8#include "llvm/Support/TargetSelect.h"
Clement Courbet44b4c542018-06-19 11:28:59 +00009#include "gmock/gmock.h"
10#include "gtest/gtest.h"
11
Guillaume Chatelet5ad29092018-09-18 11:26:27 +000012#include "llvm/MC/MCInstPrinter.h"
13
14namespace llvm {
15
Guillaume Chatelet8721ad92018-09-18 11:26:35 +000016bool operator==(const MCOperand &a, const MCOperand &b) {
Guillaume Chatelet5ad29092018-09-18 11:26:27 +000017 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;
22}
23
Guillaume Chatelet8721ad92018-09-18 11:26:35 +000024bool operator==(const MCInst &a, const MCInst &b) {
Guillaume Chatelet5ad29092018-09-18 11:26:27 +000025 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;
32 }
33 return true;
34}
35
36} // namespace llvm
37
Clement Courbet44b4c542018-06-19 11:28:59 +000038namespace exegesis {
39
40void InitializeX86ExegesisTarget();
41
42namespace {
43
Guillaume Chatelet8721ad92018-09-18 11:26:35 +000044using testing::AllOf;
Guillaume Chatelet5ad29092018-09-18 11:26:27 +000045using testing::ElementsAre;
Guillaume Chatelet8721ad92018-09-18 11:26:35 +000046using testing::ElementsAreArray;
47using testing::Eq;
Clement Courbeta51efc22018-06-25 13:12:02 +000048using testing::Gt;
Guillaume Chatelet8721ad92018-09-18 11:26:35 +000049using testing::Matcher;
Clement Courbet44b4c542018-06-19 11:28:59 +000050using testing::NotNull;
Guillaume Chatelet8721ad92018-09-18 11:26:35 +000051using testing::Property;
Clement Courbeta51efc22018-06-25 13:12:02 +000052using testing::SizeIs;
Clement Courbet44b4c542018-06-19 11:28:59 +000053
Guillaume Chatelet5ad29092018-09-18 11:26:27 +000054using llvm::APInt;
55using llvm::MCInst;
56using llvm::MCInstBuilder;
Guillaume Chatelet8721ad92018-09-18 11:26:35 +000057using llvm::MCOperand;
58
59Matcher<MCOperand> IsImm(int64_t Value) {
60 return AllOf(Property(&MCOperand::isImm, Eq(true)),
61 Property(&MCOperand::getImm, Eq(Value)));
62}
63
64Matcher<MCOperand> IsReg(unsigned Reg) {
65 return AllOf(Property(&MCOperand::isReg, Eq(true)),
66 Property(&MCOperand::getReg, Eq(Reg)));
67}
68
69Matcher<MCInst> OpcodeIs(unsigned Opcode) {
70 return Property(&MCInst::getOpcode, Eq(Opcode));
71}
72
73Matcher<MCInst> IsMovImmediate(unsigned Opcode, int64_t Reg, int64_t Value) {
74 return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg), IsImm(Value)));
75}
76
77Matcher<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)));
82}
83
84Matcher<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)));
88}
89
90Matcher<MCInst> IsStackAllocate(unsigned Size) {
91 return AllOf(
92 OpcodeIs(llvm::X86::SUB64ri8),
93 ElementsAre(IsReg(llvm::X86::RSP), IsReg(llvm::X86::RSP), IsImm(Size)));
94}
95
96Matcher<MCInst> IsStackDeallocate(unsigned Size) {
97 return AllOf(
98 OpcodeIs(llvm::X86::ADD64ri8),
99 ElementsAre(IsReg(llvm::X86::RSP), IsReg(llvm::X86::RSP), IsImm(Size)));
100}
Guillaume Chatelet5ad29092018-09-18 11:26:27 +0000101
Clement Courbete7851692018-07-03 06:17:05 +0000102constexpr const char kTriple[] = "x86_64-unknown-linux";
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000103constexpr const char kFeaturesEmpty[] = "";
104constexpr const char kFeaturesAvx[] = "+avx";
105constexpr const char kFeaturesAvx512VL[] = "+avx512vl";
106constexpr const char kCpuCore2[] = "core2";
Clement Courbete7851692018-07-03 06:17:05 +0000107
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000108template <const char *CPU, const char *Features>
Clement Courbet44b4c542018-06-19 11:28:59 +0000109class X86TargetTest : public ::testing::Test {
110protected:
Clement Courbeta51efc22018-06-25 13:12:02 +0000111 X86TargetTest()
Clement Courbete7851692018-07-03 06:17:05 +0000112 : ExegesisTarget_(ExegesisTarget::lookup(llvm::Triple(kTriple))) {
113 EXPECT_THAT(ExegesisTarget_, NotNull());
114 std::string error;
115 Target_ = llvm::TargetRegistry::lookupTarget(kTriple, error);
Clement Courbeta51efc22018-06-25 13:12:02 +0000116 EXPECT_THAT(Target_, NotNull());
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000117 STI_.reset(Target_->createMCSubtargetInfo(kTriple, kCpuCore2, Features));
Clement Courbeta51efc22018-06-25 13:12:02 +0000118 }
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000119
Clement Courbete7851692018-07-03 06:17:05 +0000120 static void SetUpTestCase() {
121 LLVMInitializeX86TargetInfo();
122 LLVMInitializeX86Target();
123 LLVMInitializeX86TargetMC();
124 InitializeX86ExegesisTarget();
125 }
Clement Courbeta51efc22018-06-25 13:12:02 +0000126
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000127 std::vector<MCInst> setRegTo(unsigned Reg, const APInt &Value) {
Simon Pilgrim02426892018-09-18 15:35:49 +0000128 return ExegesisTarget_->setRegTo(*STI_, Value, Reg);
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000129 }
130
Clement Courbete7851692018-07-03 06:17:05 +0000131 const llvm::Target *Target_;
132 const ExegesisTarget *const ExegesisTarget_;
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000133 std::unique_ptr<llvm::MCSubtargetInfo> STI_;
Clement Courbet44b4c542018-06-19 11:28:59 +0000134};
135
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000136using Core2TargetTest = X86TargetTest<kCpuCore2, kFeaturesEmpty>;
137using Core2AvxTargetTest = X86TargetTest<kCpuCore2, kFeaturesAvx>;
138using Core2Avx512TargetTest = X86TargetTest<kCpuCore2, kFeaturesAvx512VL>;
139
140TEST_F(Core2TargetTest, SetRegToGR8Value) {
141 const uint8_t Value = 0xFFU;
142 const unsigned Reg = llvm::X86::AL;
143 EXPECT_THAT(setRegTo(Reg, APInt(8, Value)),
144 ElementsAre(IsMovImmediate(llvm::X86::MOV8ri, Reg, Value)));
Clement Courbeta51efc22018-06-25 13:12:02 +0000145}
146
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000147TEST_F(Core2TargetTest, SetRegToGR16Value) {
148 const uint16_t Value = 0xFFFFU;
149 const unsigned Reg = llvm::X86::BX;
150 EXPECT_THAT(setRegTo(Reg, APInt(16, Value)),
151 ElementsAre(IsMovImmediate(llvm::X86::MOV16ri, Reg, Value)));
Clement Courbete7851692018-07-03 06:17:05 +0000152}
153
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000154TEST_F(Core2TargetTest, SetRegToGR32Value) {
155 const uint32_t Value = 0x7FFFFU;
156 const unsigned Reg = llvm::X86::ECX;
157 EXPECT_THAT(setRegTo(Reg, APInt(32, Value)),
158 ElementsAre(IsMovImmediate(llvm::X86::MOV32ri, Reg, Value)));
Clement Courbete7851692018-07-03 06:17:05 +0000159}
160
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000161TEST_F(Core2TargetTest, SetRegToGR64Value) {
162 const uint64_t Value = 0x7FFFFFFFFFFFFFFFULL;
163 const unsigned Reg = llvm::X86::RDX;
164 EXPECT_THAT(setRegTo(Reg, APInt(64, Value)),
165 ElementsAre(IsMovImmediate(llvm::X86::MOV64ri, Reg, Value)));
Clement Courbete7851692018-07-03 06:17:05 +0000166}
167
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000168TEST_F(Core2TargetTest, SetRegToVR64Value) {
169 EXPECT_THAT(
170 setRegTo(llvm::X86::MM0, APInt(64, 0x1111222233334444ULL)),
171 ElementsAre(IsStackAllocate(8),
172 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
173 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
174 IsMovValueFromStack(llvm::X86::MMX_MOVQ64rm, llvm::X86::MM0),
175 IsStackDeallocate(8)));
Clement Courbete7851692018-07-03 06:17:05 +0000176}
177
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000178TEST_F(Core2TargetTest, SetRegToVR128Value_Use_MOVDQUrm) {
179 EXPECT_THAT(
180 setRegTo(llvm::X86::XMM0,
181 APInt(128, "11112222333344445555666677778888", 16)),
182 ElementsAre(IsStackAllocate(16),
183 IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
184 IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
185 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
186 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
187 IsMovValueFromStack(llvm::X86::MOVDQUrm, llvm::X86::XMM0),
188 IsStackDeallocate(16)));
Clement Courbete7851692018-07-03 06:17:05 +0000189}
190
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000191TEST_F(Core2AvxTargetTest, SetRegToVR128Value_Use_VMOVDQUrm) {
192 EXPECT_THAT(
193 setRegTo(llvm::X86::XMM0,
194 APInt(128, "11112222333344445555666677778888", 16)),
195 ElementsAre(IsStackAllocate(16),
196 IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
197 IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
198 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
199 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
200 IsMovValueFromStack(llvm::X86::VMOVDQUrm, llvm::X86::XMM0),
201 IsStackDeallocate(16)));
Clement Courbete7851692018-07-03 06:17:05 +0000202}
203
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000204TEST_F(Core2Avx512TargetTest, SetRegToVR128Value_Use_VMOVDQU32Z128rm) {
205 EXPECT_THAT(
206 setRegTo(llvm::X86::XMM0,
207 APInt(128, "11112222333344445555666677778888", 16)),
208 ElementsAre(
209 IsStackAllocate(16),
210 IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
211 IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
212 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
213 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
214 IsMovValueFromStack(llvm::X86::VMOVDQU32Z128rm, llvm::X86::XMM0),
215 IsStackDeallocate(16)));
Clement Courbet44b4c542018-06-19 11:28:59 +0000216}
217
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000218TEST_F(Core2AvxTargetTest, SetRegToVR256Value_Use_VMOVDQUYrm) {
219 const char ValueStr[] =
220 "1111111122222222333333334444444455555555666666667777777788888888";
221 EXPECT_THAT(setRegTo(llvm::X86::YMM0, APInt(256, ValueStr, 16)),
222 ElementsAreArray(
223 {IsStackAllocate(32),
224 IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 0),
225 IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 4),
226 IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 8),
227 IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 12),
228 IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 16),
229 IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 20),
230 IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 24),
231 IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 28),
232 IsMovValueFromStack(llvm::X86::VMOVDQUYrm, llvm::X86::YMM0),
233 IsStackDeallocate(32)}));
234}
Guillaume Chatelet5ad29092018-09-18 11:26:27 +0000235
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000236TEST_F(Core2Avx512TargetTest, SetRegToVR256Value_Use_VMOVDQU32Z256rm) {
237 const char ValueStr[] =
238 "1111111122222222333333334444444455555555666666667777777788888888";
239 EXPECT_THAT(
240 setRegTo(llvm::X86::YMM0, APInt(256, ValueStr, 16)),
241 ElementsAreArray(
242 {IsStackAllocate(32),
243 IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 0),
244 IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 4),
245 IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 8),
246 IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 12),
247 IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 16),
248 IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 20),
249 IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 24),
250 IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 28),
251 IsMovValueFromStack(llvm::X86::VMOVDQU32Z256rm, llvm::X86::YMM0),
252 IsStackDeallocate(32)}));
253}
Guillaume Chatelet5ad29092018-09-18 11:26:27 +0000254
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000255TEST_F(Core2Avx512TargetTest, SetRegToVR512Value) {
256 const char ValueStr[] =
257 "1111111122222222333333334444444455555555666666667777777788888888"
258 "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000";
259 EXPECT_THAT(
260 setRegTo(llvm::X86::ZMM0, APInt(512, ValueStr, 16)),
261 ElementsAreArray(
262 {IsStackAllocate(64),
263 IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 0),
264 IsMovValueToStack(llvm::X86::MOV32mi, 0xFFFFFFFFUL, 4),
265 IsMovValueToStack(llvm::X86::MOV32mi, 0xEEEEEEEEUL, 8),
266 IsMovValueToStack(llvm::X86::MOV32mi, 0xDDDDDDDDUL, 12),
267 IsMovValueToStack(llvm::X86::MOV32mi, 0xCCCCCCCCUL, 16),
268 IsMovValueToStack(llvm::X86::MOV32mi, 0xBBBBBBBBUL, 20),
269 IsMovValueToStack(llvm::X86::MOV32mi, 0xAAAAAAAAUL, 24),
270 IsMovValueToStack(llvm::X86::MOV32mi, 0x99999999UL, 28),
271 IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 32),
272 IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 36),
273 IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 40),
274 IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 44),
275 IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 48),
276 IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 52),
277 IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 56),
278 IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 60),
279 IsMovValueFromStack(llvm::X86::VMOVDQU32Zrm, llvm::X86::ZMM0),
280 IsStackDeallocate(64)}));
281}
282
283TEST_F(Core2TargetTest, SetRegToST0_32Bits) {
284 EXPECT_THAT(
285 setRegTo(llvm::X86::ST0, APInt(32, 0x11112222ULL)),
286 ElementsAre(IsStackAllocate(4),
287 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0),
Simon Pilgrim02426892018-09-18 15:35:49 +0000288 testing::A<MCInst>(), IsStackDeallocate(4)));
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000289}
290
291TEST_F(Core2TargetTest, SetRegToST1_32Bits) {
292 const MCInst CopySt0ToSt1 =
293 llvm::MCInstBuilder(llvm::X86::ST_Frr).addReg(llvm::X86::ST1);
294 EXPECT_THAT(
295 setRegTo(llvm::X86::ST1, APInt(32, 0x11112222ULL)),
296 ElementsAre(IsStackAllocate(4),
297 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0),
Simon Pilgrim02426892018-09-18 15:35:49 +0000298 testing::A<MCInst>(), CopySt0ToSt1, IsStackDeallocate(4)));
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000299}
300
301TEST_F(Core2TargetTest, SetRegToST0_64Bits) {
302 EXPECT_THAT(
303 setRegTo(llvm::X86::ST0, APInt(64, 0x1111222233334444ULL)),
304 ElementsAre(IsStackAllocate(8),
305 IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
306 IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
Simon Pilgrim02426892018-09-18 15:35:49 +0000307 testing::A<MCInst>(), IsStackDeallocate(8)));
Guillaume Chatelet8721ad92018-09-18 11:26:35 +0000308}
309
310TEST_F(Core2TargetTest, SetRegToST0_80Bits) {
311 EXPECT_THAT(
312 setRegTo(llvm::X86::ST0, APInt(80, "11112222333344445555", 16)),
313 ElementsAre(IsStackAllocate(10),
314 IsMovValueToStack(llvm::X86::MOV32mi, 0x44445555UL, 0),
315 IsMovValueToStack(llvm::X86::MOV32mi, 0x22223333UL, 4),
316 IsMovValueToStack(llvm::X86::MOV16mi, 0x1111UL, 8),
Simon Pilgrim02426892018-09-18 15:35:49 +0000317 testing::A<MCInst>(), IsStackDeallocate(10)));
Guillaume Chatelet5ad29092018-09-18 11:26:27 +0000318}
319
Clement Courbet44b4c542018-06-19 11:28:59 +0000320} // namespace
321} // namespace exegesis