[llvm] r345500 - [llvm-mca] Lower to mca::Instructon before the pipeline is run.

Andrea Di Biagio via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 29 06:29:22 PDT 2018


Author: adibiagio
Date: Mon Oct 29 06:29:22 2018
New Revision: 345500

URL: http://llvm.org/viewvc/llvm-project?rev=345500&view=rev
Log:
[llvm-mca] Lower to mca::Instructon before the pipeline is run.

Before this change, the lowering of instructions from llvm::MCInst to
mca::Instruction was done as part of the first stage of the pipeline (i.e. the
FetchStage).  In particular, FetchStage was responsible for picking the next
instruction from the source sequence, and lower it to an mca::Instruction with
the help of an object of class InstrBuilder.

The dependency on InstrBuilder was problematic for a number of reasons. Class
InstrBuilder only knows how to lower from llvm::MCInst to mca::Instruction.
That means, it is hard to support a different scenario where instructions
in input are not instances of class llvm::MCInst. Even if we managed to
specialize InstrBuilder, and generalize most of its internal logic, the
dependency on InstrBuilder in FetchStage would have caused more troubles (other
than complicating the pipeline logic).

With this patch, the lowering step is done before the pipeline is run. The
pipeline is no longer responsible for lowering from MCInst to mca::Instruction.
As a consequence of this, the FetchStage no longer needs to interact with an
InstrBuilder. The mca::SourceMgr class now simply wraps a reference to a
sequence of mca::Instruction objects.
This simplifies the logic of FetchStage, and increases the usability of it.  As
a result, on a debug build, we see a 7-9% speedup; on a release build, the
speedup is around 3-4%.

Modified:
    llvm/trunk/tools/llvm-mca/include/Instruction.h
    llvm/trunk/tools/llvm-mca/include/SourceMgr.h
    llvm/trunk/tools/llvm-mca/include/Stages/FetchStage.h
    llvm/trunk/tools/llvm-mca/lib/Context.cpp
    llvm/trunk/tools/llvm-mca/lib/Instruction.cpp
    llvm/trunk/tools/llvm-mca/lib/Stages/FetchStage.cpp
    llvm/trunk/tools/llvm-mca/llvm-mca.cpp

Modified: llvm/trunk/tools/llvm-mca/include/Instruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/Instruction.h?rev=345500&r1=345499&r2=345500&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/Instruction.h (original)
+++ llvm/trunk/tools/llvm-mca/include/Instruction.h Mon Oct 29 06:29:22 2018
@@ -88,7 +88,7 @@ class ReadState;
 /// register write. It also tracks how many cycles are left before the write
 /// back stage.
 class WriteState {
-  const WriteDescriptor &WD;
+  const WriteDescriptor *WD;
   // On instruction issue, this field is set equal to the write latency.
   // Before instruction issue, this field defaults to -512, a special
   // value that represents an "unknown" number of cycles.
@@ -133,14 +133,17 @@ class WriteState {
 public:
   WriteState(const WriteDescriptor &Desc, unsigned RegID,
              bool clearsSuperRegs = false, bool writesZero = false)
-      : WD(Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID),
+      : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID),
         ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero),
         IsEliminated(false), DependentWrite(nullptr), NumWriteUsers(0U) {}
 
+  WriteState(const WriteState &Other) = default;
+  WriteState &operator=(const WriteState &Other) = default;
+
   int getCyclesLeft() const { return CyclesLeft; }
-  unsigned getWriteResourceID() const { return WD.SClassOrWriteResourceID; }
+  unsigned getWriteResourceID() const { return WD->SClassOrWriteResourceID; }
   unsigned getRegisterID() const { return RegisterID; }
-  unsigned getLatency() const { return WD.Latency; }
+  unsigned getLatency() const { return WD->Latency; }
 
   void addUser(ReadState *Use, int ReadAdvance);
 
