@@ -111,6 +111,7 @@ class SubtargetEmitter {
111
111
Record *FindReadAdvance (const CodeGenSchedRW &SchedRead,
112
112
const CodeGenProcModel &ProcModel);
113
113
void ExpandProcResources (RecVec &PRVec, std::vector<int64_t > &Cycles,
114
+ std::vector<int64_t > &StartAtCycles,
114
115
const CodeGenProcModel &ProcModel);
115
116
void GenSchedClassTables (const CodeGenProcModel &ProcModel,
116
117
SchedClassTables &SchedTables);
@@ -968,6 +969,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
968
969
// resource groups and super resources that cover them.
969
970
void SubtargetEmitter::ExpandProcResources (RecVec &PRVec,
970
971
std::vector<int64_t > &Cycles,
972
+ std::vector<int64_t > &StartAtCycles,
971
973
const CodeGenProcModel &PM) {
972
974
assert (PRVec.size () == Cycles.size () && " failed precondition" );
973
975
for (unsigned i = 0 , e = PRVec.size (); i != e; ++i) {
@@ -990,6 +992,7 @@ void SubtargetEmitter::ExpandProcResources(RecVec &PRVec,
990
992
SubDef->getLoc ());
991
993
PRVec.push_back (SuperDef);
992
994
Cycles.push_back (Cycles[i]);
995
+ StartAtCycles.push_back (StartAtCycles[i]);
993
996
SubDef = SuperDef;
994
997
}
995
998
}
@@ -1006,6 +1009,7 @@ void SubtargetEmitter::ExpandProcResources(RecVec &PRVec,
1006
1009
if (SubI == SubE) {
1007
1010
PRVec.push_back (PR);
1008
1011
Cycles.push_back (Cycles[i]);
1012
+ StartAtCycles.push_back (StartAtCycles[i]);
1009
1013
}
1010
1014
}
1011
1015
}
@@ -1140,29 +1144,66 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
1140
1144
std::vector<int64_t > Cycles =
1141
1145
WriteRes->getValueAsListOfInts (" ResourceCycles" );
1142
1146
1143
- if (Cycles.empty ()) {
1144
- // If ResourceCycles is not provided, default to one cycle per
1145
- // resource.
1146
- Cycles.resize (PRVec.size (), 1 );
1147
- } else if (Cycles.size () != PRVec.size ()) {
1147
+ std::vector<int64_t > StartAtCycles =
1148
+ WriteRes->getValueAsListOfInts (" StartAtCycles" );
1149
+
1150
+ // Check consistency of the two vectors carrying the start and
1151
+ // stop cycles of the resources.
1152
+ if (!Cycles.empty () && Cycles.size () != PRVec.size ()) {
1148
1153
// If ResourceCycles is provided, check consistency.
1149
1154
PrintFatalError (
1150
1155
WriteRes->getLoc (),
1151
- Twine (" Inconsistent resource cycles: ! size(ResourceCycles) != "
1152
- " ! size(ProcResources): " )
1156
+ Twine (" Inconsistent resource cycles: size(ResourceCycles) != "
1157
+ " size(ProcResources): " )
1153
1158
.concat (Twine (PRVec.size ()))
1154
1159
.concat (" vs " )
1155
1160
.concat (Twine (Cycles.size ())));
1156
1161
}
1157
1162
1158
- ExpandProcResources (PRVec, Cycles, ProcModel);
1163
+ if (!StartAtCycles.empty () && StartAtCycles.size () != PRVec.size ()) {
1164
+ PrintFatalError (
1165
+ WriteRes->getLoc (),
1166
+ Twine (" Inconsistent resource cycles: size(StartAtCycles) != "
1167
+ " size(ProcResources): " )
1168
+ .concat (Twine (StartAtCycles.size ()))
1169
+ .concat (" vs " )
1170
+ .concat (Twine (PRVec.size ())));
1171
+ }
1172
+
1173
+ if (Cycles.empty ()) {
1174
+ // If ResourceCycles is not provided, default to one cycle
1175
+ // per resource.
1176
+ Cycles.resize (PRVec.size (), 1 );
1177
+ }
1178
+
1179
+ if (StartAtCycles.empty ()) {
1180
+ // If StartAtCycles is not provided, reserve the resource
1181
+ // starting from cycle 0.
1182
+ StartAtCycles.resize (PRVec.size (), 0 );
1183
+ }
1184
+
1185
+ assert (StartAtCycles.size () == Cycles.size ());
1186
+
1187
+ ExpandProcResources (PRVec, Cycles, StartAtCycles, ProcModel);
1188
+ assert (StartAtCycles.size () == Cycles.size ());
1159
1189
1160
1190
for (unsigned PRIdx = 0 , PREnd = PRVec.size ();
1161
1191
PRIdx != PREnd; ++PRIdx) {
1162
1192
MCWriteProcResEntry WPREntry;
1163
1193
WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx (PRVec[PRIdx]);
1164
1194
assert (WPREntry.ProcResourceIdx && " Bad ProcResourceIdx" );
1165
1195
WPREntry.Cycles = Cycles[PRIdx];
1196
+ WPREntry.StartAtCycle = StartAtCycles[PRIdx];
1197
+ if (StartAtCycles[PRIdx] > Cycles[PRIdx]) {
1198
+ PrintFatalError (WriteRes->getLoc (),
1199
+ Twine (" Inconsistent resource cycles: StartAtCycles "
1200
+ " < Cycles must hold." ));
1201
+ }
1202
+ if (StartAtCycles[PRIdx] < 0 ) {
1203
+ PrintFatalError (WriteRes->getLoc (),
1204
+ Twine (" Invalid value: StartAtCycle "
1205
+ " must be a non-negative value." ));
1206
+ }
1166
1207
// If this resource is already used in this sequence, add the current
1167
1208
// entry's cycles so that the same resource appears to be used
1168
1209
// serially, rather than multiple parallel uses. This is important for
@@ -1171,6 +1212,15 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
1171
1212
for ( ; WPRIdx != WPREnd; ++WPRIdx) {
1172
1213
if (WriteProcResources[WPRIdx].ProcResourceIdx
1173
1214
== WPREntry.ProcResourceIdx ) {
1215
+ // TODO: multiple use of the same resources would
1216
+ // require either 1. thinking of how to handle multiple
1217
+ // intervals for the same resource in
1218
+ // `<Target>WriteProcResTable` (see
1219
+ // `SubtargetEmitter::EmitSchedClassTables`), or
1220
+ // 2. thinking how to merge multiple intervals into a
1221
+ // single interval.
1222
+ assert (WPREntry.StartAtCycle == 0 &&
1223
+ " multiple use ofthe same resource is not yet handled" );
1174
1224
WriteProcResources[WPRIdx].Cycles += WPREntry.Cycles ;
1175
1225
break ;
1176
1226
}
@@ -1275,15 +1325,16 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
1275
1325
void SubtargetEmitter::EmitSchedClassTables (SchedClassTables &SchedTables,
1276
1326
raw_ostream &OS) {
1277
1327
// Emit global WriteProcResTable.
1278
- OS << " \n // {ProcResourceIdx, Cycles}\n "
1279
- << " extern const llvm::MCWriteProcResEntry "
1280
- << Target << " WriteProcResTable[] = {\n "
1281
- << " { 0, 0}, // Invalid\n " ;
1328
+ OS << " \n // {ProcResourceIdx, Cycles, StartAtCycle }\n "
1329
+ << " extern const llvm::MCWriteProcResEntry " << Target
1330
+ << " WriteProcResTable[] = {\n "
1331
+ << " { 0, 0, 0 }, // Invalid\n " ;
1282
1332
for (unsigned WPRIdx = 1 , WPREnd = SchedTables.WriteProcResources .size ();
1283
1333
WPRIdx != WPREnd; ++WPRIdx) {
1284
1334
MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources [WPRIdx];
1285
1335
OS << " {" << format (" %2d" , WPREntry.ProcResourceIdx ) << " , "
1286
- << format (" %2d" , WPREntry.Cycles ) << " }" ;
1336
+ << format (" %2d" , WPREntry.Cycles ) << " , "
1337
+ << format (" %2d" , WPREntry.StartAtCycle ) << " }" ;
1287
1338
if (WPRIdx + 1 < WPREnd)
1288
1339
OS << ' ,' ;
1289
1340
OS << " // #" << WPRIdx << ' \n ' ;
0 commit comments