1 //===-- SnippetGeneratorTest.cpp --------------------------------*- C++ -*-===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "../Common/AssemblerUtils.h" 10 #include "LlvmState.h" 11 #include "MCInstrDescView.h" 12 #include "PPCInstrInfo.h" 13 #include "ParallelSnippetGenerator.h" 14 #include "RegisterAliasing.h" 15 #include "SerialSnippetGenerator.h" 16 #include "TestBase.h" 17 18 #include <unordered_set> 19 20 namespace llvm { 21 namespace exegesis { 22 namespace { 23 24 using testing::AnyOf; 25 using testing::ElementsAre; 26 using testing::HasSubstr; 27 using testing::SizeIs; 28 29 MATCHER(IsInvalid, "") { return !arg.isValid(); } 30 MATCHER(IsReg, "") { return arg.isReg(); } 31 32 class PPCSnippetGeneratorTest : public PPCTestBase {}; 33 34 template <typename SnippetGeneratorT> 35 class SnippetGeneratorTest : public PPCSnippetGeneratorTest { 36 protected: 37 SnippetGeneratorTest() : Generator(State, SnippetGenerator::Options()) {} 38 39 std::vector<CodeTemplate> checkAndGetCodeTemplates(unsigned Opcode) { 40 randomGenerator().seed(0); // Initialize seed. 41 const Instruction &Instr = State.getIC().getInstr(Opcode); 42 auto CodeTemplateOrError = Generator.generateCodeTemplates( 43 &Instr, State.getRATC().emptyRegisters()); 44 EXPECT_FALSE(CodeTemplateOrError.takeError()); // Valid configuration. 45 return std::move(CodeTemplateOrError.get()); 46 } 47 48 SnippetGeneratorT Generator; 49 }; 50 51 using SerialSnippetGeneratorTest = SnippetGeneratorTest<SerialSnippetGenerator>; 52 53 using ParallelSnippetGeneratorTest = 54 SnippetGeneratorTest<ParallelSnippetGenerator>; 55 56 TEST_F(SerialSnippetGeneratorTest, ImplicitSelfDependencyThroughExplicitRegs) { 57 // - ADD8 58 // - Op0 Explicit Def RegClass(G8RC) 59 // - Op1 Explicit Use RegClass(G8RC) 60 // - Op2 Explicit Use RegClass(G8RC) 61 // - Var0 [Op0] 62 // - Var1 [Op1] 63 // - Var2 [Op2] 64 // - hasAliasingRegisters 65 const unsigned Opcode = PPC::ADD8; 66 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode); 67 ASSERT_THAT(CodeTemplates, SizeIs(1)); 68 const auto &CT = CodeTemplates[0]; 69 EXPECT_THAT(CT.Execution, ExecutionMode::SERIAL_VIA_EXPLICIT_REGS); 70 ASSERT_THAT(CT.Instructions, SizeIs(1)); 71 const InstructionTemplate &IT = CT.Instructions[0]; 72 EXPECT_THAT(IT.getOpcode(), Opcode); 73 ASSERT_THAT(IT.getVariableValues(), SizeIs(3)); 74 EXPECT_THAT(IT.getVariableValues(), 75 AnyOf(ElementsAre(IsReg(), IsInvalid(), IsReg()), 76 ElementsAre(IsReg(), IsReg(), IsInvalid()))) 77 << "Op0 is either set to Op1 or to Op2"; 78 } 79 80 TEST_F(SerialSnippetGeneratorTest, ImplicitSelfDependencyThroughTiedRegs) { 81 82 // - RLDIMI 83 // - Op0 Explicit Def RegClass(G8RC) 84 // - Op1 Explicit Use RegClass(G8RC) TiedToOp0 85 // - Op2 Explicit Use RegClass(G8RC) 86 // - Op3 Explicit Use Immediate 87 // - Op4 Explicit Use Immediate 88 // - Var0 [Op0,Op1] 89 // - Var1 [Op2] 90 // - Var2 [Op3] 91 // - Var3 [Op4] 92 // - hasTiedRegisters (execution is always serial) 93 // - hasAliasingRegisters 94 // - RLDIMI 95 const unsigned Opcode = PPC::RLDIMI; 96 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode); 97 ASSERT_THAT(CodeTemplates, SizeIs(1)); 98 const auto &CT = CodeTemplates[0]; 99 EXPECT_THAT(CT.Execution, ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS); 100 ASSERT_THAT(CT.Instructions, SizeIs(1)); 101 const InstructionTemplate &IT = CT.Instructions[0]; 102 EXPECT_THAT(IT.getOpcode(), Opcode); 103 ASSERT_THAT(IT.getVariableValues(), SizeIs(4)); 104 EXPECT_THAT(IT.getVariableValues()[2], IsInvalid()) << "Operand 1 is not set"; 105 EXPECT_THAT(IT.getVariableValues()[3], IsInvalid()) << "Operand 2 is not set"; 106 } 107 108 TEST_F(ParallelSnippetGeneratorTest, MemoryUse) { 109 // - LDX 110 // - Op0 Explicit Def RegClass(G8RC) 111 // - Op1 Explicit Use Memory RegClass(GPRC) 112 // - Op2 Explicit Use Memory RegClass(VSSRC) 113 // - Var0 [Op0] 114 // - Var1 [Op1] 115 // - Var2 [Op2] 116 // - hasMemoryOperands 117 // - hasAliasingRegisters 118 const unsigned Opcode = PPC::LDX; 119 const auto CodeTemplates = checkAndGetCodeTemplates(Opcode); 120 ASSERT_THAT(CodeTemplates, SizeIs(1)); 121 const auto &CT = CodeTemplates[0]; 122 EXPECT_THAT(CT.Info, HasSubstr("instruction has no tied variables picking " 123 "Uses different from defs")); 124 EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN); 125 ASSERT_THAT(CT.Instructions, 126 SizeIs(ParallelSnippetGenerator::kMinNumDifferentAddresses)); 127 const InstructionTemplate &IT = CT.Instructions[0]; 128 EXPECT_THAT(IT.getOpcode(), Opcode); 129 ASSERT_THAT(IT.getVariableValues(), SizeIs(3)); 130 EXPECT_EQ(IT.getVariableValues()[1].getReg(), PPC::X1); 131 EXPECT_EQ(IT.getVariableValues()[2].getReg(), PPC::X13); 132 } 133 134 } // namespace 135 } // namespace exegesis 136 } // namespace llvm 137