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) { _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits