[llvm-branch-commits] [llvm] 76ad099 - add some comment

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Jul 28 19:19:56 PDT 2021


Author: 董⼀峰
Date: 2021-07-29T10:19:28+08:00
New Revision: 76ad09983deafe9d2d0384b2a0b1244495e23400

URL: https://github.com/llvm/llvm-project/commit/76ad09983deafe9d2d0384b2a0b1244495e23400
DIFF: https://github.com/llvm/llvm-project/commit/76ad09983deafe9d2d0384b2a0b1244495e23400.diff

LOG: add some comment

Added: 
    

Modified: 
    llvm/examples/HowToUseLLJIT/HowToUseLLJIT.cpp
    llvm/include/llvm/CodeGen/MachineInstr.h
    llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
    llvm/include/llvm/MC/MCRegisterInfo.h
    llvm/include/llvm/MC/MCSchedule.h
    llvm/include/llvm/Target/Target.td
    llvm/include/llvm/Target/TargetItinerary.td
    llvm/include/llvm/Target/TargetMachine.h
    llvm/include/llvm/Target/TargetSchedule.td
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
    llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
    llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
    llvm/lib/CodeGen/StackMaps.cpp
    llvm/lib/CodeGen/TargetSchedule.cpp
    llvm/lib/Target/AArch64/AArch64SchedA64FX.td
    llvm/lib/Target/BPF/BPFAsmPrinter.cpp
    llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
    llvm/test/CodeGen/AArch64/arm64-patchpoint.ll
    llvm/utils/TableGen/CodeGenInstruction.cpp
    llvm/utils/TableGen/CodeGenRegisters.cpp
    llvm/utils/TableGen/CodeGenSchedule.cpp
    llvm/utils/TableGen/CodeGenTarget.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/examples/HowToUseLLJIT/HowToUseLLJIT.cpp b/llvm/examples/HowToUseLLJIT/HowToUseLLJIT.cpp
