LLVM学习笔记(42)

3.6.2.4. 资源描述的调度

3.6.2.4.1. SchedReadWrite数据的收集

描述类似SandyBridge处理器指令执行细节的方法不同于Atom这样的处理器,上面的处理对这些处理器不适用。这些处理器使用WriteRes或SchedWriteRes描述SchedWrite对资源的使用,依靠ReadAdvance或SchedReadAdvance来描述对特定的SchedWrite以及特定SchedRead的预读情况。为了处理这些定义,首先需要找出与当前处理的调度类型相关的SchedWrite与SchedRead定义。

SubtargetEmitter::EmitSchedModel(续)

1266    OS << "\n// ===============================================================\n"

1267       << "// Data tables for the new per-operand machine model.\n";

1268 

1269    SchedClassTables SchedTables;

1270    for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),

1271           PE = SchedModels.procModelEnd(); PI != PE; ++PI) {

1272      GenSchedClassTables(*PI, SchedTables);

1273    }

1274    EmitSchedClassTables(SchedTables, OS);

1275 

1276    // Emit the processor machine model

1277    EmitProcessorModels(OS);

1278    // Emit the processor lookup data

1279    EmitProcessorLookup(OS);

1280 

1281    OS << "#undef DBGFIELD";

1282  }

1269行的SchedClassTables是SubtargetEmitter的内嵌类,在SchedClassDesc表中每个处理器的每个调度类型都有一个对应项。

38         struct SchedClassTables {

39           std::vector<std::vector<MCSchedClassDesc> > ProcSchedClasses;

40          std::vector<MCWriteProcResEntry> WriteProcResources;

41           std::vector<MCWriteLatencyEntry> WriteLatencies;

42           std::vector<std::string> WriterNames;

43          std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;

44      

45           // Reserve an invalid entry at index 0

46           SchedClassTables() {

47             ProcSchedClasses.resize(1);

48             WriteProcResources.resize(1);

49             WriteLatencies.resize(1);

50             WriterNames.push_back("InvalidWrite");

51             ReadAdvanceEntries.resize(1);

52           }

53         };

其中MCSchedClassDesc的定义如下。它是MC对资源调度的描述方式。

101     struct MCSchedClassDesc {

102       static const unsigned short InvalidNumMicroOps = UINT16_MAX;

103       static const unsigned short VariantNumMicroOps = UINT16_MAX - 1;

104    

105     #ifndef NDEBUG

106       const char* Name;

107     #endif

108       unsigned short NumMicroOps;

109       bool     BeginGroup;

110       bool     EndGroup;

111       unsigned WriteProcResIdx; // First index into WriteProcResTable.

112       unsigned NumWriteProcResEntries;

113       unsigned WriteLatencyIdx; // First index into WriteLatencyTable.

114       unsigned NumWriteLatencyEntries;

115       unsigned ReadAdvanceIdx; // First index into ReadAdvanceTable.

116       unsigned NumReadAdvanceEntries;

117    

118       bool isValid() const {

119         return NumMicroOps != InvalidNumMicroOps;

120       }

121       bool isVariant() const {

122         return NumMicroOps == VariantNumMicroOps;

123       }

124     };

类型MCWriteProcResEntry用于描述指定调度类型在指定周期数里消耗指定处理器资源。

55       struct MCWriteProcResEntry {

56         unsigned ProcResourceIdx;

57         unsigned Cycles;

58      

59         bool operator==(const MCWriteProcResEntry &Other) const {

60           return ProcResourceIdx == Other.ProcResourceIdx && Cycles == Other.Cycles;

61         }

62       };

类型MCWriteLatencyEntry用于记录执行一个指定的SchedWrite定义所需的处理器周期。

69       struct MCWriteLatencyEntry {

70         int Cycles;

71         unsigned WriteResourceID;

72      

73         bool operator==(const MCWriteLatencyEntry &Other) const {

74           return Cycles == Other.Cycles && WriteResourceID == Other.WriteResourceID;

75         }

76       };

MCReadAdvanceEntry由ReadAdvance定义创建,用于描述处理器的流水线旁路,这时写操作的结果可提前若干周期(在ReadAdvance定义中给出)传给后续的读操作。这时UseIdx是这个ReadAdvance定义的索引,WriteResourceID则是旁路支持的SchedWrite的索引,Cycles是缩短的周期(如果是负数则是延长)。

86       struct MCReadAdvanceEntry {

87         unsigned UseIdx;

88         unsigned WriteResourceID;

89         int Cycles;

90      

91         bool operator==(const MCReadAdvanceEntry &Other) const {

92           return UseIdx == Other.UseIdx && WriteResourceID == Other.WriteResourceID

93             && Cycles == Other.Cycles;

94         }

95       };

1272行的GenSchedClassTables()方法就是为特定的处理器生成对应的MCSchedClassDesc实例。在816行CodeGenProcModel::hasInstrSchedModel()在容器WriteResDefs或ItinRWDefs不为空时返回true。这意味着对该处理器而言,存在援引它的WriteRes定义或ItinRW定义。注意815行,不管怎么样,SchedTables的ProcSchedClasses容器与CodeGenSchedModels的ProcModels容器最终将同一大小。

813     void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,

814                                                SchedClassTables &SchedTables) {

815       SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1);

816       if (!ProcModel.hasInstrSchedModel())

817         return;

818    

819       std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back();

820       for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),

821              SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {

822         DEBUG(SCI->dump(&SchedModels));

823    

824         SCTab.resize(SCTab.size() + 1);

825         MCSchedClassDesc &SCDesc = SCTab.back();

826         // SCDesc.Name is guarded by NDEBUG

827         SCDesc.NumMicroOps = 0;

828         SCDesc.BeginGroup = false;

829         SCDesc.EndGroup = false;

830         SCDesc.WriteProcResIdx = 0;

831         SCDesc.WriteLatencyIdx = 0;

832         SCDesc.ReadAdvanceIdx = 0;

833    

834         // A Variant SchedClass has no resources of its own.

835         bool HasVariants = false;

836         for (std::vector<CodeGenSchedTransition>::const_iterator

837                TI = SCI->Transitions.begin(), TE = SCI->Transitions.end();

838              TI != TE; ++TI) {

839           if (TI->ProcIndices[0] == 0) {

840      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值