[llvm] 5be8b2e - [llvm-exegesis] Serial snippet: Restrict the set of back-to-back instructions

Clement Courbet via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 22 02:01:04 PST 2020


Author: Clement Courbet
Date: 2020-01-22T11:00:43+01:00
New Revision: 5be8b2ec4a0f73900b4b41f6c67ac7d0091d6ac7

URL: https://github.com/llvm/llvm-project/commit/5be8b2ec4a0f73900b4b41f6c67ac7d0091d6ac7
DIFF: https://github.com/llvm/llvm-project/commit/5be8b2ec4a0f73900b4b41f6c67ac7d0091d6ac7.diff

LOG: [llvm-exegesis] Serial snippet: Restrict the set of back-to-back instructions

Summary:
Right now when picking a back-to-back instruction at random, we might select
instructions that we do not know how to handle.
Add a ExegesisTarget hook to possibly filter instructions.

Reviewers: gchatelet

Subscribers: tschuett, mstojanovic, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D73161

Added: 
    

Modified: 
    llvm/tools/llvm-exegesis/lib/Target.h
    llvm/tools/llvm-exegesis/lib/X86/Target.cpp
    llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 62f0dab1e989..bd4300904105 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -115,6 +115,13 @@ class ExegesisTarget {
                                   MCOperand &AssignedValue,
                                   const BitVector &ForbiddenRegs) const;
 