index c3ab7e6c1adb8..170a899136054 100644
--- a/llvm/examples/HowToUseLLJIT/HowToUseLLJIT.cpp
+++ b/llvm/examples/HowToUseLLJIT/HowToUseLLJIT.cpp
@@ -40,7 +40,7 @@ ExitOnError ExitOnErr;
 
 ThreadSafeModule createDemoModule() {
   auto Context = std::make_unique<LLVMContext>();
-xo  auto M = std::make_unique<Module>("test", *Context);
+  auto M = std::make_unique<Module>("test", *Context);
 
   // Create the add1 function entry and insert this entry into module M.  The
   // function will have a return type of "int" and take an argument of "int".

diff  --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 7fc1576fe5a09..2f62da932bba1 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -559,7 +559,7 @@ class MachineInstr
 
   /// Returns the total number of definitions.
   unsigned getNumDefs() const {
-    return getNumExplicitDefs() + MCID->getNumImplicitDefs();
+    return getNumExplicitDefs() + MCID->getNumImplicitDefs();   // 一条指令的定义数量取决于显示和隐式两种定义。
   }
 
   /// Returns true if the instruction has implicit definition.

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h b/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
index d4960ab8b0bbf..bb07d0f1e2325 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h
@@ -84,7 +84,7 @@ class ThreadSafeModule {
 
   ThreadSafeModule &operator=(ThreadSafeModule &&Other) {
     // We have to explicitly define this move operator to copy the fields in
-    // reverse order (i.e. module first) to ensure the dependencies are
+    // reverse order (i.e. module first) to ensure theo dependencies are
     // protected: The old module that is being overwritten must be destroyed
     // *before* the context that it depends on.
     // We also need to lock the context to make sure the module tear-down

diff  --git a/llvm/include/llvm/MC/MCRegisterInfo.h b/llvm/include/llvm/MC/MCRegisterInfo.h
index 65436dc74c3e2..7a58b7e1c875f 100644
--- a/llvm/include/llvm/MC/MCRegisterInfo.h
+++ b/llvm/include/llvm/MC/MCRegisterInfo.h
@@ -101,7 +101,7 @@ class MCRegisterClass {
 /// of AX. The SuperRegs field is a zero terminated array of registers that are
 /// super-registers of the specific register, e.g. RAX, EAX, are
 /// super-registers of AX.
-///
+///   用来描述当前寄存器的状态。 tablegen和cpp代码之间的链接结构体。
 struct MCRegisterDesc {
   uint32_t Name;      // Printable name for the reg (for debugging)
   uint32_t SubRegs;   // Sub-register set, described above

diff  --git a/llvm/include/llvm/MC/MCSchedule.h b/llvm/include/llvm/MC/MCSchedule.h
index acfbfd387ff35..d98e73aded675 100644
--- a/llvm/include/llvm/MC/MCSchedule.h
+++ b/llvm/include/llvm/MC/MCSchedule.h
@@ -61,6 +61,7 @@ struct MCProcResourceDesc {
 
 /// Identify one of the processor resource kinds consumed by a particular
 /// scheduling class for the specified number of cycles.
+// 用于描述指定调度类型在指定周期数里消耗指定处理器资源
 struct MCWriteProcResEntry {
   uint16_t ProcResourceIdx;
   uint16_t Cycles;
@@ -75,6 +76,7 @@ struct MCWriteProcResEntry {
 /// an instruction with invalid latency to have infinite latency.  Also identify
 /// the WriteResources of this def. When the operand expands to a sequence of
 /// writes, this ID is the last write in the sequence.
+/// 用于记录执行一个指定的SchedWrite定义所需的处理器周期
 struct MCWriteLatencyEntry {
   int16_t Cycles;
   uint16_t WriteResourceID;
@@ -92,6 +94,10 @@ struct MCWriteLatencyEntry {
 ///
 /// MCReadAdvanceEntries are sorted first by operand index (UseIdx), then by
 /// WriteResourceIdx.
+///
+/// MCReadAdvanceEntry由ReadAdvance定义创建,用于描述处理器的流水线旁路,
+/// 这时写操作的结果可提前若干周期(在ReadAdvance定义中给出)传给后续的读操作。
+/// 这时UseIdx是这个ReadAdvance定义的索引,WriteResourceID则是旁路支持的SchedWrite的索引,Cycles是缩短的周期(如果是负数则是延长)。
 struct MCReadAdvanceEntry {
   unsigned UseIdx;
   unsigned WriteResourceID;
@@ -107,6 +113,7 @@ struct MCReadAdvanceEntry {
 /// particular scheduling class.
 ///
 /// Defined as an aggregate struct for creating tables with initializer lists.
+/// MC对资源调度的描述方式
 struct MCSchedClassDesc {
   static const unsigned short InvalidNumMicroOps = (1U << 13) - 1;
   static const unsigned short VariantNumMicroOps = InvalidNumMicroOps - 1;

diff  --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index e9720d7651677..eefd2aee421e7 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -476,8 +476,8 @@ class EncodingByHwMode<list<HwMode> Ms = [], list<InstructionEncoding> Ts = []>
 class Instruction : InstructionEncoding {
   string Namespace = "";
 
-  dag OutOperandList;       // An dag containing the MI def operand list.
-  dag InOperandList;        // An dag containing the MI use operand list.
+  dag OutOperandList;       // An dag containing the MI def operand list.  (CGIOperandList)
+  dag InOperandList;        // An dag containing the MI use operand list.  (CGIOperandList)
   string AsmString = "";    // The .s format to print the instruction with.
 
   // Allows specifying a canonical InstructionEncoding by HwMode. If non-empty,
@@ -596,10 +596,12 @@ class Instruction : InstructionEncoding {
   // scheduling model.
   bit hasNoSchedulingInfo = false;
 
+  // 从指令执行步骤方面来描述指令
   InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling.
 
   // Scheduling information from TargetSchedule.td.
-  list<SchedReadWrite> SchedRW;
+  // 记录下当前指令可读可写的状态。是一个数组。
+  list<SchedReadWrite> SchedRW;      // ----> 决定了一个CodeGenSchedClass的构建、
 
   string Constraints = "";  // OperandConstraint, e.g. $src = $dst.
 

diff  --git a/llvm/include/llvm/Target/TargetItinerary.td b/llvm/include/llvm/Target/TargetItinerary.td
index a432d4e42b61d..d0feae658c9d1 100644
--- a/llvm/include/llvm/Target/TargetItinerary.td
+++ b/llvm/include/llvm/Target/TargetItinerary.td
@@ -52,12 +52,15 @@ def Reserved : ReservationKind<1>;
 //   InstrStage<1, [FU_x, FU_y]>     - TimeInc defaults to Cycles
 //   InstrStage<1, [FU_x, FU_y], 0>  - TimeInc explicit
 //
-
+// 指令执行的一个流水线步骤则由InstrStage来描述
 class InstrStage<int cycles, list<FuncUnit> units,
                  int timeinc = -1,
                  ReservationKind kind = Required> {
+  // 完成这个这个步骤(阶段)所需的周期数                    
   int Cycles          = cycles;       // length of stage in machine cycles
+  // 用于完成该阶段的功能单元的选择
   list<FuncUnit> Units = units;       // choice of functional units
+  // 在执行步骤中,从这个阶段的开始到下个阶段的开始,需要经历多少个周期.
   int TimeInc         = timeinc;      // cycles till start of next stage
   int Kind            = kind.Value;   // kind of FU reservation
 }
@@ -75,6 +78,7 @@ class InstrStage<int cycles, list<FuncUnit> units,
 // across all chip sets.  Thus a new chip set can be added without modifying
 // instruction information.
 //
+// 从指令执行步骤方面来描述指令
 class InstrItinClass;
 def NoItinerary : InstrItinClass;
 
@@ -110,9 +114,15 @@ class InstrItinData<InstrItinClass Class, list<InstrStage> stages,
                     list<int> operandcycles = [],
                     list<Bypass> bypasses = [], int uops = 1> {
   InstrItinClass TheClass = Class;
+  // 该类指令解码后的微操作(micro-operation)的数量。如果数量是0,意味着该指令可以解码为需要动态确定的、数量不定的微操作。
+  // 这直接关系到执行步骤限制每周期可发布的微操作数的全局IssueWidth属性
   int NumMicroOps = uops;
+  // 
   list<InstrStage> Stages = stages;
+  // 是可选的“周期数”。它们指出在指令发出这些周期后,指定的操作数完成写或读
   list<int> OperandCycles = operandcycles;
+  // 是可选的“流水线转发路径”(即处理器将执行写入操作指令的结果直接交给后续的读操作指令,绕过寄存器的接力),
+  // 如果一条指令的值在一个特定旁路上可用,且另一条指令可以从这个旁路读出这个值,那么操作数的使用时延降低1个周期。
   list<Bypass> Bypasses = bypasses;
 }
 

diff  --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index dd17af4a642ac..83329e75d27e4 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -163,7 +163,7 @@ class TargetMachine {
   }
 
   /// Create a DataLayout.
-  const DataLayout createDataLayout() const { return DL; }
+  const DataLayout createDataLayout() const { return DL; }         // access an object with target-specific data characteristics, such as data type size and alignment requirements
 
   /// Test if a DataLayout if compatible with the CodeGen for this target.
   ///
@@ -201,15 +201,15 @@ class TargetMachine {
   /// Return target specific asm information.
   const MCAsmInfo *getMCAsmInfo() const { return AsmInfo.get(); }
 
-  const MCRegisterInfo *getMCRegisterInfo() const { return MRI.get(); }
-  const MCInstrInfo *getMCInstrInfo() const { return MII.get(); }
+  const MCRegisterInfo *getMCRegisterInfo() const { return MRI.get(); }                         // register set
+  const MCInstrInfo *getMCInstrInfo() const { return MII.get(); }                               // Instruction set
   const MCSubtargetInfo *getMCSubtargetInfo() const { return STI.get(); }
 
   /// If intrinsic information is available, return it.  If not, return null.
   virtual const TargetIntrinsicInfo *getIntrinsicInfo() const {
     return nullptr;
   }
-
+  // 当RequireStructuredCFG=true的时候llvm将避免程序CFG的更改, 防止产生不可控的优化。
   bool requiresStructuredCFG() const { return RequireStructuredCFG; }
   void setRequiresStructuredCFG(bool Value) { RequireStructuredCFG = Value; }
 

diff  --git a/llvm/include/llvm/Target/TargetSchedule.td b/llvm/include/llvm/Target/TargetSchedule.td
index 3bc467fbbfb0a..e5a21049bf38c 100644
--- a/llvm/include/llvm/Target/TargetSchedule.td
+++ b/llvm/include/llvm/Target/TargetSchedule.td
@@ -74,12 +74,19 @@ def instregex;
 //
 // See MCSchedule.h for detailed comments.
 class SchedMachineModel {
+  // 每个cycle可以被调度的最大的微指令个数。
   int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle.
+  // 可以被缓存的最大微指令个数
+  // µop cache ???
   int MicroOpBufferSize = -1; // Max micro-ops that can be buffered.
+  //  Loopback buffer???
   int LoopMicroOpBufferSize = -1; // Max micro-ops that can be buffered for
                                   // optimized loop dispatch/execution.
+  // 从cache中加载数据的延迟                                  
   int LoadLatency = -1; // Cycles for loads to access the cache.
+  // 
   int HighLatency = -1; // Approximation of cycles for "high latency" ops.
+  // 分支预测失败的时候, 需要引入的额外的cycle
   int MispredictPenalty = -1; // Extra cycles for a mispredicted branch.
 
   // Per-cycle resources tables.
@@ -114,6 +121,7 @@ class SchedMachineModel {
   // to skip the checks for scheduling information when building LLVM for
   // instructions which have any of the listed predicates in their Predicates
   // field.
+  // some features instruction not support scheduling
   list<Predicate> UnsupportedFeatures = [];
 
   bit NoModel = false; // Special tag to indicate missing machine model.
@@ -128,6 +136,17 @@ def NoSchedModel : SchedMachineModel {
 // similar subtargets.
 class ProcResourceKind;
 
+// issued: 在CPU中被称作指令发射
+// throughput: 单位时间执行的指令条数
+// Latency:指令执行多少个Cycle数之后,能够产生输出
+// ResourceCycles:在拥有流水线机制的CPU,某些指令存在比较特殊的情况,即必须等待指令完成执行完,
+//                才能启动下一条指令,此时需要设置此值。其值=Latency。当throughput < latency,
+//                指令是pipeline 模式,否则是非pipeline模式。指令的并行周期为latency - throughput
+// Buffersize:保留站,即reoreder buffer。保留站是out-of-order CPU用来调度指令使用的,指令会先发射到保留站进行缓冲
+// IssuseWth:每个周期能发射的指令数。单发射或者双发射
+// ReadAdvance:可以理解为指令执行多少cycles之后,需要输入。
+//              此值的设定取决与硬件是否支持的Forwarding机制(下文会提到Forwarding)
+
 // Define a number of interchangeable processor resources. NumUnits
 // determines the throughput of instructions that require the resource.
 //
@@ -171,7 +190,7 @@ class ProcResourceKind;
 //
 // Use BufferSize > 1 for out-of-order executions units with a
 // separate reservation station. This simply models the size of the
-// reservation station.
+// reservation station.  (BufferSize = 保留站中的微指令个数)
 //
 // To model both dispatch/issue groups and in-order execution units,
 // create two types of units, one with BufferSize=0 and one with
@@ -179,21 +198,26 @@ class ProcResourceKind;
 //
 // SchedModel ties these units to a processor for any stand-alone defs
 // of this class.
+// 定义了CPU中执行pipeline的各个部件。
 class ProcResourceUnits<ProcResourceKind kind, int num> {
   ProcResourceKind Kind = kind;
-  int NumUnits = num;
+  int NumUnits = num;                 // 确定要求该资源指令的吞吐率
   ProcResourceKind Super = ?;
-  int BufferSize = -1;
+  int BufferSize = -1;                // 代表保留站大小。            
   SchedMachineModel SchedModel = ?;
 }
 
 // EponymousProcResourceKind helps implement ProcResourceUnits by
 // allowing a ProcResourceUnits definition to reference itself. It
 // should not be referenced anywhere else.
+// 据说它主要是为了能让ProcResourceUnits定义能援引它自己
 def EponymousProcResourceKind : ProcResourceKind;
 
 // Subtargets typically define processor resource kind and number of
 // units in one place.
+// 通过ProcResGroup或者ProcResource来组织与描述资源,
+// 资源描述的最小单位是资源单元(ProcResourceUnits)
+// num表示资源的个数
 class ProcResource<int num> : ProcResourceKind,
   ProcResourceUnits<EponymousProcResourceKind, num>;
 
@@ -250,7 +274,7 @@ class WriteSequence<list<SchedWrite> writes, int rep = 1> : SchedWrite {
 class ProcWriteResources<list<ProcResourceKind> resources> {
   list<ProcResourceKind> ProcResources = resources;
   list<int> ResourceCycles = [];
-  int Latency = 1;
+  int Latency = 1;            // 延迟N个cycle后产生或者需要数据。
   int NumMicroOps = 1;
   bit BeginGroup = false;
   bit EndGroup = false;
@@ -264,7 +288,7 @@ class ProcWriteResources<list<ProcResourceKind> resources> {
   // true for at least one of its writes. This field is only used by
   // MCA for in-order subtargets, and is ignored for other targets.
   bit RetireOOO = false;
-  SchedMachineModel SchedModel = ?;
+  SchedMachineModel SchedModel = ?;    /// SchedModel ties these resources to a processor
 }
 
 // Define the resources and latency of a SchedWrite. This will be used
@@ -333,6 +357,7 @@ class ProcReadAdvance<int cycles, list<SchedWrite> writes = []> {
 // indicate operands that are always read this number of Cycles later
 // than a normal register read, allowing the read's parent instruction
 // to issue earlier relative to the writer.
+// 当前指令在第cycles个周期的时候需要读取当前的值。
 class ReadAdvance<SchedRead read, int cycles, list<SchedWrite> writes = []>
   : ProcReadAdvance<cycles, writes> {
   SchedRead ReadType = read;

diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f5e320e94bdb0..ef3707c30a204 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -271,6 +271,12 @@ bool llvm::haveNoCommonBitsSet(const Value *LHS, const Value *RHS,
   if (match(RHS, m_c_And(m_Not(m_Value(M)), m_Value())) &&
       match(LHS, m_c_And(m_Specific(M), m_Value())))
     return true;
+
+  // Look for a pattern:(A & ~B) op B
+  if (match(LHS, m_c_And(m_Not(m_Specific(RHS)), m_Value())) ||
+      match(RHS, m_c_And(m_Not(m_Specific(LHS)), m_Value())))
+    return true;
+
   IntegerType *IT = cast<IntegerType>(LHS->getType()->getScalarType());
   KnownBits LHSKnown(IT->getBitWidth());
   KnownBits RHSKnown(IT->getBitWidth());

diff  --git a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
index 62948fff86147..445d0f4853169 100644
--- a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
@@ -230,6 +230,7 @@ void ScheduleDAGInstrs::addSchedBarrierDeps() {
 
 /// MO is an operand of SU's instruction that defines a physical register. Adds
 /// data dependencies from SU to any uses of the physical register.
+// 当前函数用于构建SU之间的数据依赖。
 void ScheduleDAGInstrs::addPhysRegDataDeps(SUnit *SU, unsigned OperIdx) {
   const MachineOperand &MO = SU->getInstr()->getOperand(OperIdx);
   assert(MO.isDef() && "expect physreg def");
@@ -241,12 +242,12 @@ void ScheduleDAGInstrs::addPhysRegDataDeps(SUnit *SU, unsigned OperIdx) {
   // "fake" operands added by regalloc.
   const MCInstrDesc *DefMIDesc = &SU->getInstr()->getDesc();
   bool ImplicitPseudoDef = (OperIdx >= DefMIDesc->getNumOperands() &&
-                            !DefMIDesc->hasImplicitDefOfPhysReg(MO.getReg()));
+                            !DefMIDesc->hasImplicitDefOfPhysReg(MO.getReg()));      // 当前指令是否隐含了对当前寄存器的定义。
   for (MCRegAliasIterator Alias(MO.getReg(), TRI, true);
-       Alias.isValid(); ++Alias) {
-    for (Reg2SUnitsMap::iterator I = Uses.find(*Alias); I != Uses.end(); ++I) {
+       Alias.isValid(); ++Alias) {  // 遍历reg相关的全部同名reg
+    for (Reg2SUnitsMap::iterator I = Uses.find(*Alias); I != Uses.end(); ++I) {    // 在use中寻找
       SUnit *UseSU = I->SU;
-      if (UseSU == SU)
+      if (UseSU == SU)     // 如果二者一样, 也就不存在什么依赖了。因为自己本身依赖自己。
         continue;
 
       // Adjust the dependence latency using operand def/use information,
@@ -255,20 +256,21 @@ void ScheduleDAGInstrs::addPhysRegDataDeps(SUnit *SU, unsigned OperIdx) {
       MachineInstr *RegUse = nullptr;
       SDep Dep;
       if (UseOp < 0)
-        Dep = SDep(SU, SDep::Artificial);
+        Dep = SDep(SU, SDep::Artificial);      // 如果使用点在ExitSU上, 那么def和use之前的dep是Artificial
       else {
         // Set the hasPhysRegDefs only for physreg defs that have a use within
         // the scheduling region.
         SU->hasPhysRegDefs = true;
-        Dep = SDep(SU, SDep::Data, *Alias);
-        RegUse = UseSU->getInstr();
+        Dep = SDep(SU, SDep::Data, *Alias);       // 存在数据依赖
+        RegUse = UseSU->getInstr();               // 哪条指令在use????
       }
       const MCInstrDesc *UseMIDesc =
-          (RegUse ? &UseSU->getInstr()->getDesc() : nullptr);
+          (RegUse ? &UseSU->getInstr()->getDesc() : nullptr);         // 获取对应的UseMIDesc
       bool ImplicitPseudoUse =
           (UseMIDesc && UseOp >= ((int)UseMIDesc->getNumOperands()) &&
-           !UseMIDesc->hasImplicitUseOfPhysReg(*Alias));
-      if (!ImplicitPseudoDef && !ImplicitPseudoUse) {
+           !UseMIDesc->hasImplicitUseOfPhysReg(*Alias));              // 当前的指令是对隐含了对Alias寄存器的使用????
+      if (!ImplicitPseudoDef && !ImplicitPseudoUse) {                 // 如果当前指令SU->getInstr()并不是对寄存器的隐含定义;在使用点也不是对寄存器的隐含使用
+        // 对于显示定义和显示使用的寄存器而言, 我们需要为其设置对应的latency
         Dep.setLatency(SchedModel.computeOperandLatency(SU->getInstr(), OperIdx,
                                                         RegUse, UseOp));
         ST.adjustSchedDependency(SU, OperIdx, UseSU, UseOp, Dep);
@@ -305,7 +307,7 @@ void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) {
   // TODO: Using a latency of 1 here for output dependencies assumes
   //       there's no cost for reusing registers.
   SDep::Kind Kind = MO.isUse() ? SDep::Anti : SDep::Output;
-  for (MCRegAliasIterator Alias(Reg, TRI, true); Alias.isValid(); ++Alias) {
+  for (MCRegAliasIterator Alias(Reg, TRI, true); Alias.isValid(); ++Alias) {   // 根据def和reg alias设置图。
     if (!Defs.contains(*Alias))
       continue;
     for (Reg2SUnitsMap::iterator I = Defs.find(*Alias); I != Defs.end(); ++I) {
@@ -325,21 +327,21 @@ void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) {
     }
   }
 
-  if (!MO.isDef()) {
+  if (!MO.isDef()) {            // USE
     SU->hasPhysRegUses = true;
     // Either insert a new Reg2SUnits entry with an empty SUnits list, or
     // retrieve the existing SUnits list for this register's uses.
     // Push this SUnit on the use list.
-    Uses.insert(PhysRegSUOper(SU, OperIdx, Reg));
+    Uses.insert(PhysRegSUOper(SU, OperIdx, Reg));    // 如果是use, 那么将其加入到use队列中。
     if (RemoveKillFlags)
       MO.setIsKill(false);
-  } else {
+  } else {                      // DEF
     addPhysRegDataDeps(SU, OperIdx);
 
     // Clear previous uses and defs of this register and its subergisters.
     for (MCSubRegIterator SubReg(Reg, TRI, true); SubReg.isValid(); ++SubReg) {
       if (Uses.contains(*SubReg))
-        Uses.eraseAll(*SubReg);
+        Uses.eraseAll(*SubReg);       // 删除当前的使用点
       if (!MO.isDead())
         Defs.eraseAll(*SubReg);
     }
@@ -511,7 +513,7 @@ void ScheduleDAGInstrs::addVRegDefDeps(SUnit *SU, unsigned OperIdx) {
 /// antidependency from this SUnit to instructions that occur later in the same
 /// scheduling region if they write the virtual register.
 ///
-/// TODO: Handle ExitSU "uses" properly.
+/// TODO: Handle ExitSU "uses" properly.  这个函数是基于top-down的分析的。
 void ScheduleDAGInstrs::addVRegUseDeps(SUnit *SU, unsigned OperIdx) {
   const MachineInstr *MI = SU->getInstr();
   assert(!MI->isDebugOrPseudoInstr());
@@ -526,7 +528,7 @@ void ScheduleDAGInstrs::addVRegUseDeps(SUnit *SU, unsigned OperIdx) {
 
   // Add antidependences to the following defs of the vreg.
   for (VReg2SUnit &V2SU : make_range(CurrentVRegDefs.find(Reg),
-                                     CurrentVRegDefs.end())) {
+                                     CurrentVRegDefs.end())) {    /// read-after-write
     // Ignore defs for unrelated lanes.
     LaneBitmask PrevDefLaneMask = V2SU.LaneMask;
     if ((PrevDefLaneMask & LaneMask).none())
@@ -534,7 +536,7 @@ void ScheduleDAGInstrs::addVRegUseDeps(SUnit *SU, unsigned OperIdx) {
     if (V2SU.SU == SU)
       continue;
 
-    V2SU.SU->addPred(SDep(SU, SDep::Anti, Reg));
+    V2SU.SU->addPred(SDep(SU, SDep::Anti, Reg));   // 因此进入过在使用reg的时候同时存在def, 那就证明当前的环境是read-after-write
   }
 }
 
@@ -572,17 +574,17 @@ void ScheduleDAGInstrs::initSUnits() {
   SUnits.reserve(NumRegionInstrs);
 
   for (MachineInstr &MI : make_range(RegionBegin, RegionEnd)) {
-    if (MI.isDebugOrPseudoInstr())
+    if (MI.isDebugOrPseudoInstr())      // 如果是debuginst, 直接跳过。
       continue;
 
     SUnit *SU = newSUnit(&MI);
     MISUnitMap[&MI] = SU;
 
     SU->isCall = MI.isCall();
-    SU->isCommutable = MI.isCommutable();
+    SU->isCommutable = MI.isCommutable();       // 当前指令是否是可交换的 op a, b === op b, a
 
     // Assign the Latency field of SU using target-provided information.
-    SU->Latency = SchedModel.computeInstrLatency(SU->getInstr());
+    SU->Latency = SchedModel.computeInstrLatency(SU->getInstr());     // 当前指令运行的时候所占用的cycle
 
     // If this SUnit uses a reserved or unbuffered resource, mark it as such.
     //
@@ -592,7 +594,7 @@ void ScheduleDAGInstrs::initSUnits() {
     // Unbuffered resources prevent execution of subsequent instructions that
     // require the same resources. This is used for in-order execution pipelines
     // within an out-of-order core. These are identified by BufferSize=1.
-    if (SchedModel.hasInstrSchedModel()) {
+    if (SchedModel.hasInstrSchedModel()) {    ///   ????
       const MCSchedClassDesc *SC = getSchedClass(SU);
       for (const MCWriteProcResEntry &PRE :
            make_range(SchedModel.getWriteProcResBegin(SC),
@@ -795,7 +797,7 @@ void ScheduleDAGInstrs::buildSchedGraph(AAResults *AA,
 
   // Model data dependencies between instructions being scheduled and the
   // ExitSU.
-  addSchedBarrierDeps();
+  addSchedBarrierDeps();    // 先确定当前的ExitSU
 
   // Walk the list of instructions, from bottom moving up.
   MachineInstr *DbgMI = nullptr;
@@ -869,7 +871,7 @@ void ScheduleDAGInstrs::buildSchedGraph(AAResults *AA,
         continue;
       Register Reg = MO.getReg();
       if (Register::isPhysicalRegister(Reg)) {
-        addPhysRegDeps(SU, j);
+        addPhysRegDeps(SU, j);    // todo
       } else if (Register::isVirtualRegister(Reg) && MO.readsReg()) {
         addVRegUseDeps(SU, j);
       }

diff  --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
index 7a5e8ac6075e6..50d8e87d79766 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
@@ -1941,6 +1941,7 @@ static int checkSpecialNodes(const SUnit *left, const SUnit *right) {
 
 /// CalcNodeSethiUllmanNumber - Compute Sethi Ullman number.
 /// Smaller number is the higher priority.
+/// https://www.docin.com/p-271407915.html
 static unsigned
 CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector<unsigned> &SUNumbers) {
   if (SUNumbers[SU->NodeNum] != 0)

diff  --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index b2a8c8bdd78ca..56c9cdee29635 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -328,7 +328,7 @@ void ScheduleDAGSDNodes::BuildSchedUnits() {
   // of -1 means the SDNode does not yet have an associated SUnit.
   unsigned NumNodes = 0;
   for (SDNode &NI : DAG->allnodes()) {
-    NI.setNodeId(-1);
+    NI.setNodeId(-1);         // -1代表当前的节点还没有对应的SUnit
     ++NumNodes;
   }
 
@@ -353,14 +353,14 @@ void ScheduleDAGSDNodes::BuildSchedUnits() {
     for (const SDValue &Op : NI->op_values())
       if (Visited.insert(Op.getNode()).second)
         Worklist.push_back(Op.getNode());
-
+    // 有些节点不需要调度, 因此会忽略
     if (isPassiveNode(NI))  // Leaf node, e.g. a TargetImmediate.
       continue;
 
     // If this node has already been processed, stop now.
     if (NI->getNodeId() != -1) continue;
 
-    SUnit *NodeSUnit = newSUnit(NI);
+    SUnit *NodeSUnit = newSUnit(NI);   // 每个节点配置一个调度实体
 
     // See if anything is glued to this node, if so, add them to glued
     // nodes.  Nodes can have at most one glue input and one glue output.  Glue
@@ -378,41 +378,41 @@ void ScheduleDAGSDNodes::BuildSchedUnits() {
     }
 
     // Scan down to find any glued succs.
-    N = NI;
-    while (N->getValueType(N->getNumValues()-1) == MVT::Glue) {
+    N = NI;  // 寻找一条连续的glue链, 在同一个BB内一个值有且只有一个或者0个glue节点。
+    while (N->getValueType(N->getNumValues()-1) == MVT::Glue) {   // ?? 约定俗称???
       SDValue GlueVal(N, N->getNumValues()-1);
 
-      // There are either zero or one users of the Glue result.
+      // There are either zero or one users of the Glue result. //  why???
       bool HasGlueUse = false;
-      for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
+      for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();  // 在其被使用的点上, 只有一个或者0个glue节点。
            UI != E; ++UI)
         if (GlueVal.isOperandOf(*UI)) {
           HasGlueUse = true;
           assert(N->getNodeId() == -1 && "Node already inserted!");
-          N->setNodeId(NodeSUnit->NodeNum);
+          N->setNodeId(NodeSUnit->NodeNum);      // 这些被glue在一起的节点, 使用相同的node num
           N = *UI;
           if (N->isMachineOpcode() && TII->get(N->getMachineOpcode()).isCall())
-            NodeSUnit->isCall = true;
+            NodeSUnit->isCall = true;     // 是一个函数调用。
           break;
         }
       if (!HasGlueUse) break;
     }
 
     if (NodeSUnit->isCall)
-      CallSUnits.push_back(NodeSUnit);
+      CallSUnits.push_back(NodeSUnit);      // 当前调度实体中存在一个意思call指令, 因此将NodeSUnit压入CallSUnits
 
     // Schedule zero-latency TokenFactor below any nodes that may increase the
     // schedule height. Otherwise, ancestors of the TokenFactor may appear to
-    // have false stalls.
+    // have false stalls.  不太理解。
     if (NI->getOpcode() == ISD::TokenFactor)
       NodeSUnit->isScheduleLow = true;
 
     // If there are glue operands involved, N is now the bottom-most node
     // of the sequence of nodes that are glued together.
     // Update the SUnit.
-    NodeSUnit->setNode(N);
+    NodeSUnit->setNode(N);   // =====> 当前调度实体对应了节点N。
     assert(N->getNodeId() == -1 && "Node already inserted!");
-    N->setNodeId(NodeSUnit->NodeNum);
+    N->setNodeId(NodeSUnit->NodeNum);     // =====> 当前节点N对应的NodeId是NodeSUnit->NodeNum, 有点类似并查集, 其中N代表某一个group
 
     // Compute NumRegDefsLeft. This must be done before AddSchedEdges.
     InitNumRegDefsLeft(NodeSUnit);
@@ -451,7 +451,7 @@ void ScheduleDAGSDNodes::AddSchedEdges() {
       unsigned Opc = MainNode->getMachineOpcode();
       const MCInstrDesc &MCID = TII->get(Opc);
       for (unsigned i = 0; i != MCID.getNumOperands(); ++i) {
-        if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) {
+        if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) {   // ???
           SU->isTwoAddress = true;
           break;
         }
@@ -482,7 +482,7 @@ void ScheduleDAGSDNodes::AddSchedEdges() {
 
         EVT OpVT = N->getOperand(i).getValueType();
         assert(OpVT != MVT::Glue && "Glued nodes should be in same sunit!");
-        bool isChain = OpVT == MVT::Other;
+        bool isChain = OpVT == MVT::Other;   // A control flow dependency is represented by chain edges, which have the special type MVT::Other
 
         unsigned PhysReg = 0;
         int Cost = 1;
@@ -498,7 +498,7 @@ void ScheduleDAGSDNodes::AddSchedEdges() {
         if (Cost >= 0 && !StressSched)
           PhysReg = 0;
 
-        // If this is a ctrl dep, latency is 1.
+        // If this is a ctrl dep, latency is 1.   如果这里存在一个控制依赖, 那么latency是1
         unsigned OpLatency = isChain ? 1 : OpSU->Latency;
         // Special-case TokenFactor chains as zero-latency.
         if(isChain && OpN->getOpcode() == ISD::TokenFactor)
@@ -507,7 +507,7 @@ void ScheduleDAGSDNodes::AddSchedEdges() {
         SDep Dep = isChain ? SDep(OpSU, SDep::Barrier)
           : SDep(OpSU, SDep::Data, PhysReg);
         Dep.setLatency(OpLatency);
-        if (!isChain && !UnitLatencies) {
+        if (!isChain && !UnitLatencies) {   // 没有控制依赖 & 不在乎延迟
           computeOperandLatency(OpN, N, i, Dep);
           ST.adjustSchedDependency(OpSU, DefIdx, SU, i, Dep);
         }
@@ -555,7 +555,7 @@ void ScheduleDAGSDNodes::RegDefIter::InitNodeNumDefs() {
     return;
   }
   unsigned POpc = Node->getMachineOpcode();
-  if (POpc == TargetOpcode::IMPLICIT_DEF) {
+  if (POpc == TargetOpcode::IMPLICIT_DEF) {     // This is the MachineInstr-level equivalent of undef
     // No register need be allocated for this.
     NodeNumDefs = 0;
     return;
@@ -568,10 +568,10 @@ void ScheduleDAGSDNodes::RegDefIter::InitNodeNumDefs() {
     NodeNumDefs = 0;
     return;
   }
-  unsigned NRegDefs = SchedDAG->TII->get(Node->getMachineOpcode()).getNumDefs();
+  unsigned NRegDefs = SchedDAG->TII->get(Node->getMachineOpcode()).getNumDefs();   // 当前机器指令所定义的总和。
   // Some instructions define regs that are not represented in the selection DAG
   // (e.g. unused flags). See tMOVi8. Make sure we don't access past NumValues.
-  NodeNumDefs = std::min(Node->getNumValues(), NRegDefs);
+  NodeNumDefs = std::min(Node->getNumValues(), NRegDefs);   // 从当前指令对应的value总和以及NRegDefs中选择一个。
   DefIdx = 0;
 }
 
@@ -621,15 +621,15 @@ void ScheduleDAGSDNodes::computeLatency(SUnit *SU) {
   }
 
   // Check to see if the scheduler cares about latencies.
-  if (forceUnitLatencies()) {
+  if (forceUnitLatencies()) {      // 调度的时候不care延迟 在这种情况下可以将全部的延迟设置成1
     SU->Latency = 1;
     return;
   }
 
-  if (!InstrItins || InstrItins->isEmpty()) {
+  if (!InstrItins || InstrItins->isEmpty()) {    // 在程序后端没有InstrItins信息的时候
     if (N && N->isMachineOpcode() &&
         TII->isHighLatencyDef(N->getMachineOpcode()))
-      SU->Latency = HighLatencyCycles;
+      SU->Latency = HighLatencyCycles;          // 同时可以区分下每条指令的延迟信息。目前只有两个10或者1
     else
       SU->Latency = 1;
     return;
@@ -637,7 +637,7 @@ void ScheduleDAGSDNodes::computeLatency(SUnit *SU) {
 
   // Compute the latency for the node.  We use the sum of the latencies for
   // all nodes glued together into this SUnit.
-  SU->Latency = 0;
+  SU->Latency = 0;  // 使用TII将全部的Glue节点的延迟做一个累加, 当做当前调度实体的整体延迟。
   for (SDNode *N = SU->getNode(); N; N = N->getGluedNode())
     if (N->isMachineOpcode())
       SU->Latency += TII->getInstrLatency(InstrItins, N);

diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index e3ff00131dbed..8ff3b41d29958 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -259,7 +259,7 @@ namespace llvm {
     if (auto *SchedulerCtor = ST.getDAGScheduler(OptLevel)) {
       return SchedulerCtor(IS, OptLevel);
     }
-
+    // 标记下  下面是llvm在pre-RA阶段目前正在支持的指令调度算法。
     if (OptLevel == CodeGenOpt::None ||
         (ST.enableMachineScheduler() && ST.enableMachineSchedDefaultSched()) ||
         TLI->getSchedulingPreference() == Sched::Source)

diff  --git a/llvm/lib/CodeGen/StackMaps.cpp b/llvm/lib/CodeGen/StackMaps.cpp
index 36e8f129ea158..10a3e4fb82e23 100644
--- a/llvm/lib/CodeGen/StackMaps.cpp
+++ b/llvm/lib/CodeGen/StackMaps.cpp
@@ -177,6 +177,8 @@ unsigned StackMaps::getNextMetaArgIdx(const MachineInstr *MI, unsigned CurIdx) {
 /// Go up the super-register chain until we hit a valid dwarf register number.
 static unsigned getDwarfRegNum(unsigned Reg, const TargetRegisterInfo *TRI) {
   int RegNum = TRI->getDwarfRegNum(Reg, false);
+  dbgs() << "dump reg:\n";
+  dbgs() << "         " << printReg(Reg, TRI) << "\n";
   for (MCSuperRegIterator SR(Reg, TRI); SR.isValid() && RegNum < 0; ++SR)
     RegNum = TRI->getDwarfRegNum(*SR, false);
 

diff  --git a/llvm/lib/CodeGen/TargetSchedule.cpp b/llvm/lib/CodeGen/TargetSchedule.cpp
index ce59452fd1b8f..d34616add9865 100644
--- a/llvm/lib/CodeGen/TargetSchedule.cpp
+++ b/llvm/lib/CodeGen/TargetSchedule.cpp
@@ -179,7 +179,7 @@ static unsigned findUseIdx(const MachineInstr *MI, unsigned UseOperIdx) {
   }
   return UseIdx;
 }
-
+// 计算Def-Use之间的latency
 // Top-level API for clients that know the operand indices.
 unsigned TargetSchedModel::computeOperandLatency(
   const MachineInstr *DefMI, unsigned DefOperIdx,

diff  --git a/llvm/lib/Target/AArch64/AArch64SchedA64FX.td b/llvm/lib/Target/AArch64/AArch64SchedA64FX.td
index b6741d418ef0b..2179714bb0bb3 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedA64FX.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedA64FX.td
@@ -33,32 +33,32 @@ let SchedModel = A64FXModel in {
 // A64FXIP*
 
 // Port 0
-def A64FXIPFLA : ProcResource<1>;
+def A64FXIPFLA : ProcResource<1>;         // floating-point operation pipeline
 
 // Port 1
-def A64FXIPPR : ProcResource<1>;
+def A64FXIPPR : ProcResource<1>;          // predicate operation pipeline
 
 // Port 2
-def A64FXIPEXA : ProcResource<1>;
+def A64FXIPEXA : ProcResource<1>;         // integer operation pipeline
 
 // Port 3
-def A64FXIPFLB : ProcResource<1>;
+def A64FXIPFLB : ProcResource<1>;         // floating-point operation pipeline
 
 // Port 4
-def A64FXIPEXB : ProcResource<1>;
+def A64FXIPEXB : ProcResource<1>;         // integer operation pipeline
 
 // Port 5
-def A64FXIPEAGA : ProcResource<1>;
+def A64FXIPEAGA : ProcResource<1>;        // address calculation pipeline (EAGA/EAGB)
 
 // Port 6
-def A64FXIPEAGB : ProcResource<1>;
+def A64FXIPEAGB : ProcResource<1>;        // address calculation pipeline (EAGA/EAGB)
 
 // Port 7
-def A64FXIPBR : ProcResource<1>;
+def A64FXIPBR : ProcResource<1>;          // branch execution pipeline
 
 // Define groups for the functional units on each issue port.  Each group
 // created will be used by a WriteRes later on.
-
+// https://github.com/fujitsu/A64FX/blob/master/doc/A64FX_Microarchitecture_Manual_en_1.5.pdf
 def A64FXGI7 : ProcResGroup<[A64FXIPBR]>;
 
 def A64FXGI0 : ProcResGroup<[A64FXIPFLA]>;

diff  --git a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
index 37950e105bdc1..f7a18a33ddc06 100644
--- a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
+++ b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
@@ -148,8 +148,8 @@ void BPFAsmPrinter::emitInstruction(const MachineInstr *MI) {
 }
 
 // Force static initialization.
-extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmPrinter() {
-  RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget());
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmPrinter() {   // register printer
+  RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget());       // 在Target上直接放置一个new函数, 相当于是注册了如何生成BPFAsmPrinter的方式
   RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget());
   RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget());
 }

diff  --git a/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp b/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
index 49eb9ad62c562..f1fe3fb9c5715 100644
--- a/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
+++ b/llvm/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
@@ -24,8 +24,9 @@ Target &llvm::getTheBPFTarget() {
   return TheBPFTarget;
 }
 
+// 向LLVM注册目标体系结构。
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTargetInfo() {
-  TargetRegistry::RegisterTarget(getTheBPFTarget(), "bpf", "BPF (host endian)",
+  TargetRegistry::RegisterTarget(getTheBPFTarget(), "bpf", "BPF (host endian)",   // 构造出一个有效的结构
                                  "BPF", [](Triple::ArchType) { return false; },
                                  true);
   RegisterTarget<Triple::bpfel, /*HasJIT=*/true> X(

diff  --git a/llvm/test/CodeGen/AArch64/arm64-patchpoint.ll b/llvm/test/CodeGen/AArch64/arm64-patchpoint.ll
index b64f2455908e0..f068a5ca8df04 100644
--- a/llvm/test/CodeGen/AArch64/arm64-patchpoint.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-patchpoint.ll
@@ -82,4 +82,3 @@ entry:
 declare void @llvm.experimental.stackmap(i64, i32, ...)
 declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
 declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
-

diff  --git a/llvm/utils/TableGen/CodeGenInstruction.cpp b/llvm/utils/TableGen/CodeGenInstruction.cpp
index 3933ce6e1106c..f791aa7cab9cf 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -29,7 +29,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
   hasOptionalDef = false;
   isVariadic = false;
 
-  DagInit *OutDI = R->getValueAsDag("OutOperandList");
+  DagInit *OutDI = R->getValueAsDag("OutOperandList");      // 指令的输出
 
   if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) {
     if (Init->getDef()->getName() != "outs")
@@ -57,6 +57,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
   unsigned e = InDI->getNumArgs() + OutDI->getNumArgs();
   OperandList.reserve(e);
   bool VariadicOuts = false;
+  // RC:$src1
+  // RC----> ArgInit
+  // $src1 ----> ArgName
   for (unsigned i = 0; i != e; ++i){
     Init *ArgInit;
     StringRef ArgName;
@@ -80,7 +83,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
     std::string OperandNamespace = "MCOI";
     unsigned NumOps = 1;
     DagInit *MIOpInfo = nullptr;
-    if (Rec->isSubClassOf("RegisterOperand")) {
+    if (Rec->isSubClassOf("RegisterOperand")) {       // 寄存器被当做是操作数。
       PrintMethod = std::string(Rec->getValueAsString("PrintMethod"));
       OperandType = std::string(Rec->getValueAsString("OperandType"));
       OperandNamespace = std::string(Rec->getValueAsString("OperandNamespace"));
@@ -123,7 +126,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
                                        "' instruction!");
 
     // Check that the operand has a name and that it's unique.
-    if (ArgName.empty())
+    if (ArgName.empty())      // ArgName不应该是空的
       PrintFatalError(R->getLoc(), "In instruction '" + R->getName() +
                                        "', operand #" + Twine(i) +
                                        " has no name!");

diff  --git a/llvm/utils/TableGen/CodeGenRegisters.cpp b/llvm/utils/TableGen/CodeGenRegisters.cpp
index db15bac9c3f8f..952c34a71253d 100644
--- a/llvm/utils/TableGen/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/CodeGenRegisters.cpp
@@ -1109,6 +1109,7 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records,
 
   // Read in the user-defined (named) sub-register indices.
   // More indices will be synthesized later.
+  // 获取全部的SubRegIndex子类型。
   std::vector<Record*> SRIs = Records.getAllDerivedDefinitions("SubRegIndex");
   llvm::sort(SRIs, LessRecord());
   for (unsigned i = 0, e = SRIs.size(); i != e; ++i)
@@ -1225,7 +1226,7 @@ CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) {
   CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def];
   if (Idx)
     return Idx;
-  SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1);
+  SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1);  // SubRegIndex record -----> CodeGenSubRegIndex object
   Idx = &SubRegIndices.back();
   return Idx;
 }

diff  --git a/llvm/utils/TableGen/CodeGenSchedule.cpp b/llvm/utils/TableGen/CodeGenSchedule.cpp
index ee52b2e7ab9f3..67b900a583b02 100644
--- a/llvm/utils/TableGen/CodeGenSchedule.cpp
+++ b/llvm/utils/TableGen/CodeGenSchedule.cpp
@@ -185,7 +185,7 @@ CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
   // defined, and populate SchedReads and SchedWrites vectors. Implicit
   // SchedReadWrites that represent sequences derived from expanded variant will
   // be inferred later.
-  collectSchedRW();
+  collectSchedRW();       // 收集所有的SchedRW
 
   // Instantiate a CodeGenSchedClass for each unique SchedRW signature directly
   // required by an instruction definition, and populate SchedClassIdxMap. Set
@@ -870,20 +870,21 @@ void CodeGenSchedModels::collectSchedClasses() {
   // Create a SchedClass for each unique combination of itinerary class and
   // SchedRW list.
   for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
-    Record *ItinDef = Inst->TheDef->getValueAsDef("Itinerary");
+    Record *ItinDef = Inst->TheDef->getValueAsDef("Itinerary");     // 获取当前指令具体的执行步骤
     IdxVec Writes, Reads;
+    // 根据SchedRW获取当前指令的可读可写窗台。
     if (!Inst->TheDef->isValueUnset("SchedRW"))
       findRWs(Inst->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads);
 
     // ProcIdx == 0 indicates the class applies to all processors.
     unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, /*ProcIndices*/{0});
-    InstrClassMap[Inst->TheDef] = SCIdx;
+    InstrClassMap[Inst->TheDef] = SCIdx;     // InstrClassMap中保存了哪条指令对应哪个CodeGenSchedClass
   }
   // Create classes for InstRW defs.
   RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
   llvm::sort(InstRWDefs, LessRecord());
   LLVM_DEBUG(dbgs() << "\n+++ SCHED CLASSES (createInstRWClass) +++\n");
-  for (Record *RWDef : InstRWDefs)
+  for (Record *RWDef : InstRWDefs)    // 遍历全部的InstRW
     createInstRWClass(RWDef);
 
   NumInstrSchedClasses = SchedClasses.size();
@@ -896,6 +897,7 @@ void CodeGenSchedModels::collectSchedClasses() {
   LLVM_DEBUG(
       dbgs()
       << "\n+++ ITINERARIES and/or MACHINE MODELS (collectSchedClasses) +++\n");
+      // 遍历全部指令
   for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
     StringRef InstName = Inst->TheDef->getName();
     unsigned SCIdx = getSchedClassIdx(*Inst);
@@ -1052,15 +1054,16 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
     if (Pos == InstrClassMap.end())
       PrintFatalError(InstDef->getLoc(), "No sched class for instruction.");
     unsigned SCIdx = Pos->second;
-    ClassInstrs[SCIdx].push_back(InstDef);
+    ClassInstrs[SCIdx].push_back(InstDef);    // 当前使用scheduleclass的instr关系表: 1 vs N
   }
   // For each set of Instrs, create a new class if necessary, and map or remap
   // the Instrs to it.
   for (auto &Entry : ClassInstrs) {
-    unsigned OldSCIdx = Entry.first;
-    ArrayRef<Record*> InstDefs = Entry.second;
+    unsigned OldSCIdx = Entry.first;              // Old ScheduleClass index
+    ArrayRef<Record*> InstDefs = Entry.second;    // 当前指令record
     // If the all instrs in the current class are accounted for, then leave
     // them mapped to their old class.
+    // 如果存在SC, 那么吧InstRW加入到旧的SC中
     if (OldSCIdx) {
       const RecVec &RWDefs = SchedClasses[OldSCIdx].InstRWs;
       if (!RWDefs.empty()) {
@@ -1096,7 +1099,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
           continue;
         }
       }
-    }
+    }   // 如果没有, 那么自己创建一个。
     unsigned SCIdx = SchedClasses.size();
     SchedClasses.emplace_back(SCIdx, createSchedClassName(InstDefs), nullptr);
     CodeGenSchedClass &SC = SchedClasses.back();
@@ -1130,7 +1133,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
     }
     // Map each Instr to this new class.
     for (Record *InstDef : InstDefs)
-      InstrClassMap[InstDef] = SCIdx;
+      InstrClassMap[InstDef] = SCIdx;     // 将原来的关系直接覆盖掉。
     SC.InstRWs.push_back(InstRWDef);
   }
 }

diff  --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp
index 7311819f77ff8..0cf5033291785 100644
--- a/llvm/utils/TableGen/CodeGenTarget.cpp
+++ b/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -448,7 +448,7 @@ CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
 }
 
 void CodeGenTarget::ReadInstructions() const {
-  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");   // 当前架构中定义的instruction
   if (Insts.size() <= 2)
     PrintFatalError("No 'Instruction' subclasses defined!");
 
@@ -481,6 +481,7 @@ unsigned CodeGenTarget::getNumFixedInstructions() {
 
 /// Return all of the instructions defined by the target, ordered by
 /// their enum value.
+/// 首先将TargetOpcodes.def中的指令加入enum, 然后再将架构相关的指令加入到enum中。
 void CodeGenTarget::ComputeInstrsByEnum() const {
   const auto &Insts = getInstructions();
   for (const char *const *p = FixedInstrs; *p; ++p) {


        


More information about the llvm-branch-commits mailing list