1 //===---------------- IncrementalSourceMgr.h --------------------*- 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 /// \file
9 /// This file contains IncrementalSourceMgr, an implementation of SourceMgr
10 /// that allows users to add new instructions incrementally / dynamically.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_MCA_INCREMENTALSOURCEMGR_H
15 #define LLVM_MCA_INCREMENTALSOURCEMGR_H
16 
17 #include "llvm/MCA/SourceMgr.h"
18 #include <deque>
19 
20 namespace llvm {
21 namespace mca {
22 
23 /// An implementation of \a SourceMgr that allows users to add new instructions
24 /// incrementally / dynamically.
25 /// Note that this SourceMgr takes ownership of all \a mca::Instruction.
26 class IncrementalSourceMgr : public SourceMgr {
27   /// Owner of all mca::Instruction instances. Note that we use std::deque here
28   /// to have a better throughput, in comparison to std::vector or
29   /// llvm::SmallVector, as they usually pay a higher re-allocation cost when
30   /// there is a large number of instructions.
31   std::deque<UniqueInst> InstStorage;
32 
33   /// Instructions that are ready to be used. Each of them is a pointer of an
34   /// \a UniqueInst inside InstStorage.
35   std::deque<Instruction *> Staging;
36 
37   /// Current instruction index.
38   unsigned TotalCounter;
39 
40   /// End-of-stream flag.
41   bool EOS;
42 
43   /// Called when an instruction is no longer needed.
44   using InstFreedCallback = llvm::function_ref<void(Instruction *)>;
45   InstFreedCallback InstFreedCB;
46 
47 public:
48   IncrementalSourceMgr() : TotalCounter(0U), EOS(false) {}
49 
50   void clear();
51 
52   /// Set a callback that is invoked when a mca::Instruction is
53   /// no longer needed. This is usually used for recycling the
54   /// instruction.
55   void setOnInstFreedCallback(InstFreedCallback CB) { InstFreedCB = CB; }
56 
57   ArrayRef<UniqueInst> getInstructions() const override {
58     llvm_unreachable("Not applicable");
59   }
60 
61   bool hasNext() const override { return !Staging.empty(); }
62   bool isEnd() const override { return EOS; }
63 
64   SourceRef peekNext() const override {
65     assert(hasNext());
66     return SourceRef(TotalCounter, *Staging.front());
67   }
68 
69   /// Add a new instruction.
70   void addInst(UniqueInst &&Inst) {
71     InstStorage.emplace_back(std::move(Inst));
72     Staging.push_back(InstStorage.back().get());
73   }
74 
75   /// Add a recycled instruction.
76   void addRecycledInst(Instruction *Inst) { Staging.push_back(Inst); }
77 
78   void updateNext() override;
79 
80   /// Mark the end of instruction stream.
81   void endOfStream() { EOS = true; }
82 
83 #ifndef NDEBUG
84   /// Print statistic about instruction recycling stats.
85   void printStatistic(raw_ostream &OS);
86 #endif
87 };
88 
89 } // end namespace mca
90 } // end namespace llvm
91 
92 #endif // LLVM_MCA_INCREMENTALSOURCEMGR_H
93