@@ -178,7 +181,7 @@ public:
 /// A read may be dependent on more than one write. This occurs when some
 /// writes only partially update the register associated to this read.
 class ReadState {
-  const ReadDescriptor &RD;
+  const ReadDescriptor *RD;
   // Physical register identified associated to this read.
   unsigned RegisterID;
   // Number of writes that contribute to the definition of RegisterID.
@@ -202,16 +205,16 @@ class ReadState {
 
 public:
   ReadState(const ReadDescriptor &Desc, unsigned RegID)
-      : RD(Desc), RegisterID(RegID), DependentWrites(0),
+      : RD(&Desc), RegisterID(RegID), DependentWrites(0),
         CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), IsReady(true),
         IndependentFromDef(false) {}
 
-  const ReadDescriptor &getDescriptor() const { return RD; }
-  unsigned getSchedClass() const { return RD.SchedClassID; }
+  const ReadDescriptor &getDescriptor() const { return *RD; }
+  unsigned getSchedClass() const { return RD->SchedClassID; }
   unsigned getRegisterID() const { return RegisterID; }
 
   bool isReady() const { return IsReady; }
-  bool isImplicitRead() const { return RD.isImplicitRead(); }
+  bool isImplicitRead() const { return RD->isImplicitRead(); }
 
   bool isIndependentFromDef() const { return IndependentFromDef; }
   void setIndependentFromDef() { IndependentFromDef = true; }
@@ -387,8 +390,6 @@ public:
   Instruction(const InstrDesc &D)
       : InstructionBase(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES),
         RCUTokenID(0) {}
-  Instruction(const Instruction &Other) = delete;
-  Instruction &operator=(const Instruction &Other) = delete;
 
   unsigned getRCUTokenID() const { return RCUTokenID; }
   int getCyclesLeft() const { return CyclesLeft; }

Modified: llvm/trunk/tools/llvm-mca/include/SourceMgr.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/SourceMgr.h?rev=345500&r1=345499&r2=345500&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/SourceMgr.h (original)
+++ llvm/trunk/tools/llvm-mca/include/SourceMgr.h Mon Oct 29 06:29:22 2018
@@ -17,35 +17,35 @@
 #define LLVM_TOOLS_LLVM_MCA_SOURCEMGR_H
 
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/MC/MCInst.h"
-#include <vector>
 
 namespace mca {
 
-typedef std::pair<unsigned, const llvm::MCInst &> SourceRef;
+class Instruction;
+
+typedef std::pair<unsigned, const Instruction &> SourceRef;
 
 class SourceMgr {
-  llvm::ArrayRef<llvm::MCInst> Sequence;
+  using UniqueInst = std::unique_ptr<Instruction>;
+  llvm::ArrayRef<UniqueInst> Sequence;
   unsigned Current;
   const unsigned Iterations;
   static const unsigned DefaultIterations = 100;
 
 public:
-  SourceMgr(llvm::ArrayRef<llvm::MCInst> MCInstSequence, unsigned NumIterations)
-      : Sequence(MCInstSequence), Current(0),
-        Iterations(NumIterations ? NumIterations : DefaultIterations) {}
+  SourceMgr(llvm::ArrayRef<UniqueInst> S, unsigned Iter)
+      : Sequence(S), Current(0), Iterations(Iter ? Iter : DefaultIterations) {}
 
   unsigned getNumIterations() const { return Iterations; }
   unsigned size() const { return Sequence.size(); }
   bool hasNext() const { return Current < (Iterations * Sequence.size()); }
   void updateNext() { ++Current; }
 
-  const SourceRef peekNext() const {
+  SourceRef peekNext() const {
     assert(hasNext() && "Already at end of sequence!");
-    return SourceRef(Current, Sequence[Current % Sequence.size()]);
+    return SourceRef(Current, *Sequence[Current % Sequence.size()]);
   }
 
-  using const_iterator = llvm::ArrayRef<llvm::MCInst>::const_iterator;
+  using const_iterator = llvm::ArrayRef<UniqueInst>::const_iterator;
   const_iterator begin() const { return Sequence.begin(); }
   const_iterator end() const { return Sequence.end(); }
 };

Modified: llvm/trunk/tools/llvm-mca/include/Stages/FetchStage.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/Stages/FetchStage.h?rev=345500&r1=345499&r2=345500&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/Stages/FetchStage.h (original)
+++ llvm/trunk/tools/llvm-mca/include/Stages/FetchStage.h Mon Oct 29 06:29:22 2018
@@ -16,7 +16,6 @@
 #ifndef LLVM_TOOLS_LLVM_MCA_FETCH_STAGE_H
 #define LLVM_TOOLS_LLVM_MCA_FETCH_STAGE_H
 
-#include "InstrBuilder.h"
 #include "SourceMgr.h"
 #include "Stages/Stage.h"
 #include <map>
@@ -27,18 +26,16 @@ class FetchStage final : public Stage {
   InstRef CurrentInstruction;
   using InstMap = std::map<unsigned, std::unique_ptr<Instruction>>;
   InstMap Instructions;
-  InstrBuilder &IB;
   SourceMgr &SM;
 
   // Updates the program counter, and sets 'CurrentInstruction'.
-  llvm::Error getNextInstruction();
+  void getNextInstruction();
 
   FetchStage(const FetchStage &Other) = delete;
   FetchStage &operator=(const FetchStage &Other) = delete;
 
 public:
-  FetchStage(InstrBuilder &IB, SourceMgr &SM)
-      : CurrentInstruction(), IB(IB), SM(SM) {}
+  FetchStage(SourceMgr &SM) : CurrentInstruction(), SM(SM) {}
 
   bool isAvailable(const InstRef &IR) const override;
   bool hasWorkToComplete() const override;

Modified: llvm/trunk/tools/llvm-mca/lib/Context.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/Context.cpp?rev=345500&r1=345499&r2=345500&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/Context.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/Context.cpp Mon Oct 29 06:29:22 2018
@@ -41,7 +41,7 @@ Context::createDefaultPipeline(const Pip
   auto HWS = llvm::make_unique<Scheduler>(SM, LSU.get());
 
   // Create the pipeline stages.
-  auto Fetch = llvm::make_unique<FetchStage>(IB, SrcMgr);
+  auto Fetch = llvm::make_unique<FetchStage>(SrcMgr);
   auto Dispatch = llvm::make_unique<DispatchStage>(STI, MRI, Opts.DispatchWidth,
                                                    *RCU, *PRF);
   auto Execute = llvm::make_unique<ExecuteStage>(*HWS);

Modified: llvm/trunk/tools/llvm-mca/lib/Instruction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/Instruction.cpp?rev=345500&r1=345499&r2=345500&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/Instruction.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/Instruction.cpp Mon Oct 29 06:29:22 2018
@@ -93,7 +93,7 @@ void ReadState::cycleEvent() {
 
 #ifndef NDEBUG
 void WriteState::dump() const {
-  dbgs() << "{ OpIdx=" << WD.OpIndex << ", Lat=" << getLatency() << ", RegID "
+  dbgs() << "{ OpIdx=" << WD->OpIndex << ", Lat=" << getLatency() << ", RegID "
          << getRegisterID() << ", Cycles Left=" << getCyclesLeft() << " }";
 }
 

Modified: llvm/trunk/tools/llvm-mca/lib/Stages/FetchStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/Stages/FetchStage.cpp?rev=345500&r1=345499&r2=345500&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/Stages/FetchStage.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/Stages/FetchStage.cpp Mon Oct 29 06:29:22 2018
@@ -14,6 +14,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Stages/FetchStage.h"
+#include "Instruction.h"
 
 namespace mca {
 
@@ -25,20 +26,15 @@ bool FetchStage::isAvailable(const InstR
   return false;
 }
 
-llvm::Error FetchStage::getNextInstruction() {
+void FetchStage::getNextInstruction() {
   assert(!CurrentInstruction && "There is already an instruction to process!");
   if (!SM.hasNext())
-    return llvm::ErrorSuccess();
-  const SourceRef SR = SM.peekNext();
-  llvm::Expected<std::unique_ptr<Instruction>> InstOrErr =
-      IB.createInstruction(SR.second);
-  if (!InstOrErr)
-    return InstOrErr.takeError();
-  std::unique_ptr<Instruction> Inst = std::move(InstOrErr.get());
+    return;
+  SourceRef SR = SM.peekNext();
+  std::unique_ptr<Instruction> Inst = llvm::make_unique<Instruction>(SR.second);
   CurrentInstruction = InstRef(SR.first, Inst.get());
   Instructions[SR.first] = std::move(Inst);
   SM.updateNext();
-  return llvm::ErrorSuccess();
 }
 
 llvm::Error FetchStage::execute(InstRef & /*unused */) {
@@ -48,12 +44,13 @@ llvm::Error FetchStage::execute(InstRef
 
   // Move the program counter.
   CurrentInstruction.invalidate();
-  return getNextInstruction();
+  getNextInstruction();
+  return llvm::ErrorSuccess();
 }
 
 llvm::Error FetchStage::cycleStart() {
   if (!CurrentInstruction)
-    return getNextInstruction();
+    getNextInstruction();
   return llvm::ErrorSuccess();
 }
 

Modified: llvm/trunk/tools/llvm-mca/llvm-mca.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/llvm-mca.cpp?rev=345500&r1=345499&r2=345500&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/llvm-mca.cpp (original)
+++ llvm/trunk/tools/llvm-mca/llvm-mca.cpp Mon Oct 29 06:29:22 2018
@@ -328,26 +328,12 @@ static void processViewOptions() {
 }
 
 // Returns true on success.
-static bool runPipeline(mca::Pipeline &P, MCInstPrinter &MCIP,
-                        const MCSubtargetInfo &STI) {
+static bool runPipeline(mca::Pipeline &P) {
   // Handle pipeline errors here.
   if (auto Err = P.run()) {
-    if (auto NewE = handleErrors(
-            std::move(Err),
-            [&MCIP, &STI](const mca::InstructionError<MCInst> &IE) {
-              std::string InstructionStr;
-              raw_string_ostream SS(InstructionStr);
-              WithColor::error() << IE.Message << '\n';
-              MCIP.printInst(&IE.Inst, SS, "", STI);
-              SS.flush();
-              WithColor::note() << "instruction: " << InstructionStr << '\n';
-            })) {
-      // Default case.
-      WithColor::error() << toString(std::move(NewE));
-    }
+    WithColor::error() << toString(std::move(Err));
     return false;
   }
-
   return true;
 }
 
@@ -513,14 +499,37 @@ int main(int argc, char **argv) {
       TOF->os() << "\n\n";
     }
 
+    // Lower the MCInst sequence into an mca::Instruction sequence.
     ArrayRef<MCInst> Insts = Region->getInstructions();
-    mca::SourceMgr S(Region->getInstructions(),
+    std::vector<std::unique_ptr<mca::Instruction>> LoweredSequence;
+    for (const MCInst &MCI : Insts) {
+      llvm::Expected<std::unique_ptr<mca::Instruction>> Inst = IB.createInstruction(MCI);
+      if (!Inst) {
+        if (auto NewE = handleErrors(Inst.takeError(),
+            [&IP, &STI](const mca::InstructionError<MCInst> &IE) {
+              std::string InstructionStr;
+              raw_string_ostream SS(InstructionStr);
+              WithColor::error() << IE.Message << '\n';
+              IP->printInst(&IE.Inst, SS, "", *STI);
+              SS.flush();
+              WithColor::note() << "instruction: " << InstructionStr << '\n';
+            })) {
+          // Default case.
+          WithColor::error() << toString(std::move(NewE));
+        }
+        return 1;
+      }
+
+      LoweredSequence.emplace_back(std::move(Inst.get()));
+    }
+
+    mca::SourceMgr S(LoweredSequence,
                      PrintInstructionTables ? 1 : Iterations);
 
     if (PrintInstructionTables) {
       //  Create a pipeline, stages, and a printer.
       auto P = llvm::make_unique<mca::Pipeline>();
-      P->appendStage(llvm::make_unique<mca::FetchStage>(IB, S));
+      P->appendStage(llvm::make_unique<mca::FetchStage>(S));
       P->appendStage(llvm::make_unique<mca::InstructionTables>(SM));
       mca::PipelinePrinter Printer(*P);
 
@@ -532,7 +541,7 @@ int main(int argc, char **argv) {
       Printer.addView(
           llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts));
 
-      if (!runPipeline(*P, *IP, *STI))
+      if (!runPipeline(*P))
         return 1;
 
       Printer.printReport(TOF->os());
@@ -574,7 +583,7 @@ int main(int argc, char **argv) {
           TimelineMaxCycles));
     }
 
-    if (!runPipeline(*P, *IP, *STI))
+    if (!runPipeline(*P))
       return 1;
 
     Printer.printReport(TOF->os());




More information about the llvm-commits mailing list