[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