@@ -124,7 +124,11 @@ class UnitTestRunner : public SILFunctionTransform {
124
124
<< name << " with: " ;
125
125
for (unsigned long index = 0 , size = components.size (); index < size;
126
126
++index ) {
127
- llvm::errs () << components[index ];
127
+ auto componentString = components[index ].trim ();
128
+ if (componentString.empty ())
129
+ continue ;
130
+
131
+ llvm::errs () << componentString;
128
132
if (index != size - 1 ) {
129
133
llvm::errs () << " , " ;
130
134
}
@@ -364,9 +368,12 @@ struct ScopedAddressLivenessTest : UnitTest {
364
368
};
365
369
366
370
// Arguments:
367
- // - variadic list of live-range defining values
371
+ // - variadic list of live-range defining values or instructions
368
372
// Dumps:
369
373
// - the liveness result and boundary
374
+ //
375
+ // Computes liveness for the specified def nodes by finding all their direct SSA
376
+ // uses. If the def is an instruction, then all results are considered.
370
377
struct MultiDefLivenessTest : UnitTest {
371
378
MultiDefLivenessTest (UnitTestRunner *pass) : UnitTest(pass) {}
372
379
@@ -376,9 +383,16 @@ struct MultiDefLivenessTest : UnitTest {
376
383
377
384
llvm::outs () << " MultiDef lifetime analysis:\n " ;
378
385
while (arguments.hasUntaken ()) {
379
- SILValue value = arguments.takeValue ();
380
- llvm::outs () << " def: " << value;
381
- liveness.initializeDef (value);
386
+ auto argument = arguments.takeArgument ();
387
+ if (isa<InstructionArgument>(argument)) {
388
+ auto *instruction = cast<InstructionArgument>(argument).getValue ();
389
+ llvm::outs () << " def instruction: " << instruction;
390
+ liveness.initializeDef (instruction);
391
+ } else {
392
+ SILValue value = cast<ValueArgument>(argument).getValue ();
393
+ llvm::outs () << " def value: " << value;
394
+ liveness.initializeDef (value);
395
+ }
382
396
}
383
397
liveness.computeSimple ();
384
398
liveness.print (llvm::outs ());
@@ -389,6 +403,66 @@ struct MultiDefLivenessTest : UnitTest {
389
403
}
390
404
};
391
405
406
+ // Arguments:
407
+ // - the string "defs:"
408
+ // - list of live-range defining values or instructions
409
+ // - the string "uses:"
410
+ // - variadic list of live-range user instructions
411
+ // Dumps:
412
+ // - the liveness result and boundary
413
+ //
414
+ // Computes liveness for the specified def nodes by considering only the
415
+ // specified uses. The actual uses of the def nodes are ignored.
416
+ //
417
+ // This is useful for testing non-ssa liveness, for example, of memory
418
+ // locations. In that case, the def nodes may be stores and the uses may be
419
+ // destroy_addrs.
420
+ struct MultiDefUseLivenessTest : UnitTest {
421
+ MultiDefUseLivenessTest (UnitTestRunner *pass) : UnitTest(pass) {}
422
+
423
+ void invoke (Arguments &arguments) override {
424
+ SmallVector<SILBasicBlock *, 8 > discoveredBlocks;
425
+ MultiDefPrunedLiveness liveness (getFunction (), &discoveredBlocks);
426
+
427
+ llvm::outs () << " MultiDef lifetime analysis:\n " ;
428
+ if (arguments.takeString () != " defs:" ) {
429
+ llvm::report_fatal_error (
430
+ " test specification expects the 'defs:' label\n " );
431
+ }
432
+ while (true ) {
433
+ auto argument = arguments.takeArgument ();
434
+ if (isa<InstructionArgument>(argument)) {
435
+ auto *instruction = cast<InstructionArgument>(argument).getValue ();
436
+ llvm::outs () << " def instruction: " << *instruction;
437
+ liveness.initializeDef (instruction);
438
+ continue ;
439
+ }
440
+ if (isa<ValueArgument>(argument)) {
441
+ SILValue value = cast<ValueArgument>(argument).getValue ();
442
+ llvm::outs () << " def value: " << value;
443
+ liveness.initializeDef (value);
444
+ continue ;
445
+ }
446
+ if (cast<StringArgument>(argument).getValue () != " uses:" ) {
447
+ llvm::report_fatal_error (
448
+ " test specification expects the 'uses:' label\n " );
449
+ }
450
+ break ;
451
+ }
452
+ while (arguments.hasUntaken ()) {
453
+ auto *inst = arguments.takeInstruction ();
454
+ // lifetimeEnding has no effects on liveness, it's only a cache for the
455
+ // caller.
456
+ liveness.updateForUse (inst, /* lifetimeEnding*/ false );
457
+ }
458
+ liveness.print (llvm::outs ());
459
+
460
+ PrunedLivenessBoundary boundary;
461
+ liveness.computeBoundary (boundary);
462
+ boundary.print (llvm::outs ());
463
+ }
464
+ };
465
+
392
466
// Arguments:
393
467
// - bool: pruneDebug
394
468
// - bool: maximizeLifetimes
@@ -811,6 +885,7 @@ void UnitTestRunner::withTest(StringRef name, Doit doit) {
811
885
ADD_UNIT_TEST_SUBCLASS (" is-lexical" , IsLexicalTest)
812
886
ADD_UNIT_TEST_SUBCLASS (" linear-liveness" , LinearLivenessTest)
813
887
ADD_UNIT_TEST_SUBCLASS (" multidef-liveness" , MultiDefLivenessTest)
888
+ ADD_UNIT_TEST_SUBCLASS (" multidefuse-liveness" , MultiDefUseLivenessTest)
814
889
ADD_UNIT_TEST_SUBCLASS (" ossa-lifetime-completion" , OSSALifetimeCompletionTest)
815
890
ADD_UNIT_TEST_SUBCLASS (" pruned-liveness-boundary-with-list-of-last-users-insertion-points" , PrunedLivenessBoundaryWithListOfLastUsersInsertionPointsTest)
816
891
ADD_UNIT_TEST_SUBCLASS (" shrink-borrow-scope" , ShrinkBorrowScopeTest)
0 commit comments