@@ -124,7 +124,11 @@ class UnitTestRunner : public SILFunctionTransform {
124124 << name << " with: " ;
125125 for (unsigned long index = 0 , size = components.size (); index < size;
126126 ++index) {
127- llvm::errs () << components[index];
127+ auto componentString = components[index].trim ();
128+ if (componentString.empty ())
129+ continue ;
130+
131+ llvm::errs () << componentString;
128132 if (index != size - 1 ) {
129133 llvm::errs () << " , " ;
130134 }
@@ -364,9 +368,12 @@ struct ScopedAddressLivenessTest : UnitTest {
364368};
365369
366370// Arguments:
367- // - variadic list of live-range defining values
371+ // - variadic list of live-range defining values or instructions
368372// Dumps:
369373// - 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.
370377struct MultiDefLivenessTest : UnitTest {
371378 MultiDefLivenessTest (UnitTestRunner *pass) : UnitTest(pass) {}
372379
@@ -376,9 +383,16 @@ struct MultiDefLivenessTest : UnitTest {
376383
377384 llvm::outs () << " MultiDef lifetime analysis:\n " ;
378385 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+ }
382396 }
383397 liveness.computeSimple ();
384398 liveness.print (llvm::outs ());
@@ -389,6 +403,66 @@ struct MultiDefLivenessTest : UnitTest {
389403 }
390404};
391405
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+
392466// Arguments:
393467// - bool: pruneDebug
394468// - bool: maximizeLifetimes
@@ -811,6 +885,7 @@ void UnitTestRunner::withTest(StringRef name, Doit doit) {
811885 ADD_UNIT_TEST_SUBCLASS (" is-lexical" , IsLexicalTest)
812886 ADD_UNIT_TEST_SUBCLASS (" linear-liveness" , LinearLivenessTest)
813887 ADD_UNIT_TEST_SUBCLASS (" multidef-liveness" , MultiDefLivenessTest)
888+ ADD_UNIT_TEST_SUBCLASS (" multidefuse-liveness" , MultiDefUseLivenessTest)
814889 ADD_UNIT_TEST_SUBCLASS (" ossa-lifetime-completion" , OSSALifetimeCompletionTest)
815890 ADD_UNIT_TEST_SUBCLASS (" pruned-liveness-boundary-with-list-of-last-users-insertion-points" , PrunedLivenessBoundaryWithListOfLastUsersInsertionPointsTest)
816891 ADD_UNIT_TEST_SUBCLASS (" shrink-borrow-scope" , ShrinkBorrowScopeTest)
0 commit comments