blob: 463eec2c21ddc3830ad0c033ff9cf6635d511ecf [file] [log] [blame]
Guillaume Chateletc9f727b2018-06-13 13:24:41 +00001//===-- SnippetGeneratorTest.cpp --------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Guillaume Chateletc9f727b2018-06-13 13:24:41 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "../Common/AssemblerUtils.h"
10#include "Latency.h"
11#include "LlvmState.h"
12#include "MCInstrDescView.h"
13#include "RegisterAliasing.h"
Clement Courbet81099012019-10-01 09:20:36 +000014#include "TestBase.h"
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000015#include "Uops.h"
16#include "X86InstrInfo.h"
17
18#include <unordered_set>
19
Fangrui Song32401af2018-10-22 17:10:47 +000020namespace llvm {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000021namespace exegesis {
Guillaume Chateletfb943542018-08-01 14:41:45 +000022
23void InitializeX86ExegesisTarget();
24
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000025namespace {
26
Guillaume Chatelet1ebb6752018-06-20 11:09:36 +000027using testing::AnyOf;
28using testing::ElementsAre;
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +000029using testing::Gt;
Guillaume Chateletef6cef52018-06-20 08:52:30 +000030using testing::HasSubstr;
31using testing::Not;
32using testing::SizeIs;
Clement Courbeta51efc22018-06-25 13:12:02 +000033using testing::UnorderedElementsAre;
Guillaume Chateletef6cef52018-06-20 08:52:30 +000034
35MATCHER(IsInvalid, "") { return !arg.isValid(); }
36MATCHER(IsReg, "") { return arg.isReg(); }
37
Clement Courbet81099012019-10-01 09:20:36 +000038class X86SnippetGeneratorTest : public X86TestBase {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000039protected:
Clement Courbet81099012019-10-01 09:20:36 +000040 X86SnippetGeneratorTest() : InstrInfo(State.getInstrInfo()) {}
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000041
Clement Courbetd422d3a2019-10-09 11:29:21 +000042 const MCInstrInfo &InstrInfo;
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000043};
44
Clement Courbetd939f6d2018-09-13 07:40:53 +000045template <typename SnippetGeneratorT>
Guillaume Chateletef6cef52018-06-20 08:52:30 +000046class SnippetGeneratorTest : public X86SnippetGeneratorTest {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000047protected:
Clement Courbet2cd0f282019-10-08 14:30:24 +000048 SnippetGeneratorTest() : Generator(State, SnippetGenerator::Options()) {}
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000049
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +000050 std::vector<CodeTemplate> checkAndGetCodeTemplates(unsigned Opcode) {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000051 randomGenerator().seed(0); // Initialize seed.
Guillaume Chateletda11b852018-10-24 11:55:06 +000052 const Instruction &Instr = State.getIC().getInstr(Opcode);
Clement Courbet8ef97e12019-09-27 08:04:10 +000053 auto CodeTemplateOrError = Generator.generateCodeTemplates(
54 Instr, State.getRATC().emptyRegisters());
Guillaume Chatelete60866a2018-08-03 09:29:38 +000055 EXPECT_FALSE(CodeTemplateOrError.takeError()); // Valid configuration.
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +000056 return std::move(CodeTemplateOrError.get());
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000057 }
58
Clement Courbetd939f6d2018-09-13 07:40:53 +000059 SnippetGeneratorT Generator;
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000060};
61
Clement Courbetd939f6d2018-09-13 07:40:53 +000062using LatencySnippetGeneratorTest =
63 SnippetGeneratorTest<LatencySnippetGenerator>;
Guillaume Chateletef6cef52018-06-20 08:52:30 +000064
Clement Courbetd939f6d2018-09-13 07:40:53 +000065using UopsSnippetGeneratorTest = SnippetGeneratorTest<UopsSnippetGenerator>;
Guillaume Chateletef6cef52018-06-20 08:52:30 +000066
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +000067TEST_F(LatencySnippetGeneratorTest, ImplicitSelfDependencyThroughImplicitReg) {
68 // - ADC16i16
69 // - Op0 Explicit Use Immediate
70 // - Op1 Implicit Def Reg(AX)
71 // - Op2 Implicit Def Reg(EFLAGS)
72 // - Op3 Implicit Use Reg(AX)
73 // - Op4 Implicit Use Reg(EFLAGS)
74 // - Var0 [Op0]
75 // - hasAliasingImplicitRegisters (execution is always serial)
76 // - hasAliasingRegisters
Clement Courbetd422d3a2019-10-09 11:29:21 +000077 const unsigned Opcode = X86::ADC16i16;
78 EXPECT_THAT(InstrInfo.get(Opcode).getImplicitDefs()[0], X86::AX);
79 EXPECT_THAT(InstrInfo.get(Opcode).getImplicitDefs()[1], X86::EFLAGS);
80 EXPECT_THAT(InstrInfo.get(Opcode).getImplicitUses()[0], X86::AX);
81 EXPECT_THAT(InstrInfo.get(Opcode).getImplicitUses()[1], X86::EFLAGS);
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +000082 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
83 ASSERT_THAT(CodeTemplates, SizeIs(1));
84 const auto &CT = CodeTemplates[0];
85 EXPECT_THAT(CT.Execution, ExecutionMode::ALWAYS_SERIAL_IMPLICIT_REGS_ALIAS);
Guillaume Chatelete60866a2018-08-03 09:29:38 +000086 ASSERT_THAT(CT.Instructions, SizeIs(1));
Guillaume Chatelet70ac0192018-09-27 09:23:04 +000087 const InstructionTemplate &IT = CT.Instructions[0];
88 EXPECT_THAT(IT.getOpcode(), Opcode);
89 ASSERT_THAT(IT.VariableValues, SizeIs(1)); // Imm.
90 EXPECT_THAT(IT.VariableValues[0], IsInvalid()) << "Immediate is not set";
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000091}
92
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +000093TEST_F(LatencySnippetGeneratorTest, ImplicitSelfDependencyThroughTiedRegs) {
94 // - ADD16ri
95 // - Op0 Explicit Def RegClass(GR16)
96 // - Op1 Explicit Use RegClass(GR16) TiedToOp0
97 // - Op2 Explicit Use Immediate
98 // - Op3 Implicit Def Reg(EFLAGS)
99 // - Var0 [Op0,Op1]
100 // - Var1 [Op2]
101 // - hasTiedRegisters (execution is always serial)
102 // - hasAliasingRegisters
Clement Courbetd422d3a2019-10-09 11:29:21 +0000103 const unsigned Opcode = X86::ADD16ri;
104 EXPECT_THAT(InstrInfo.get(Opcode).getImplicitDefs()[0], X86::EFLAGS);
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000105 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
106 ASSERT_THAT(CodeTemplates, SizeIs(1));
107 const auto &CT = CodeTemplates[0];
108 EXPECT_THAT(CT.Execution, ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS);
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000109 ASSERT_THAT(CT.Instructions, SizeIs(1));
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000110 const InstructionTemplate &IT = CT.Instructions[0];
111 EXPECT_THAT(IT.getOpcode(), Opcode);
112 ASSERT_THAT(IT.VariableValues, SizeIs(2));
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000113 EXPECT_THAT(IT.VariableValues[0], IsInvalid()) << "Operand 1 is not set";
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000114 EXPECT_THAT(IT.VariableValues[1], IsInvalid()) << "Operand 2 is not set";
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000115}
116
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000117TEST_F(LatencySnippetGeneratorTest, ImplicitSelfDependencyThroughExplicitRegs) {
118 // - VXORPSrr
119 // - Op0 Explicit Def RegClass(VR128)
120 // - Op1 Explicit Use RegClass(VR128)
121 // - Op2 Explicit Use RegClass(VR128)
122 // - Var0 [Op0]
123 // - Var1 [Op1]
124 // - Var2 [Op2]
125 // - hasAliasingRegisters
Clement Courbetd422d3a2019-10-09 11:29:21 +0000126 const unsigned Opcode = X86::VXORPSrr;
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000127 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
128 ASSERT_THAT(CodeTemplates, SizeIs(1));
129 const auto &CT = CodeTemplates[0];
130 EXPECT_THAT(CT.Execution, ExecutionMode::SERIAL_VIA_EXPLICIT_REGS);
131 ASSERT_THAT(CT.Instructions, SizeIs(1));
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000132 const InstructionTemplate &IT = CT.Instructions[0];
133 EXPECT_THAT(IT.getOpcode(), Opcode);
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000134 ASSERT_THAT(IT.VariableValues, SizeIs(3));
135 EXPECT_THAT(IT.VariableValues,
136 AnyOf(ElementsAre(IsReg(), IsInvalid(), IsReg()),
137 ElementsAre(IsReg(), IsReg(), IsInvalid())))
138 << "Op0 is either set to Op1 or to Op2";
139}
140
Clement Courbet8ef97e12019-09-27 08:04:10 +0000141TEST_F(LatencySnippetGeneratorTest,
142 ImplicitSelfDependencyThroughExplicitRegsForbidAll) {
143 // - VXORPSrr
144 // - Op0 Explicit Def RegClass(VR128)
145 // - Op1 Explicit Use RegClass(VR128)
146 // - Op2 Explicit Use RegClass(VR128)
147 // - Var0 [Op0]
148 // - Var1 [Op1]
149 // - Var2 [Op2]
150 // - hasAliasingRegisters
Clement Courbetd422d3a2019-10-09 11:29:21 +0000151 const unsigned Opcode = X86::VXORPSrr;
Clement Courbet8ef97e12019-09-27 08:04:10 +0000152 randomGenerator().seed(0); // Initialize seed.
153 const Instruction &Instr = State.getIC().getInstr(Opcode);
154 auto AllRegisters = State.getRATC().emptyRegisters();
155 AllRegisters.flip();
156 auto Error = Generator.generateCodeTemplates(Instr, AllRegisters).takeError();
157 EXPECT_TRUE((bool)Error);
Clement Courbetd422d3a2019-10-09 11:29:21 +0000158 consumeError(std::move(Error));
Clement Courbet8ef97e12019-09-27 08:04:10 +0000159}
160
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000161TEST_F(LatencySnippetGeneratorTest, DependencyThroughOtherOpcode) {
162 // - CMP64rr
163 // - Op0 Explicit Use RegClass(GR64)
164 // - Op1 Explicit Use RegClass(GR64)
165 // - Op2 Implicit Def Reg(EFLAGS)
166 // - Var0 [Op0]
167 // - Var1 [Op1]
Clement Courbetd422d3a2019-10-09 11:29:21 +0000168 const unsigned Opcode = X86::CMP64rr;
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000169 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
170 ASSERT_THAT(CodeTemplates, SizeIs(Gt(1U))) << "Many templates are available";
171 for (const auto &CT : CodeTemplates) {
172 EXPECT_THAT(CT.Execution, ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR);
173 ASSERT_THAT(CT.Instructions, SizeIs(2));
174 const InstructionTemplate &IT = CT.Instructions[0];
175 EXPECT_THAT(IT.getOpcode(), Opcode);
176 ASSERT_THAT(IT.VariableValues, SizeIs(2));
177 EXPECT_THAT(IT.VariableValues, AnyOf(ElementsAre(IsReg(), IsInvalid()),
178 ElementsAre(IsInvalid(), IsReg())));
179 EXPECT_THAT(CT.Instructions[1].getOpcode(), Not(Opcode));
180 // TODO: check that the two instructions alias each other.
181 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000182}
183
Clement Courbetd939f6d2018-09-13 07:40:53 +0000184TEST_F(LatencySnippetGeneratorTest, LAHF) {
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000185 // - LAHF
186 // - Op0 Implicit Def Reg(AH)
187 // - Op1 Implicit Use Reg(EFLAGS)
Clement Courbetd422d3a2019-10-09 11:29:21 +0000188 const unsigned Opcode = X86::LAHF;
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000189 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
190 ASSERT_THAT(CodeTemplates, SizeIs(Gt(1U))) << "Many templates are available";
191 for (const auto &CT : CodeTemplates) {
192 EXPECT_THAT(CT.Execution, ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR);
193 ASSERT_THAT(CT.Instructions, SizeIs(2));
194 const InstructionTemplate &IT = CT.Instructions[0];
195 EXPECT_THAT(IT.getOpcode(), Opcode);
196 ASSERT_THAT(IT.VariableValues, SizeIs(0));
197 }
Guillaume Chatelet60e3d582018-06-13 13:53:56 +0000198}
199
Clement Courbetd939f6d2018-09-13 07:40:53 +0000200TEST_F(UopsSnippetGeneratorTest, ParallelInstruction) {
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000201 // - BNDCL32rr
202 // - Op0 Explicit Use RegClass(BNDR)
203 // - Op1 Explicit Use RegClass(GR32)
204 // - Var0 [Op0]
205 // - Var1 [Op1]
Clement Courbetd422d3a2019-10-09 11:29:21 +0000206 const unsigned Opcode = X86::BNDCL32rr;
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000207 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
208 ASSERT_THAT(CodeTemplates, SizeIs(1));
209 const auto &CT = CodeTemplates[0];
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000210 EXPECT_THAT(CT.Info, HasSubstr("parallel"));
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000211 EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000212 ASSERT_THAT(CT.Instructions, SizeIs(1));
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000213 const InstructionTemplate &IT = CT.Instructions[0];
214 EXPECT_THAT(IT.getOpcode(), Opcode);
215 ASSERT_THAT(IT.VariableValues, SizeIs(2));
216 EXPECT_THAT(IT.VariableValues[0], IsInvalid());
217 EXPECT_THAT(IT.VariableValues[1], IsInvalid());
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000218}
219
Clement Courbetd939f6d2018-09-13 07:40:53 +0000220TEST_F(UopsSnippetGeneratorTest, SerialInstruction) {
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000221 // - CDQ
222 // - Op0 Implicit Def Reg(EAX)
223 // - Op1 Implicit Def Reg(EDX)
224 // - Op2 Implicit Use Reg(EAX)
225 // - hasAliasingImplicitRegisters (execution is always serial)
226 // - hasAliasingRegisters
Clement Courbetd422d3a2019-10-09 11:29:21 +0000227 const unsigned Opcode = X86::CDQ;
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000228 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
229 ASSERT_THAT(CodeTemplates, SizeIs(1));
230 const auto &CT = CodeTemplates[0];
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000231 EXPECT_THAT(CT.Info, HasSubstr("serial"));
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000232 EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000233 ASSERT_THAT(CT.Instructions, SizeIs(1));
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000234 const InstructionTemplate &IT = CT.Instructions[0];
235 EXPECT_THAT(IT.getOpcode(), Opcode);
236 ASSERT_THAT(IT.VariableValues, SizeIs(0));
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000237}
238
Clement Courbetd939f6d2018-09-13 07:40:53 +0000239TEST_F(UopsSnippetGeneratorTest, StaticRenaming) {
Craig Toppere0bfeb52019-04-05 19:27:41 +0000240 // CMOV32rr has tied variables, we enumerate the possible values to execute
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000241 // as many in parallel as possible.
242
Craig Toppere0bfeb52019-04-05 19:27:41 +0000243 // - CMOV32rr
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000244 // - Op0 Explicit Def RegClass(GR32)
245 // - Op1 Explicit Use RegClass(GR32) TiedToOp0
246 // - Op2 Explicit Use RegClass(GR32)
Craig Toppere0bfeb52019-04-05 19:27:41 +0000247 // - Op3 Explicit Use Immediate
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000248 // - Op3 Implicit Use Reg(EFLAGS)
249 // - Var0 [Op0,Op1]
250 // - Var1 [Op2]
251 // - hasTiedRegisters (execution is always serial)
252 // - hasAliasingRegisters
Clement Courbetd422d3a2019-10-09 11:29:21 +0000253 const unsigned Opcode = X86::CMOV32rr;
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000254 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
255 ASSERT_THAT(CodeTemplates, SizeIs(1));
256 const auto &CT = CodeTemplates[0];
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000257 EXPECT_THAT(CT.Info, HasSubstr("static renaming"));
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000258 EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000259 constexpr const unsigned kInstructionCount = 15;
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000260 ASSERT_THAT(CT.Instructions, SizeIs(kInstructionCount));
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000261 std::unordered_set<unsigned> AllDefRegisters;
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000262 for (const auto &IT : CT.Instructions) {
Craig Toppere0bfeb52019-04-05 19:27:41 +0000263 ASSERT_THAT(IT.VariableValues, SizeIs(3));
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000264 AllDefRegisters.insert(IT.VariableValues[0].getReg());
Guillaume Chateletef6cef52018-06-20 08:52:30 +0000265 }
266 EXPECT_THAT(AllDefRegisters, SizeIs(kInstructionCount))
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000267 << "Each instruction writes to a different register";
268}
269
Clement Courbetd939f6d2018-09-13 07:40:53 +0000270TEST_F(UopsSnippetGeneratorTest, NoTiedVariables) {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000271 // CMOV_GR32 has no tied variables, we make sure def and use are different
272 // from each other.
273
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000274 // - CMOV_GR32
275 // - Op0 Explicit Def RegClass(GR32)
276 // - Op1 Explicit Use RegClass(GR32)
277 // - Op2 Explicit Use RegClass(GR32)
278 // - Op3 Explicit Use Immediate
279 // - Op4 Implicit Use Reg(EFLAGS)
280 // - Var0 [Op0]
281 // - Var1 [Op1]
282 // - Var2 [Op2]
283 // - Var3 [Op3]
284 // - hasAliasingRegisters
Clement Courbetd422d3a2019-10-09 11:29:21 +0000285 const unsigned Opcode = X86::CMOV_GR32;
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000286 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
287 ASSERT_THAT(CodeTemplates, SizeIs(1));
288 const auto &CT = CodeTemplates[0];
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000289 EXPECT_THAT(CT.Info, HasSubstr("no tied variables"));
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000290 EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000291 ASSERT_THAT(CT.Instructions, SizeIs(1));
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000292 const InstructionTemplate &IT = CT.Instructions[0];
293 EXPECT_THAT(IT.getOpcode(), Opcode);
294 ASSERT_THAT(IT.VariableValues, SizeIs(4));
295 EXPECT_THAT(IT.VariableValues[0].getReg(), Not(IT.VariableValues[1].getReg()))
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000296 << "Def is different from first Use";
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000297 EXPECT_THAT(IT.VariableValues[0].getReg(), Not(IT.VariableValues[2].getReg()))
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000298 << "Def is different from second Use";
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000299 EXPECT_THAT(IT.VariableValues[3], IsInvalid());
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000300}
301
Clement Courbetd939f6d2018-09-13 07:40:53 +0000302TEST_F(UopsSnippetGeneratorTest, MemoryUse) {
Guillaume Chateletfb943542018-08-01 14:41:45 +0000303 // Mov32rm reads from memory.
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000304 // - MOV32rm
305 // - Op0 Explicit Def RegClass(GR32)
306 // - Op1 Explicit Use Memory RegClass(GR8)
307 // - Op2 Explicit Use Memory
308 // - Op3 Explicit Use Memory RegClass(GRH8)
309 // - Op4 Explicit Use Memory
310 // - Op5 Explicit Use Memory RegClass(SEGMENT_REG)
311 // - Var0 [Op0]
312 // - Var1 [Op1]
313 // - Var2 [Op2]
314 // - Var3 [Op3]
315 // - Var4 [Op4]
316 // - Var5 [Op5]
317 // - hasMemoryOperands
318 // - hasAliasingRegisters
Clement Courbetd422d3a2019-10-09 11:29:21 +0000319 const unsigned Opcode = X86::MOV32rm;
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000320 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
321 ASSERT_THAT(CodeTemplates, SizeIs(1));
322 const auto &CT = CodeTemplates[0];
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000323 EXPECT_THAT(CT.Info, HasSubstr("no tied variables"));
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000324 EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);
Guillaume Chatelete60866a2018-08-03 09:29:38 +0000325 ASSERT_THAT(CT.Instructions,
Clement Courbetd939f6d2018-09-13 07:40:53 +0000326 SizeIs(UopsSnippetGenerator::kMinNumDifferentAddresses));
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000327 const InstructionTemplate &IT = CT.Instructions[0];
328 EXPECT_THAT(IT.getOpcode(), Opcode);
329 ASSERT_THAT(IT.VariableValues, SizeIs(6));
330 EXPECT_EQ(IT.VariableValues[2].getImm(), 1);
331 EXPECT_EQ(IT.VariableValues[3].getReg(), 0u);
332 EXPECT_EQ(IT.VariableValues[4].getImm(), 0);
333 EXPECT_EQ(IT.VariableValues[5].getReg(), 0u);
Guillaume Chateletfb943542018-08-01 14:41:45 +0000334}
335
Clement Courbet8ef97e12019-09-27 08:04:10 +0000336class FakeSnippetGenerator : public SnippetGenerator {
337public:
Clement Courbet2cd0f282019-10-08 14:30:24 +0000338 FakeSnippetGenerator(const LLVMState &State, const Options &Opts)
339 : SnippetGenerator(State, Opts) {}
Clement Courbet8ef97e12019-09-27 08:04:10 +0000340
341 Instruction createInstruction(unsigned Opcode) {
342 return State.getIC().getInstr(Opcode);
343 }
344
345private:
Clement Courbetd422d3a2019-10-09 11:29:21 +0000346 Expected<std::vector<CodeTemplate>>
Clement Courbet8ef97e12019-09-27 08:04:10 +0000347 generateCodeTemplates(const Instruction &, const BitVector &) const override {
Clement Courbetd422d3a2019-10-09 11:29:21 +0000348 return make_error<StringError>("not implemented", inconvertibleErrorCode());
Clement Courbet8ef97e12019-09-27 08:04:10 +0000349 }
350};
351
352using FakeSnippetGeneratorTest = SnippetGeneratorTest<FakeSnippetGenerator>;
353
354testing::Matcher<const RegisterValue &> IsRegisterValue(unsigned Reg,
Clement Courbetd422d3a2019-10-09 11:29:21 +0000355 APInt Value) {
Clement Courbet8ef97e12019-09-27 08:04:10 +0000356 return testing::AllOf(testing::Field(&RegisterValue::Register, Reg),
357 testing::Field(&RegisterValue::Value, Value));
358}
359
360TEST_F(FakeSnippetGeneratorTest, MemoryUse_Movsb) {
Guillaume Chateletfb943542018-08-01 14:41:45 +0000361 // MOVSB writes to scratch memory register.
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000362 // - MOVSB
363 // - Op0 Explicit Use Memory RegClass(GR8)
364 // - Op1 Explicit Use Memory RegClass(GR8)
365 // - Op2 Explicit Use Memory RegClass(SEGMENT_REG)
366 // - Op3 Implicit Def Reg(EDI)
367 // - Op4 Implicit Def Reg(ESI)
368 // - Op5 Implicit Use Reg(EDI)
369 // - Op6 Implicit Use Reg(ESI)
370 // - Op7 Implicit Use Reg(DF)
371 // - Var0 [Op0]
372 // - Var1 [Op1]
373 // - Var2 [Op2]
374 // - hasMemoryOperands
375 // - hasAliasingImplicitRegisters (execution is always serial)
376 // - hasAliasingRegisters
Clement Courbetd422d3a2019-10-09 11:29:21 +0000377 const unsigned Opcode = X86::MOVSB;
Guillaume Chateletda11b852018-10-24 11:55:06 +0000378 const Instruction &Instr = State.getIC().getInstr(Opcode);
Clement Courbet9431b722019-09-27 12:56:24 +0000379 auto Error =
380 Generator.generateConfigurations(Instr, State.getRATC().emptyRegisters())
381 .takeError();
Guillaume Chateletfb943542018-08-01 14:41:45 +0000382 EXPECT_TRUE((bool)Error);
Clement Courbetd422d3a2019-10-09 11:29:21 +0000383 consumeError(std::move(Error));
Guillaume Chateletfb943542018-08-01 14:41:45 +0000384}
385
Guillaume Chateletc96a97b2018-09-20 12:22:18 +0000386TEST_F(FakeSnippetGeneratorTest, ComputeRegisterInitialValuesAdd16ri) {
Clement Courbeta51efc22018-06-25 13:12:02 +0000387 // ADD16ri:
388 // explicit def 0 : reg RegClass=GR16
389 // explicit use 1 : reg RegClass=GR16 | TIED_TO:0
390 // explicit use 2 : imm
391 // implicit def : EFLAGS
Clement Courbetd422d3a2019-10-09 11:29:21 +0000392 InstructionTemplate IT(Generator.createInstruction(X86::ADD16ri));
393 IT.getValueFor(IT.Instr.Variables[0]) = MCOperand::createReg(X86::AX);
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000394 std::vector<InstructionTemplate> Snippet;
395 Snippet.push_back(std::move(IT));
Guillaume Chateletc96a97b2018-09-20 12:22:18 +0000396 const auto RIV = Generator.computeRegisterInitialValues(Snippet);
Clement Courbetd422d3a2019-10-09 11:29:21 +0000397 EXPECT_THAT(RIV, ElementsAre(IsRegisterValue(X86::AX, APInt())));
Clement Courbeta51efc22018-06-25 13:12:02 +0000398}
399
Guillaume Chateletc96a97b2018-09-20 12:22:18 +0000400TEST_F(FakeSnippetGeneratorTest, ComputeRegisterInitialValuesAdd64rr) {
Clement Courbeta51efc22018-06-25 13:12:02 +0000401 // ADD64rr:
402 // mov64ri rax, 42
403 // add64rr rax, rax, rbx
404 // -> only rbx needs defining.
Guillaume Chatelet70ac0192018-09-27 09:23:04 +0000405 std::vector<InstructionTemplate> Snippet;
Clement Courbeta51efc22018-06-25 13:12:02 +0000406 {
Clement Courbetd422d3a2019-10-09 11:29:21 +0000407 InstructionTemplate Mov(Generator.createInstruction(X86::MOV64ri));
408 Mov.getValueFor(Mov.Instr.Variables[0]) = MCOperand::createReg(X86::RAX);
409 Mov.getValueFor(Mov.Instr.Variables[1]) = MCOperand::createImm(42);
Clement Courbeta51efc22018-06-25 13:12:02 +0000410 Snippet.push_back(std::move(Mov));
411 }
412 {
Clement Courbetd422d3a2019-10-09 11:29:21 +0000413 InstructionTemplate Add(Generator.createInstruction(X86::ADD64rr));
414 Add.getValueFor(Add.Instr.Variables[0]) = MCOperand::createReg(X86::RAX);
415 Add.getValueFor(Add.Instr.Variables[1]) = MCOperand::createReg(X86::RBX);
Clement Courbeta51efc22018-06-25 13:12:02 +0000416 Snippet.push_back(std::move(Add));
417 }
418
Guillaume Chateletc96a97b2018-09-20 12:22:18 +0000419 const auto RIV = Generator.computeRegisterInitialValues(Snippet);
Clement Courbetd422d3a2019-10-09 11:29:21 +0000420 EXPECT_THAT(RIV, ElementsAre(IsRegisterValue(X86::RBX, APInt())));
Clement Courbeta51efc22018-06-25 13:12:02 +0000421}
422
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000423} // namespace
424} // namespace exegesis
Fangrui Song32401af2018-10-22 17:10:47 +0000425} // namespace llvm