@@ -223,9 +223,130 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
223
223
return LastPoppedValue;
224
224
}
225
225
226
+ mcdc::TVIdxBuilder::TVIdxBuilder (const SmallVectorImpl<ConditionIDs> &NextIDs,
227
+ int Offset)
228
+ : Indices(NextIDs.size()) {
229
+ // Construct Nodes and set up each InCount
230
+ auto N = NextIDs.size ();
231
+ SmallVector<MCDCNode> Nodes (N);
232
+ for (unsigned ID = 0 ; ID < N; ++ID) {
233
+ for (unsigned C = 0 ; C < 2 ; ++C) {
234
+ #ifndef NDEBUG
235
+ Indices[ID][C] = INT_MIN;
236
+ #endif
237
+ auto NextID = NextIDs[ID][C];
238
+ Nodes[ID].NextIDs [C] = NextID;
239
+ if (NextID >= 0 )
240
+ ++Nodes[NextID].InCount ;
241
+ }
242
+ }
243
+
244
+ // Sort key ordered by <-Width, Ord>
245
+ SmallVector<std::tuple<int , // / -Width
246
+ unsigned , // / Ord
247
+ int , // / ID
248
+ unsigned // / Cond (0 or 1)
249
+ >>
250
+ Decisions;
251
+
252
+ // Traverse Nodes to assign Idx
253
+ SmallVector<int > Q;
254
+ assert (Nodes[0 ].InCount == 0 );
255
+ Nodes[0 ].Width = 1 ;
256
+ Q.push_back (0 );
257
+
258
+ unsigned Ord = 0 ;
259
+ while (!Q.empty ()) {
260
+ auto IID = Q.begin ();
261
+ int ID = *IID;
262
+ Q.erase (IID);
263
+ auto &Node = Nodes[ID];
264
+ assert (Node.Width > 0 );
265
+
266
+ for (unsigned I = 0 ; I < 2 ; ++I) {
267
+ auto NextID = Node.NextIDs [I];
268
+ assert (NextID != 0 && " NextID should not point to the top" );
269
+ if (NextID < 0 ) {
270
+ // Decision
271
+ Decisions.emplace_back (-Node.Width , Ord++, ID, I);
272
+ assert (Ord == Decisions.size ());
273
+ continue ;
274
+ }
275
+
276
+ // Inter Node
277
+ auto &NextNode = Nodes[NextID];
278
+ assert (NextNode.InCount > 0 );
279
+
280
+ // Assign Idx
281
+ assert (Indices[ID][I] == INT_MIN);
282
+ Indices[ID][I] = NextNode.Width ;
283
+ auto NextWidth = int64_t (NextNode.Width ) + Node.Width ;
284
+ if (NextWidth > HardMaxTVs) {
285
+ NumTestVectors = HardMaxTVs; // Overflow
286
+ return ;
287
+ }
288
+ NextNode.Width = NextWidth;
289
+
290
+ // Ready if all incomings are processed.
291
+ // Or NextNode.Width hasn't been confirmed yet.
292
+ if (--NextNode.InCount == 0 )
293
+ Q.push_back (NextID);
294
+ }
295
+ }
296
+
297
+ llvm::sort (Decisions);
298
+
299
+ // Assign TestVector Indices in Decision Nodes
300
+ int64_t CurIdx = 0 ;
301
+ for (auto [NegWidth, Ord, ID, C] : Decisions) {
302
+ int Width = -NegWidth;
303
+ assert (Nodes[ID].Width == Width);
304
+ assert (Nodes[ID].NextIDs [C] < 0 );
305
+ assert (Indices[ID][C] == INT_MIN);
306
+ Indices[ID][C] = Offset + CurIdx;
307
+ CurIdx += Width;
308
+ if (CurIdx > HardMaxTVs) {
309
+ NumTestVectors = HardMaxTVs; // Overflow
310
+ return ;
311
+ }
312
+ }
313
+
314
+ assert (CurIdx < HardMaxTVs);
315
+ NumTestVectors = CurIdx;
316
+
317
+ #ifndef NDEBUG
318
+ for (const auto &Idxs : Indices)
319
+ for (auto Idx : Idxs)
320
+ assert (Idx != INT_MIN);
321
+ SavedNodes = std::move (Nodes);
322
+ #endif
323
+ }
324
+
226
325
namespace {
227
326
228
- class MCDCRecordProcessor {
327
+ // / Construct this->NextIDs with Branches for TVIdxBuilder to use it
328
+ // / before MCDCRecordProcessor().
329
+ class NextIDsBuilder {
330
+ protected:
331
+ SmallVector<mcdc::ConditionIDs> NextIDs;
332
+
333
+ public:
334
+ NextIDsBuilder (const ArrayRef<const CounterMappingRegion *> Branches)
335
+ : NextIDs(Branches.size()) {
336
+ #ifndef NDEBUG
337
+ DenseSet<mcdc::ConditionID> SeenIDs;
338
+ #endif
339
+ for (const auto *Branch : Branches) {
340
+ const auto &BranchParams = Branch->getBranchParams ();
341
+ assert (BranchParams.ID >= 0 && " CondID isn't set" );
342
+ assert (SeenIDs.insert (BranchParams.ID ).second && " Duplicate CondID" );
343
+ NextIDs[BranchParams.ID ] = BranchParams.Conds ;
344
+ }
345
+ assert (SeenIDs.size () == Branches.size ());
346
+ }
347
+ };
348
+
349
+ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
229
350
// / A bitmap representing the executed test vectors for a boolean expression.
230
351
// / Each index of the bitmap corresponds to a possible test vector. An index
231
352
// / with a bit value of '1' indicates that the corresponding Test Vector
@@ -243,9 +364,6 @@ class MCDCRecordProcessor {
243
364
// / Total number of conditions in the boolean expression.
244
365
unsigned NumConditions;
245
366
246
- // / Mapping of a condition ID to its corresponding branch params.
247
- llvm::DenseMap<unsigned , mcdc::ConditionIDs> CondsMap;
248
-
249
367
// / Vector used to track whether a condition is constant folded.
250
368
MCDCRecord::BoolVector Folded;
251
369
@@ -256,34 +374,43 @@ class MCDCRecordProcessor {
256
374
// / ExecutedTestVectorBitmap.
257
375
MCDCRecord::TestVectors ExecVectors;
258
376
377
+ #ifndef NDEBUG
378
+ DenseSet<unsigned > TVIdxs;
379
+ #endif
380
+
259
381
public:
260
382
MCDCRecordProcessor (const BitVector &Bitmap,
261
383
const CounterMappingRegion &Region,
262
384
ArrayRef<const CounterMappingRegion *> Branches)
263
- : Bitmap(Bitmap ), Region(Region ),
264
- DecisionParams (Region.getDecisionParams()), Branches(Branches ),
265
- NumConditions(DecisionParams.NumConditions),
385
+ : NextIDsBuilder(Branches ), TVIdxBuilder( this ->NextIDs), Bitmap(Bitmap ),
386
+ Region (Region), DecisionParams(Region.getDecisionParams()),
387
+ Branches(Branches), NumConditions(DecisionParams.NumConditions),
266
388
Folded(NumConditions, false ), IndependencePairs(NumConditions) {}
267
389
268
390
private:
269
391
// Walk the binary decision diagram and try assigning both false and true to
270
392
// each node. When a terminal node (ID == 0) is reached, fill in the value in
271
393
// the truth table.
272
394
void buildTestVector (MCDCRecord::TestVector &TV, mcdc::ConditionID ID,
273
- unsigned Index) {
395
+ int TVIdx, unsigned Index) {
274
396
assert ((Index & (1 << ID)) == 0 );
275
397
276
398
for (auto MCDCCond : {MCDCRecord::MCDC_False, MCDCRecord::MCDC_True}) {
277
399
static_assert (MCDCRecord::MCDC_False == 0 );
278
400
static_assert (MCDCRecord::MCDC_True == 1 );
279
401
Index |= MCDCCond << ID;
280
402
TV[ID] = MCDCCond;
281
- auto NextID = CondsMap[ID][MCDCCond];
403
+ auto NextID = NextIDs[ID][MCDCCond];
404
+ auto NextTVIdx = TVIdx + Indices[ID][MCDCCond];
405
+ assert (NextID == SavedNodes[ID].NextIDs [MCDCCond]);
282
406
if (NextID >= 0 ) {
283
- buildTestVector (TV, NextID, Index);
407
+ buildTestVector (TV, NextID, NextTVIdx, Index);
284
408
continue ;
285
409
}
286
410
411
+ assert (TVIdx < SavedNodes[ID].Width );
412
+ assert (TVIdxs.insert (NextTVIdx).second && " Duplicate TVIdx" );
413
+
287
414
if (!Bitmap[DecisionParams.BitmapIdx * CHAR_BIT + Index])
288
415
continue ;
289
416
@@ -304,9 +431,12 @@ class MCDCRecordProcessor {
304
431
void findExecutedTestVectors () {
305
432
// Walk the binary decision diagram to enumerate all possible test vectors.
306
433
// We start at the root node (ID == 0) with all values being DontCare.
434
+ // `TVIdx` starts with 0 and is in the traversal.
307
435
// `Index` encodes the bitmask of true values and is initially 0.
308
436
MCDCRecord::TestVector TV (NumConditions, MCDCRecord::MCDC_DontCare);
309
- buildTestVector (TV, 0 , 0 );
437
+ buildTestVector (TV, 0 , 0 , 0 );
438
+ assert (TVIdxs.size () == unsigned (NumTestVectors) &&
439
+ " TVIdxs wasn't fulfilled" );
310
440
}
311
441
312
442
// Find an independence pair for each condition:
@@ -367,7 +497,6 @@ class MCDCRecordProcessor {
367
497
// from being measured.
368
498
for (const auto *B : Branches) {
369
499
const auto &BranchParams = B->getBranchParams ();
370
- CondsMap[BranchParams.ID ] = BranchParams.Conds ;
371
500
PosToID[I] = BranchParams.ID ;
372
501
CondLoc[I] = B->startLoc ();
373
502
Folded[I++] = (B->Count .isZero () && B->FalseCount .isZero ());
0 commit comments