@@ -601,6 +601,65 @@ bool MultiDefPrunedLiveness::isUserBeforeDef(SILInstruction *user) const {
601
601
}
602
602
}
603
603
604
+ namespace swift ::test {
605
+ // Arguments:
606
+ // - the string "defs:"
607
+ // - list of live-range defining values or instructions
608
+ // - the string "uses:"
609
+ // - variadic list of live-range user instructions
610
+ // Dumps:
611
+ // - the liveness result and boundary
612
+ //
613
+ // Computes liveness for the specified def nodes by considering only the
614
+ // specified uses. The actual uses of the def nodes are ignored.
615
+ //
616
+ // This is useful for testing non-ssa liveness, for example, of memory
617
+ // locations. In that case, the def nodes may be stores and the uses may be
618
+ // destroy_addrs.
619
+ static FunctionTest MultiDefUseLivenessTest (
620
+ " multidefuse-liveness" , [](auto &function, auto &arguments, auto &test) {
621
+ SmallVector<SILBasicBlock *, 8 > discoveredBlocks;
622
+ MultiDefPrunedLiveness liveness (&function, &discoveredBlocks);
623
+
624
+ llvm::outs () << " MultiDef lifetime analysis:\n " ;
625
+ if (arguments.takeString () != " defs:" ) {
626
+ llvm::report_fatal_error (
627
+ " test specification expects the 'defs:' label\n " );
628
+ }
629
+ while (true ) {
630
+ auto argument = arguments.takeArgument ();
631
+ if (isa<InstructionArgument>(argument)) {
632
+ auto *instruction = cast<InstructionArgument>(argument).getValue ();
633
+ llvm::outs () << " def instruction: " << *instruction;
634
+ liveness.initializeDef (instruction);
635
+ continue ;
636
+ }
637
+ if (isa<ValueArgument>(argument)) {
638
+ SILValue value = cast<ValueArgument>(argument).getValue ();
639
+ llvm::outs () << " def value: " << value;
640
+ liveness.initializeDef (value);
641
+ continue ;
642
+ }
643
+ if (cast<StringArgument>(argument).getValue () != " uses:" ) {
644
+ llvm::report_fatal_error (
645
+ " test specification expects the 'uses:' label\n " );
646
+ }
647
+ break ;
648
+ }
649
+ while (arguments.hasUntaken ()) {
650
+ auto *inst = arguments.takeInstruction ();
651
+ // lifetimeEnding has no effects on liveness, it's only a cache for the
652
+ // caller.
653
+ liveness.updateForUse (inst, /* lifetimeEnding*/ false );
654
+ }
655
+ liveness.print (llvm::outs ());
656
+
657
+ PrunedLivenessBoundary boundary;
658
+ liveness.computeBoundary (boundary);
659
+ boundary.print (llvm::outs ());
660
+ });
661
+ } // end namespace swift::test
662
+
604
663
void MultiDefPrunedLiveness::findBoundariesInBlock (
605
664
SILBasicBlock *block, bool isLiveOut,
606
665
PrunedLivenessBoundary &boundary) const {
0 commit comments