+  // Returns true if this instruction is supported as a back-to-back
+  // instructions.
+  // FIXME: Eventually we should discover this dynamically.
+  virtual bool allowAsBackToBack(const Instruction &Instr) const {
+    return true;
+  }
+
   // Creates a snippet generator for the given mode.
   std::unique_ptr<SnippetGenerator>
   createSnippetGenerator(InstructionBenchmark::ModeE Mode,

diff  --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index c739eae651e4..cea8af0cf69c 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -22,9 +22,9 @@
 namespace llvm {
 namespace exegesis {
 
-// Returns an error if we cannot handle the memory references in this
+// Returns a non-null reason if we cannot handle the memory references in this
 // instruction.
-static Error isInvalidMemoryInstr(const Instruction &Instr) {
+static const char *isInvalidMemoryInstr(const Instruction &Instr) {
   switch (Instr.Description.TSFlags & X86II::FormMask) {
   default:
     llvm_unreachable("Unknown FormMask value");
@@ -112,15 +112,14 @@ static Error isInvalidMemoryInstr(const Instruction &Instr) {
   case X86II::MRM_FE:
   case X86II::MRM_FF:
   case X86II::RawFrmImm8:
-    return Error::success();
+    return nullptr;
   case X86II::AddRegFrm:
     return (Instr.Description.Opcode == X86::POP16r ||
             Instr.Description.Opcode == X86::POP32r ||
             Instr.Description.Opcode == X86::PUSH16r ||
             Instr.Description.Opcode == X86::PUSH32r)
-               ? make_error<Failure>(
-                     "unsupported opcode: unsupported memory access")
-               : Error::success();
+               ? "unsupported opcode: unsupported memory access"
+               : nullptr;
   // These access memory and are handled.
   case X86II::MRMDestMem:
   case X86II::MRMSrcMem:
@@ -137,38 +136,40 @@ static Error isInvalidMemoryInstr(const Instruction &Instr) {
   case X86II::MRM5m:
   case X86II::MRM6m:
   case X86II::MRM7m:
-    return Error::success();
+    return nullptr;
   // These access memory and are not handled yet.
   case X86II::RawFrmImm16:
   case X86II::RawFrmMemOffs:
   case X86II::RawFrmSrc:
   case X86II::RawFrmDst:
   case X86II::RawFrmDstSrc:
-    return make_error<Failure>("unsupported opcode: non uniform memory access");
+    return "unsupported opcode: non uniform memory access";
   }
 }
 
-static Error IsInvalidOpcode(const Instruction &Instr) {
+// If the opcode is invalid, returns a pointer to a character literal indicating
+// the reason. nullptr indicates a valid opcode.
+static const char *isInvalidOpcode(const Instruction &Instr) {
   const auto OpcodeName = Instr.Name;
   if ((Instr.Description.TSFlags & X86II::FormMask) == X86II::Pseudo)
-    return make_error<Failure>("unsupported opcode: pseudo instruction");
-  if (OpcodeName.startswith("POPF") || OpcodeName.startswith("PUSHF") ||
-      OpcodeName.startswith("ADJCALLSTACK"))
-    return make_error<Failure>("unsupported opcode: Push/Pop/AdjCallStack");
-  if (Error Error = isInvalidMemoryInstr(Instr))
-    return Error;
+    return "unsupported opcode: pseudo instruction";
+  if (OpcodeName.startswith("POP") || OpcodeName.startswith("PUSH") ||
+      OpcodeName.startswith("ADJCALLSTACK") || OpcodeName.startswith("LEAVE"))
+    return "unsupported opcode: Push/Pop/AdjCallStack/Leave";
+  if (const auto reason = isInvalidMemoryInstr(Instr))
+    return reason;
   // We do not handle instructions with OPERAND_PCREL.
   for (const Operand &Op : Instr.Operands)
     if (Op.isExplicit() &&
         Op.getExplicitOperandInfo().OperandType == MCOI::OPERAND_PCREL)
-      return make_error<Failure>("unsupported opcode: PC relative operand");
+      return "unsupported opcode: PC relative operand";
   // We do not handle second-form X87 instructions. We only handle first-form
   // ones (_Fp), see comment in X86InstrFPStack.td.
   for (const Operand &Op : Instr.Operands)
     if (Op.isReg() && Op.isExplicit() &&
         Op.getExplicitOperandInfo().RegClass == X86::RSTRegClassID)
-      return make_error<Failure>("unsupported second-form X87 instruction");
-  return Error::success();
+      return "unsupported second-form X87 instruction";
+  return nullptr;
 }
 
 static unsigned getX86FPFlags(const Instruction &Instr) {
@@ -263,8 +264,8 @@ class X86SerialSnippetGenerator : public SerialSnippetGenerator {
 Expected<std::vector<CodeTemplate>>
 X86SerialSnippetGenerator::generateCodeTemplates(
     const Instruction &Instr, const BitVector &ForbiddenRegisters) const {
-  if (auto E = IsInvalidOpcode(Instr))
-    return std::move(E);
+  if (const auto reason = isInvalidOpcode(Instr))
+    return make_error<Failure>(reason);
 
   // LEA gets special attention.
   const auto Opcode = Instr.Description.getOpcode();
@@ -280,6 +281,10 @@ X86SerialSnippetGenerator::generateCodeTemplates(
         });
   }
 
+  if (Instr.hasMemoryOperands())
+    return make_error<Failure>(
+        "unsupported memory operand in latency measurements");
+
   switch (getX86FPFlags(Instr)) {
   case X86II::NotFP:
     return SerialSnippetGenerator::generateCodeTemplates(Instr,
@@ -317,8 +322,8 @@ class X86ParallelSnippetGenerator : public ParallelSnippetGenerator {
 Expected<std::vector<CodeTemplate>>
 X86ParallelSnippetGenerator::generateCodeTemplates(
     const Instruction &Instr, const BitVector &ForbiddenRegisters) const {
-  if (auto E = IsInvalidOpcode(Instr))
-    return std::move(E);
+  if (const auto reason = isInvalidOpcode(Instr))
+    return make_error<Failure>(reason);
 
   // LEA gets special attention.
   const auto Opcode = Instr.Description.getOpcode();
@@ -581,6 +586,12 @@ class ExegesisX86Target : public ExegesisTarget {
                             sizeof(kUnavailableRegisters[0]));
   }
 
+  bool allowAsBackToBack(const Instruction &Instr) const override {
+    const unsigned Opcode = Instr.Description.Opcode;
+    return !isInvalidOpcode(Instr) && Opcode != X86::LEA64r &&
+           Opcode != X86::LEA64_32r && Opcode != X86::LEA16r;
+  }
+
   std::unique_ptr<SnippetGenerator> createSerialSnippetGenerator(
       const LLVMState &State,
       const SnippetGenerator::Options &Opts) const override {
@@ -727,8 +738,8 @@ std::vector<MCInst> ExegesisX86Target::setRegTo(const MCSubtargetInfo &STI,
     return CI.popFlagAndFinalize();
   if (Reg == X86::MXCSR)
     return CI.loadImplicitRegAndFinalize(
-              STI.getFeatureBits()[X86::FeatureAVX] ? X86::VLDMXCSR
-                                                    : X86::LDMXCSR, 0x1f80);
+        STI.getFeatureBits()[X86::FeatureAVX] ? X86::VLDMXCSR : X86::LDMXCSR,
+        0x1f80);
   if (Reg == X86::FPCW)
     return CI.loadImplicitRegAndFinalize(X86::FLDCW16m, 0x37f);
   return {}; // Not yet implemented.

diff  --git a/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
index eefed6dd5441..7ea002614915 100644
--- a/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
+++ b/llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
@@ -384,6 +384,13 @@ TEST_F(Core2Avx512TargetTest, FillMemoryOperands_VGATHERDPSZ128rm) {
   EXPECT_THAT(IT.getValueFor(I.Operands[8]), IsReg(0));
 }
 
+TEST_F(Core2TargetTest, AllowAsBackToBack) {
+  EXPECT_TRUE(
+      State.getExegesisTarget().allowAsBackToBack(getInstr(X86::ADD64rr)));
+  EXPECT_FALSE(
+      State.getExegesisTarget().allowAsBackToBack(getInstr(X86::LEA64r)));
+}
+
 } // namespace
 } // namespace exegesis
 } // namespace llvm


        


More information about the llvm-commits mailing list