[llvm-branch-commits] [llvm] c8ec685 - [llvm-exegesis][PowerPC] Add more register classes
Jinsong Ji via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Dec 4 07:06:44 PST 2020
Author: Jinsong Ji
Date: 2020-12-04T15:02:12Z
New Revision: c8ec685ca555459051125f9c0194ceee19e959d7
URL: https://github.com/llvm/llvm-project/commit/c8ec685ca555459051125f9c0194ceee19e959d7
DIFF: https://github.com/llvm/llvm-project/commit/c8ec685ca555459051125f9c0194ceee19e959d7.diff
LOG: [llvm-exegesis][PowerPC] Add more register classes
This PR adds more register class support in PowerPC,
mark OperandType for imm and memory operands.
Also added more unit tests for SnippetGenerator.
Reviewed By: #powerpc, steven.zhang
Differential Revision: https://reviews.llvm.org/D88044
Added:
llvm/unittests/tools/llvm-exegesis/PowerPC/SnippetGeneratorTest.cpp
llvm/unittests/tools/llvm-exegesis/PowerPC/TestBase.h
Modified:
llvm/lib/Target/PowerPC/PPCInstr64Bit.td
llvm/lib/Target/PowerPC/PPCInstrInfo.td
llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
llvm/unittests/tools/llvm-exegesis/PowerPC/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index eaf20fdc0173..931109e2cbc4 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -19,12 +19,14 @@ def s16imm64 : Operand<i64> {
let EncoderMethod = "getImm16Encoding";
let ParserMatchClass = PPCS16ImmAsmOperand;
let DecoderMethod = "decodeSImmOperand<16>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def u16imm64 : Operand<i64> {
let PrintMethod = "printU16ImmOperand";
let EncoderMethod = "getImm16Encoding";
let ParserMatchClass = PPCU16ImmAsmOperand;
let DecoderMethod = "decodeUImmOperand<16>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def s17imm64 : Operand<i64> {
// This operand type is used for addis/lis to allow the assembler parser
@@ -34,6 +36,7 @@ def s17imm64 : Operand<i64> {
let EncoderMethod = "getImm16Encoding";
let ParserMatchClass = PPCS17ImmAsmOperand;
let DecoderMethod = "decodeSImmOperand<16>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def tocentry : Operand<iPTR> {
let MIOperandInfo = (ops i64imm:$imm);
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index 1496accf83d8..2dc575923da7 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -666,6 +666,7 @@ def PPCU1ImmAsmOperand : AsmOperandClass {
def u1imm : Operand<i32> {
let PrintMethod = "printU1ImmOperand";
let ParserMatchClass = PPCU1ImmAsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCU2ImmAsmOperand : AsmOperandClass {
@@ -675,6 +676,7 @@ def PPCU2ImmAsmOperand : AsmOperandClass {
def u2imm : Operand<i32> {
let PrintMethod = "printU2ImmOperand";
let ParserMatchClass = PPCU2ImmAsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCATBitsAsHintAsmOperand : AsmOperandClass {
@@ -684,6 +686,7 @@ def PPCATBitsAsHintAsmOperand : AsmOperandClass {
def atimm : Operand<i32> {
let PrintMethod = "printATBitsAsHint";
let ParserMatchClass = PPCATBitsAsHintAsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCU3ImmAsmOperand : AsmOperandClass {
@@ -693,6 +696,7 @@ def PPCU3ImmAsmOperand : AsmOperandClass {
def u3imm : Operand<i32> {
let PrintMethod = "printU3ImmOperand";
let ParserMatchClass = PPCU3ImmAsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCU4ImmAsmOperand : AsmOperandClass {
@@ -702,6 +706,7 @@ def PPCU4ImmAsmOperand : AsmOperandClass {
def u4imm : Operand<i32> {
let PrintMethod = "printU4ImmOperand";
let ParserMatchClass = PPCU4ImmAsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCS5ImmAsmOperand : AsmOperandClass {
let Name = "S5Imm"; let PredicateMethod = "isS5Imm";
@@ -711,6 +716,7 @@ def s5imm : Operand<i32> {
let PrintMethod = "printS5ImmOperand";
let ParserMatchClass = PPCS5ImmAsmOperand;
let DecoderMethod = "decodeSImmOperand<5>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCU5ImmAsmOperand : AsmOperandClass {
let Name = "U5Imm"; let PredicateMethod = "isU5Imm";
@@ -720,6 +726,7 @@ def u5imm : Operand<i32> {
let PrintMethod = "printU5ImmOperand";
let ParserMatchClass = PPCU5ImmAsmOperand;
let DecoderMethod = "decodeUImmOperand<5>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCU6ImmAsmOperand : AsmOperandClass {
let Name = "U6Imm"; let PredicateMethod = "isU6Imm";
@@ -729,6 +736,7 @@ def u6imm : Operand<i32> {
let PrintMethod = "printU6ImmOperand";
let ParserMatchClass = PPCU6ImmAsmOperand;
let DecoderMethod = "decodeUImmOperand<6>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCU7ImmAsmOperand : AsmOperandClass {
let Name = "U7Imm"; let PredicateMethod = "isU7Imm";
@@ -738,6 +746,7 @@ def u7imm : Operand<i32> {
let PrintMethod = "printU7ImmOperand";
let ParserMatchClass = PPCU7ImmAsmOperand;
let DecoderMethod = "decodeUImmOperand<7>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCU8ImmAsmOperand : AsmOperandClass {
let Name = "U8Imm"; let PredicateMethod = "isU8Imm";
@@ -747,6 +756,7 @@ def u8imm : Operand<i32> {
let PrintMethod = "printU8ImmOperand";
let ParserMatchClass = PPCU8ImmAsmOperand;
let DecoderMethod = "decodeUImmOperand<8>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCU10ImmAsmOperand : AsmOperandClass {
let Name = "U10Imm"; let PredicateMethod = "isU10Imm";
@@ -756,6 +766,7 @@ def u10imm : Operand<i32> {
let PrintMethod = "printU10ImmOperand";
let ParserMatchClass = PPCU10ImmAsmOperand;
let DecoderMethod = "decodeUImmOperand<10>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCU12ImmAsmOperand : AsmOperandClass {
let Name = "U12Imm"; let PredicateMethod = "isU12Imm";
@@ -765,6 +776,7 @@ def u12imm : Operand<i32> {
let PrintMethod = "printU12ImmOperand";
let ParserMatchClass = PPCU12ImmAsmOperand;
let DecoderMethod = "decodeUImmOperand<12>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCS16ImmAsmOperand : AsmOperandClass {
let Name = "S16Imm"; let PredicateMethod = "isS16Imm";
@@ -775,6 +787,7 @@ def s16imm : Operand<i32> {
let EncoderMethod = "getImm16Encoding";
let ParserMatchClass = PPCS16ImmAsmOperand;
let DecoderMethod = "decodeSImmOperand<16>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCU16ImmAsmOperand : AsmOperandClass {
let Name = "U16Imm"; let PredicateMethod = "isU16Imm";
@@ -785,6 +798,7 @@ def u16imm : Operand<i32> {
let EncoderMethod = "getImm16Encoding";
let ParserMatchClass = PPCU16ImmAsmOperand;
let DecoderMethod = "decodeUImmOperand<16>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCS17ImmAsmOperand : AsmOperandClass {
let Name = "S17Imm"; let PredicateMethod = "isS17Imm";
@@ -798,6 +812,7 @@ def s17imm : Operand<i32> {
let EncoderMethod = "getImm16Encoding";
let ParserMatchClass = PPCS17ImmAsmOperand;
let DecoderMethod = "decodeSImmOperand<16>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCS34ImmAsmOperand : AsmOperandClass {
let Name = "S34Imm";
@@ -809,12 +824,14 @@ def s34imm : Operand<i64> {
let EncoderMethod = "getImm34EncodingNoPCRel";
let ParserMatchClass = PPCS34ImmAsmOperand;
let DecoderMethod = "decodeSImmOperand<34>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def s34imm_pcrel : Operand<i64> {
let PrintMethod = "printS34ImmOperand";
let EncoderMethod = "getImm34EncodingPCRel";
let ParserMatchClass = PPCS34ImmAsmOperand;
let DecoderMethod = "decodeSImmOperand<34>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PPCImmZeroAsmOperand : AsmOperandClass {
let Name = "ImmZero";
@@ -825,6 +842,7 @@ def immZero : Operand<i32> {
let PrintMethod = "printImmZeroOperand";
let ParserMatchClass = PPCImmZeroAsmOperand;
let DecoderMethod = "decodeImmZeroOperand";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def fpimm0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>;
@@ -970,40 +988,47 @@ def memri : Operand<iPTR> {
let MIOperandInfo = (ops dispRI:$imm, ptr_rc_nor0:$reg);
let EncoderMethod = "getMemRIEncoding";
let DecoderMethod = "decodeMemRIOperands";
+ let OperandType = "OPERAND_MEMORY";
}
def memrr : Operand<iPTR> {
let PrintMethod = "printMemRegReg";
let MIOperandInfo = (ops ptr_rc_nor0:$ptrreg, ptr_rc_idx:$offreg);
+ let OperandType = "OPERAND_MEMORY";
}
def memrix : Operand<iPTR> { // memri where the imm is 4-aligned.
let PrintMethod = "printMemRegImm";
let MIOperandInfo = (ops dispRIX:$imm, ptr_rc_nor0:$reg);
let EncoderMethod = "getMemRIXEncoding";
let DecoderMethod = "decodeMemRIXOperands";
+ let OperandType = "OPERAND_MEMORY";
}
def memrix16 : Operand<iPTR> { // memri, imm is 16-aligned, 12-bit, Inst{16:27}
let PrintMethod = "printMemRegImm";
let MIOperandInfo = (ops dispRIX16:$imm, ptr_rc_nor0:$reg);
let EncoderMethod = "getMemRIX16Encoding";
let DecoderMethod = "decodeMemRIX16Operands";
+ let OperandType = "OPERAND_MEMORY";
}
def spe8dis : Operand<iPTR> { // SPE displacement where the imm is 8-aligned.
let PrintMethod = "printMemRegImm";
let MIOperandInfo = (ops dispSPE8:$imm, ptr_rc_nor0:$reg);
let EncoderMethod = "getSPE8DisEncoding";
let DecoderMethod = "decodeSPE8Operands";
+ let OperandType = "OPERAND_MEMORY";
}
def spe4dis : Operand<iPTR> { // SPE displacement where the imm is 4-aligned.
let PrintMethod = "printMemRegImm";
let MIOperandInfo = (ops dispSPE4:$imm, ptr_rc_nor0:$reg);
let EncoderMethod = "getSPE4DisEncoding";
let DecoderMethod = "decodeSPE4Operands";
+ let OperandType = "OPERAND_MEMORY";
}
def spe2dis : Operand<iPTR> { // SPE displacement where the imm is 2-aligned.
let PrintMethod = "printMemRegImm";
let MIOperandInfo = (ops dispSPE2:$imm, ptr_rc_nor0:$reg);
let EncoderMethod = "getSPE2DisEncoding";
let DecoderMethod = "decodeSPE2Operands";
+ let OperandType = "OPERAND_MEMORY";
}
// A single-register address. This is used with the SjLj
@@ -1011,6 +1036,7 @@ def spe2dis : Operand<iPTR> { // SPE displacement where the imm is 2-aligned.
// G8RC_NOX0 registers.
def memr : Operand<iPTR> {
let MIOperandInfo = (ops ptr_rc_nor0:$ptrreg);
+ let OperandType = "OPERAND_MEMORY";
}
def PPCTLSRegOperand : AsmOperandClass {
let Name = "TLSReg"; let PredicateMethod = "isTLSReg";
diff --git a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
index 771b01a5790b..54d42dfd22e5 100644
--- a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
@@ -13,6 +13,14 @@
namespace llvm {
namespace exegesis {
+// Helper to fill a memory operand with a value.
+static void setMemOp(InstructionTemplate &IT, int OpIdx,
+ const MCOperand &OpVal) {
+ const auto Op = IT.getInstr().Operands[OpIdx];
+ assert(Op.isExplicit() && "invalid memory pattern");
+ IT.getValueFor(Op) = OpVal;
+}
+
#include "PPCGenExegesis.inc"
namespace {
@@ -26,6 +34,9 @@ class ExegesisPowerPCTarget : public ExegesisTarget {
bool matchesArch(Triple::ArchType Arch) const override {
return Arch == Triple::ppc64le;
}
+ unsigned getScratchMemoryRegister(const Triple &) const override;
+ void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
+ unsigned Offset) const override;
};
} // end anonymous namespace
@@ -44,19 +55,75 @@ static MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
const APInt &Value) {
if (Value.getBitWidth() > RegBitWidth)
llvm_unreachable("Value must fit in the Register");
+ // We don't really care the value in reg, ignore the 16 bit
+ // restriction for now.
+ // TODO: make sure we get the exact value in reg if needed.
return MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
.addReg(Reg)
.addImm(Value.getZExtValue());
}
+unsigned
+ExegesisPowerPCTarget::getScratchMemoryRegister(const Triple &TT) const {
+ // R13 is reserved as Thread Pointer, we won't use threading in benchmark, so
+ // use it as scratch memory register
+ return TT.isArch64Bit() ? PPC::X13 : PPC::R13;
+}
+
+void ExegesisPowerPCTarget::fillMemoryOperands(InstructionTemplate &IT,
+ unsigned Reg,
+ unsigned Offset) const {
+ int MemOpIdx = 0;
+ if (IT.getInstr().hasTiedRegisters())
+ MemOpIdx = 1;
+ int DispOpIdx = MemOpIdx + 1;
+ const auto DispOp = IT.getInstr().Operands[DispOpIdx];
+ if (DispOp.isReg())
+ // We don't really care about the real address in snippets,
+ // So hardcode X1 for X-form Memory Operations for simplicity.
+ // TODO: materialize the offset into a reggister
+ setMemOp(IT, DispOpIdx, MCOperand::createReg(PPC::X1));
+ else
+ setMemOp(IT, DispOpIdx, MCOperand::createImm(Offset)); // Disp
+ setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg)); // BaseReg
+}
+
std::vector<MCInst> ExegesisPowerPCTarget::setRegTo(const MCSubtargetInfo &STI,
unsigned Reg,
const APInt &Value) const {
+ // X11 is optional use in function linkage, should be the least used one
+ // Use it as scratch reg to load immediate.
+ unsigned ScratchImmReg = PPC::X11;
+
if (PPC::GPRCRegClass.contains(Reg))
return {loadImmediate(Reg, 32, Value)};
if (PPC::G8RCRegClass.contains(Reg))
return {loadImmediate(Reg, 64, Value)};
- errs() << "setRegTo is not implemented, results will be unreliable\n";
+ if (PPC::F4RCRegClass.contains(Reg))
+ return {loadImmediate(ScratchImmReg, 64, Value),
+ MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
+ // We don't care the real value in reg, so set 64 bits or duplicate 64 bits
+ // for simplicity.
+ // TODO: update these if we need a accurate 128 values in registers.
+ if (PPC::VRRCRegClass.contains(Reg))
+ return {loadImmediate(ScratchImmReg, 64, Value),
+ MCInstBuilder(PPC::MTVRD).addReg(Reg).addReg(ScratchImmReg)};
+ if (PPC::VSRCRegClass.contains(Reg))
+ return {loadImmediate(ScratchImmReg, 64, Value),
+ MCInstBuilder(PPC::MTVSRDD)
+ .addReg(Reg)
+ .addReg(ScratchImmReg)
+ .addReg(ScratchImmReg)};
+ if (PPC::VFRCRegClass.contains(Reg))
+ return {loadImmediate(ScratchImmReg, 64, Value),
+ MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
+ // SPE not supported yet
+ if (PPC::SPERCRegClass.contains(Reg)) {
+ errs() << "Unsupported SPE Reg:" << Reg << "\n";
+ return {};
+ }
+ errs() << "setRegTo is not implemented, results will be unreliable:" << Reg
+ << "\n";
return {};
}
diff --git a/llvm/unittests/tools/llvm-exegesis/PowerPC/CMakeLists.txt b/llvm/unittests/tools/llvm-exegesis/PowerPC/CMakeLists.txt
index 6324ae652de0..3392a69ca0e4 100644
--- a/llvm/unittests/tools/llvm-exegesis/PowerPC/CMakeLists.txt
+++ b/llvm/unittests/tools/llvm-exegesis/PowerPC/CMakeLists.txt
@@ -15,6 +15,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_target_unittest(LLVMExegesisPowerPCTests
AnalysisTest.cpp
+ SnippetGeneratorTest.cpp
TargetTest.cpp
)
target_link_libraries(LLVMExegesisPowerPCTests PRIVATE
diff --git a/llvm/unittests/tools/llvm-exegesis/PowerPC/SnippetGeneratorTest.cpp b/llvm/unittests/tools/llvm-exegesis/PowerPC/SnippetGeneratorTest.cpp
new file mode 100644
index 000000000000..9b350e059aec
--- /dev/null
+++ b/llvm/unittests/tools/llvm-exegesis/PowerPC/SnippetGeneratorTest.cpp
@@ -0,0 +1,136 @@
+//===-- SnippetGeneratorTest.cpp --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../Common/AssemblerUtils.h"
+#include "LlvmState.h"
+#include "MCInstrDescView.h"
+#include "PPCInstrInfo.h"
+#include "ParallelSnippetGenerator.h"
+#include "RegisterAliasing.h"
+#include "SerialSnippetGenerator.h"
+#include "TestBase.h"
+
+#include <unordered_set>
+
+namespace llvm {
+namespace exegesis {
+namespace {
+
+using testing::AnyOf;
+using testing::ElementsAre;
+using testing::HasSubstr;
+using testing::SizeIs;
+
+MATCHER(IsInvalid, "") { return !arg.isValid(); }
+MATCHER(IsReg, "") { return arg.isReg(); }
+
+class PPCSnippetGeneratorTest : public PPCTestBase {};
+
+template <typename SnippetGeneratorT>
+class SnippetGeneratorTest : public PPCSnippetGeneratorTest {
+protected:
+ SnippetGeneratorTest() : Generator(State, SnippetGenerator::Options()) {}
+
+ std::vector<CodeTemplate> checkAndGetCodeTemplates(unsigned Opcode) {
+ randomGenerator().seed(0); // Initialize seed.
+ const Instruction &Instr = State.getIC().getInstr(Opcode);
+ auto CodeTemplateOrError = Generator.generateCodeTemplates(
+ &Instr, State.getRATC().emptyRegisters());
+ EXPECT_FALSE(CodeTemplateOrError.takeError()); // Valid configuration.
+ return std::move(CodeTemplateOrError.get());
+ }
+
+ SnippetGeneratorT Generator;
+};
+
+using SerialSnippetGeneratorTest = SnippetGeneratorTest<SerialSnippetGenerator>;
+
+using ParallelSnippetGeneratorTest =
+ SnippetGeneratorTest<ParallelSnippetGenerator>;
+
+TEST_F(SerialSnippetGeneratorTest, ImplicitSelfDependencyThroughExplicitRegs) {
+ // - ADD8
+ // - Op0 Explicit Def RegClass(G8RC)
+ // - Op1 Explicit Use RegClass(G8RC)
+ // - Op2 Explicit Use RegClass(G8RC)
+ // - Var0 [Op0]
+ // - Var1 [Op1]
+ // - Var2 [Op2]
+ // - hasAliasingRegisters
+ const unsigned Opcode = PPC::ADD8;
+ const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
+ ASSERT_THAT(CodeTemplates, SizeIs(1));
+ const auto &CT = CodeTemplates[0];
+ EXPECT_THAT(CT.Execution, ExecutionMode::SERIAL_VIA_EXPLICIT_REGS);
+ ASSERT_THAT(CT.Instructions, SizeIs(1));
+ const InstructionTemplate &IT = CT.Instructions[0];
+ EXPECT_THAT(IT.getOpcode(), Opcode);
+ ASSERT_THAT(IT.getVariableValues(), SizeIs(3));
+ EXPECT_THAT(IT.getVariableValues(),
+ AnyOf(ElementsAre(IsReg(), IsInvalid(), IsReg()),
+ ElementsAre(IsReg(), IsReg(), IsInvalid())))
+ << "Op0 is either set to Op1 or to Op2";
+}
+
+TEST_F(SerialSnippetGeneratorTest, ImplicitSelfDependencyThroughTiedRegs) {
+
+ // - RLDIMI
+ // - Op0 Explicit Def RegClass(G8RC)
+ // - Op1 Explicit Use RegClass(G8RC) TiedToOp0
+ // - Op2 Explicit Use RegClass(G8RC)
+ // - Op3 Explicit Use Immediate
+ // - Op4 Explicit Use Immediate
+ // - Var0 [Op0,Op1]
+ // - Var1 [Op2]
+ // - Var2 [Op3]
+ // - Var3 [Op4]
+ // - hasTiedRegisters (execution is always serial)
+ // - hasAliasingRegisters
+ // - RLDIMI
+ const unsigned Opcode = PPC::RLDIMI;
+ const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
+ ASSERT_THAT(CodeTemplates, SizeIs(1));
+ const auto &CT = CodeTemplates[0];
+ EXPECT_THAT(CT.Execution, ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS);
+ ASSERT_THAT(CT.Instructions, SizeIs(1));
+ const InstructionTemplate &IT = CT.Instructions[0];
+ EXPECT_THAT(IT.getOpcode(), Opcode);
+ ASSERT_THAT(IT.getVariableValues(), SizeIs(4));
+ EXPECT_THAT(IT.getVariableValues()[2], IsInvalid()) << "Operand 1 is not set";
+ EXPECT_THAT(IT.getVariableValues()[3], IsInvalid()) << "Operand 2 is not set";
+}
+
+TEST_F(ParallelSnippetGeneratorTest, MemoryUse) {
+ // - LDX
+ // - Op0 Explicit Def RegClass(G8RC)
+ // - Op1 Explicit Use Memory RegClass(GPRC)
+ // - Op2 Explicit Use Memory RegClass(VSSRC)
+ // - Var0 [Op0]
+ // - Var1 [Op1]
+ // - Var2 [Op2]
+ // - hasMemoryOperands
+ // - hasAliasingRegisters
+ const unsigned Opcode = PPC::LDX;
+ const auto CodeTemplates = checkAndGetCodeTemplates(Opcode);
+ ASSERT_THAT(CodeTemplates, SizeIs(1));
+ const auto &CT = CodeTemplates[0];
+ EXPECT_THAT(CT.Info, HasSubstr("instruction has no tied variables picking "
+ "Uses
diff erent from defs"));
+ EXPECT_THAT(CT.Execution, ExecutionMode::UNKNOWN);
+ ASSERT_THAT(CT.Instructions,
+ SizeIs(ParallelSnippetGenerator::kMinNumDifferentAddresses));
+ const InstructionTemplate &IT = CT.Instructions[0];
+ EXPECT_THAT(IT.getOpcode(), Opcode);
+ ASSERT_THAT(IT.getVariableValues(), SizeIs(3));
+ EXPECT_EQ(IT.getVariableValues()[1].getReg(), PPC::X1);
+ EXPECT_EQ(IT.getVariableValues()[2].getReg(), PPC::X13);
+}
+
+} // namespace
+} // namespace exegesis
+} // namespace llvm
diff --git a/llvm/unittests/tools/llvm-exegesis/PowerPC/TestBase.h b/llvm/unittests/tools/llvm-exegesis/PowerPC/TestBase.h
new file mode 100644
index 000000000000..567f3f381fbd
--- /dev/null
+++ b/llvm/unittests/tools/llvm-exegesis/PowerPC/TestBase.h
@@ -0,0 +1,42 @@
+//===-- TestBase.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Test fixture common to all PowerPC tests.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UNITTESTS_TOOLS_LLVMEXEGESIS_POWERPC_TESTBASE_H
+#define LLVM_UNITTESTS_TOOLS_LLVMEXEGESIS_POWERPC_TESTBASE_H
+
+#include "LlvmState.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace exegesis {
+
+void InitializePowerPCExegesisTarget();
+
+class PPCTestBase : public ::testing::Test {
+protected:
+ PPCTestBase() : State("powerpc64le-unknown-linux", "ppc64le") {}
+
+ static void SetUpTestCase() {
+ LLVMInitializePowerPCTargetInfo();
+ LLVMInitializePowerPCTargetMC();
+ LLVMInitializePowerPCTarget();
+ InitializePowerPCExegesisTarget();
+ }
+
+ const LLVMState State;
+};
+
+} // namespace exegesis
+} // namespace llvm
+
+#endif
More information about the llvm-branch-commits
mailing list