[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