1 //===-- SnippetGeneratorTest.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 //===----------------------------------------------------------------------===//
9 #include "../Common/AssemblerUtils.h"
10 #include "LlvmState.h"
11 #include "MCInstrDescView.h"
12 #include "MipsInstrInfo.h"
13 #include "ParallelSnippetGenerator.h"
14 #include "RegisterAliasing.h"
15 #include "SerialSnippetGenerator.h"
18 #include <unordered_set>
25 using testing::ElementsAre
;
26 using testing::HasSubstr
;
27 using testing::SizeIs
;
29 MATCHER(IsInvalid
, "") { return !arg
.isValid(); }
30 MATCHER(IsReg
, "") { return arg
.isReg(); }
32 template <typename SnippetGeneratorT
>
33 class MipsSnippetGeneratorTest
: public MipsTestBase
{
35 MipsSnippetGeneratorTest() : Generator(State
, SnippetGenerator::Options()) {}
37 std::vector
<CodeTemplate
> checkAndGetCodeTemplates(unsigned Opcode
) {
38 randomGenerator().seed(0); // Initialize seed.
39 const Instruction
&Instr
= State
.getIC().getInstr(Opcode
);
40 auto CodeTemplateOrError
= Generator
.generateCodeTemplates(
41 &Instr
, State
.getRATC().emptyRegisters());
42 EXPECT_FALSE(CodeTemplateOrError
.takeError()); // Valid configuration.
43 return std::move(CodeTemplateOrError
.get());
46 SnippetGeneratorT Generator
;
49 using MipsSerialSnippetGeneratorTest
= MipsSnippetGeneratorTest
<SerialSnippetGenerator
>;
51 using MipsParallelSnippetGeneratorTest
=
52 MipsSnippetGeneratorTest
<ParallelSnippetGenerator
>;
54 TEST_F(MipsSerialSnippetGeneratorTest
, ImplicitSelfDependencyThroughExplicitRegs
) {
56 // - Op0 Explicit Def RegClass(GPR32)
57 // - Op1 Explicit Use RegClass(GPR32)
58 // - Op2 Explicit Use RegClass(GPR32)
62 // - hasAliasingRegisters
63 const unsigned Opcode
= Mips::ADD
;
64 const auto CodeTemplates
= checkAndGetCodeTemplates(Opcode
);
65 ASSERT_THAT(CodeTemplates
, SizeIs(1));
66 const auto &CT
= CodeTemplates
[0];
67 EXPECT_THAT(CT
.Execution
, ExecutionMode::SERIAL_VIA_EXPLICIT_REGS
);
68 ASSERT_THAT(CT
.Instructions
, SizeIs(1));
69 const InstructionTemplate
&IT
= CT
.Instructions
[0];
70 EXPECT_THAT(IT
.getOpcode(), Opcode
);
71 ASSERT_THAT(IT
.getVariableValues(), SizeIs(3));
72 EXPECT_THAT(IT
.getVariableValues(),
73 AnyOf(ElementsAre(IsReg(), IsInvalid(), IsReg()),
74 ElementsAre(IsReg(), IsReg(), IsInvalid())))
75 << "Op0 is either set to Op1 or to Op2";
78 TEST_F(MipsSerialSnippetGeneratorTest
,
79 ImplicitSelfDependencyThroughExplicitRegsForbidAll
) {
81 // - Op0 Explicit Def RegClass(GPR32)
82 // - Op1 Explicit Use RegClass(GPR32)
83 // - Op2 Explicit Use RegClass(GPR32)
87 // - hasAliasingRegisters
88 randomGenerator().seed(0); // Initialize seed.
89 const Instruction
&Instr
= State
.getIC().getInstr(Mips::XOR
);
90 auto AllRegisters
= State
.getRATC().emptyRegisters();
93 Generator
.generateCodeTemplates(&Instr
, AllRegisters
).takeError();
94 EXPECT_TRUE((bool)Error
);
95 consumeError(std::move(Error
));
98 TEST_F(MipsParallelSnippetGeneratorTest
, MemoryUse
) {
99 // LB reads from memory.
101 // - Op0 Explicit Def RegClass(GPR32)
102 // - Op1 Explicit Use Memory RegClass(MSA128F16)
103 // - Op2 Explicit Use Memory
107 // - hasMemoryOperands
108 const unsigned Opcode
= Mips::LB
;
109 const auto CodeTemplates
= checkAndGetCodeTemplates(Opcode
);
110 ASSERT_THAT(CodeTemplates
, SizeIs(1));
111 const auto &CT
= CodeTemplates
[0];
113 HasSubstr("instruction is parallel, repeating a random one."));
114 EXPECT_THAT(CT
.Execution
, ExecutionMode::UNKNOWN
);
115 ASSERT_THAT(CT
.Instructions
,
116 SizeIs(ParallelSnippetGenerator::kMinNumDifferentAddresses
));
117 const InstructionTemplate
&IT
= CT
.Instructions
[0];
118 EXPECT_THAT(IT
.getOpcode(), Opcode
);
119 ASSERT_THAT(IT
.getVariableValues(), SizeIs(3));
120 EXPECT_EQ(IT
.getVariableValues()[0].getReg(), 0u);
121 EXPECT_EQ(IT
.getVariableValues()[2].getImm(), 0);
125 } // namespace exegesis