@@ -286,17 +286,8 @@ class MCDCRecordProcessor {
286
286
TestVectors((size_t )1 << NumConditions) {}
287
287
288
288
private:
289
- void recordTestVector (MCDCRecord::TestVector &TV,
289
+ void recordTestVector (MCDCRecord::TestVector &TV, unsigned Index,
290
290
MCDCRecord::CondState Result) {
291
- // Calculate an index that is used to identify the test vector in a vector
292
- // of test vectors. This index also corresponds to the index values of an
293
- // MCDC Region's bitmap (see findExecutedTestVectors()).
294
- unsigned Index = 0 ;
295
- for (auto Cond = std::rbegin (TV); Cond != std::rend (TV); ++Cond) {
296
- Index <<= 1 ;
297
- Index |= (*Cond == MCDCRecord::MCDC_True) ? 0x1 : 0x0 ;
298
- }
299
-
300
291
// Copy the completed test vector to the vector of testvectors.
301
292
TestVectors[Index] = TV;
302
293
@@ -305,38 +296,25 @@ class MCDCRecordProcessor {
305
296
TestVectors[Index].push_back (Result);
306
297
}
307
298
308
- void shouldCopyOffTestVectorForTruePath (MCDCRecord::TestVector &TV,
309
- unsigned ID) {
310
- // Branch regions are hashed based on an ID.
311
- const CounterMappingRegion *Branch = Map[ID];
312
-
313
- TV[ID - 1 ] = MCDCRecord::MCDC_True;
314
- if (Branch->MCDCParams .TrueID > 0 )
315
- buildTestVector (TV, Branch->MCDCParams .TrueID );
316
- else
317
- recordTestVector (TV, MCDCRecord::MCDC_True);
318
- }
319
-
320
- void shouldCopyOffTestVectorForFalsePath (MCDCRecord::TestVector &TV,
321
- unsigned ID) {
322
- // Branch regions are hashed based on an ID.
299
+ // Walk the binary decision diagram and try assigning both false and true to
300
+ // each node. When a terminal node (ID == 0) is reached, fill in the value in
301
+ // the truth table.
302
+ void buildTestVector (MCDCRecord::TestVector &TV, unsigned ID,
303
+ unsigned Index) {
323
304
const CounterMappingRegion *Branch = Map[ID];
324
305
325
306
TV[ID - 1 ] = MCDCRecord::MCDC_False;
326
307
if (Branch->MCDCParams .FalseID > 0 )
327
- buildTestVector (TV, Branch->MCDCParams .FalseID );
308
+ buildTestVector (TV, Branch->MCDCParams .FalseID , Index );
328
309
else
329
- recordTestVector (TV, MCDCRecord::MCDC_False);
330
- }
310
+ recordTestVector (TV, Index, MCDCRecord::MCDC_False);
331
311
332
- // / Starting with the base test vector, build a comprehensive list of
333
- // / possible test vectors by recursively walking the branch condition IDs
334
- // / provided. Once an end node is reached, record the test vector in a vector
335
- // / of test vectors that can be matched against during MC/DC analysis, and
336
- // / then reset the positions to 'DontCare'.
337
- void buildTestVector (MCDCRecord::TestVector &TV, unsigned ID = 1 ) {
338
- shouldCopyOffTestVectorForTruePath (TV, ID);
339
- shouldCopyOffTestVectorForFalsePath (TV, ID);
312
+ Index |= 1 << (ID - 1 );
313
+ TV[ID - 1 ] = MCDCRecord::MCDC_True;
314
+ if (Branch->MCDCParams .TrueID > 0 )
315
+ buildTestVector (TV, Branch->MCDCParams .TrueID , Index);
316
+ else
317
+ recordTestVector (TV, Index, MCDCRecord::MCDC_True);
340
318
341
319
// Reset back to DontCare.
342
320
TV[ID - 1 ] = MCDCRecord::MCDC_DontCare;
@@ -353,71 +331,33 @@ class MCDCRecordProcessor {
353
331
}
354
332
}
355
333
356
- // / For a given condition and two executed Test Vectors, A and B, see if the
357
- // / two test vectors match forming an Independence Pair for the condition.
358
- // / For two test vectors to match, the following must be satisfied:
359
- // / - The condition's value in each test vector must be opposite.
360
- // / - The result's value in each test vector must be opposite.
361
- // / - All other conditions' values must be equal or marked as "don't care".
362
- bool matchTestVectors (unsigned Aidx, unsigned Bidx, unsigned ConditionIdx) {
363
- const MCDCRecord::TestVector &A = ExecVectors[Aidx];
364
- const MCDCRecord::TestVector &B = ExecVectors[Bidx];
365
-
366
- // If condition values in both A and B aren't opposites, no match.
367
- // Because a value can be 0 (false), 1 (true), or -1 (DontCare), a check
368
- // that "XOR != 1" will ensure that the values are opposites and that
369
- // neither of them is a DontCare.
370
- // 1 XOR 0 == 1 | 0 XOR 0 == 0 | -1 XOR 0 == -1
371
- // 1 XOR 1 == 0 | 0 XOR 1 == 1 | -1 XOR 1 == -2
372
- // 1 XOR -1 == -2 | 0 XOR -1 == -1 | -1 XOR -1 == 0
373
- if ((A[ConditionIdx] ^ B[ConditionIdx]) != 1 )
374
- return false ;
375
-
376
- // If the results of both A and B aren't opposites, no match.
377
- if ((A[NumConditions] ^ B[NumConditions]) != 1 )
378
- return false ;
379
-
380
- for (unsigned Idx = 0 ; Idx < NumConditions; ++Idx) {
381
- // Look for other conditions that don't match. Skip over the given
382
- // Condition as well as any conditions marked as "don't care".
383
- const auto ARecordTyForCond = A[Idx];
384
- const auto BRecordTyForCond = B[Idx];
385
- if (Idx == ConditionIdx ||
386
- ARecordTyForCond == MCDCRecord::MCDC_DontCare ||
387
- BRecordTyForCond == MCDCRecord::MCDC_DontCare)
388
- continue ;
389
-
390
- // If there is a condition mismatch with any of the other conditions,
391
- // there is no match for the test vectors.
392
- if (ARecordTyForCond != BRecordTyForCond)
393
- return false ;
394
- }
395
-
396
- // Otherwise, match.
397
- return true ;
398
- }
399
-
400
- // / Find all possible Independence Pairs for a boolean expression given its
401
- // / executed Test Vectors. This process involves looking at each condition
402
- // / and attempting to find two Test Vectors that "match", giving us a pair.
334
+ // Find an independence pair for each condition:
335
+ // - The condition is true in one test and false in the other.
336
+ // - The decision outcome is true one test and false in the other.
337
+ // - All other conditions' values must be equal or marked as "don't care".
403
338
void findIndependencePairs () {
404
339
unsigned NumTVs = ExecVectors.size ();
405
-
406
- // For each condition.
407
- for (unsigned C = 0 ; C < NumConditions; ++C) {
408
- bool PairFound = false ;
409
-
410
- // For each executed test vector.
411
- for (unsigned I = 0 ; !PairFound && I < NumTVs; ++I) {
412
- // Compared to every other executed test vector.
413
- for (unsigned J = 0 ; !PairFound && J < NumTVs; ++J) {
414
- if (I == J)
340
+ for (unsigned I = 1 ; I < NumTVs; ++I) {
341
+ const MCDCRecord::TestVector &A = ExecVectors[I];
342
+ for (unsigned J = 0 ; J < I; ++J) {
343
+ const MCDCRecord::TestVector &B = ExecVectors[J];
344
+ // Enumerate two execution vectors whose outcomes are different.
345
+ if (A[NumConditions] == B[NumConditions])
346
+ continue ;
347
+ unsigned Flip = NumConditions, Idx;
348
+ for (Idx = 0 ; Idx < NumConditions; ++Idx) {
349
+ MCDCRecord::CondState ACond = A[Idx], BCond = B[Idx];
350
+ if (ACond == BCond || ACond == MCDCRecord::MCDC_DontCare ||
351
+ BCond == MCDCRecord::MCDC_DontCare)
415
352
continue ;
416
-
417
- // If a matching pair of vectors is found, record them.
418
- if ((PairFound = matchTestVectors (I, J, C)))
419
- IndependencePairs[C] = std::make_pair (I + 1 , J + 1 );
353
+ if (Flip != NumConditions)
354
+ break ;
355
+ Flip = Idx;
420
356
}
357
+ // If the two vectors differ in exactly one condition, ignoring DontCare
358
+ // conditions, we have found an independence pair.
359
+ if (Idx == NumConditions && Flip != NumConditions)
360
+ IndependencePairs.insert ({Flip, std::make_pair (J + 1 , I + 1 )});
421
361
}
422
362
}
423
363
}
@@ -454,11 +394,11 @@ class MCDCRecordProcessor {
454
394
Folded[I++] = (B->Count .isZero () && B->FalseCount .isZero ());
455
395
}
456
396
457
- // Initialize a base test vector as 'DontCare'.
397
+ // Walk the binary decision diagram to enumerate all possible test vectors.
398
+ // We start at the root node (ID == 1) with all values being DontCare.
399
+ // `Index` encodes the bitmask of true values and is initially 0.
458
400
MCDCRecord::TestVector TV (NumConditions, MCDCRecord::MCDC_DontCare);
459
-
460
- // Use the base test vector to build the list of all possible test vectors.
461
- buildTestVector (TV);
401
+ buildTestVector (TV, 1 , 0 );
462
402
463
403
// Using Profile Bitmap from runtime, mark the executed test vectors.
464
404
findExecutedTestVectors (ExecutedTestVectorBitmap);
0 commit comments