@@ -393,64 +393,50 @@ void MemoryLocations::initFieldsCounter(Location &loc) {
393
393
// MemoryDataflow members
394
394
// ===----------------------------------------------------------------------===//
395
395
396
- MemoryDataflow::MemoryDataflow (SILFunction *function, unsigned numLocations) {
397
- // Resizing is mandatory! Just adding states with push_back would potentially
398
- // invalidate previous pointers to states, which are stored in block2State.
399
- blockStates.resize (function->size ());
400
-
401
- unsigned idx = 0 ;
402
- unsigned numBits = numLocations;
403
- for (SILBasicBlock &BB : *function) {
404
- BlockState *st = &blockStates[idx++];
405
- st->block = &BB;
406
- st->entrySet .resize (numBits);
407
- st->genSet .resize (numBits);
408
- st->killSet .resize (numBits);
409
- st->exitSet .resize (numBits);
410
- block2State[&BB] = st;
411
- }
412
- }
396
+ MemoryDataflow::MemoryDataflow (SILFunction *function, unsigned numLocations) :
397
+ blockStates(function, [numLocations](SILBasicBlock *block) {
398
+ return BlockState (numLocations);
399
+ }) {}
413
400
414
401
void MemoryDataflow::entryReachabilityAnalysis () {
415
- llvm::SmallVector<BlockState *, 16 > workList;
416
- BlockState *entryState = &blockStates[0 ];
417
- assert (entryState ==
418
- block2State[entryState->block ->getParent ()->getEntryBlock ()]);
419
- entryState->reachableFromEntry = true ;
420
- workList.push_back (entryState);
402
+ llvm::SmallVector<SILBasicBlock *, 16 > workList;
403
+ auto entry = blockStates.entry ();
404
+ entry.data .reachableFromEntry = true ;
405
+ workList.push_back (&entry.block );
421
406
422
407
while (!workList.empty ()) {
423
- BlockState *state = workList.pop_back_val ();
424
- for (SILBasicBlock *succ : state-> block ->getSuccessorBlocks ()) {
425
- BlockState * succState = block2State [succ];
426
- if (!succState-> reachableFromEntry ) {
427
- succState-> reachableFromEntry = true ;
428
- workList.push_back (succState );
408
+ SILBasicBlock *block = workList.pop_back_val ();
409
+ for (SILBasicBlock *succ : block->getSuccessorBlocks ()) {
410
+ BlockState & succState = blockStates [succ];
411
+ if (!succState. reachableFromEntry ) {
412
+ succState. reachableFromEntry = true ;
413
+ workList.push_back (succ );
429
414
}
430
415
}
431
416
}
432
417
}
433
418
434
419
void MemoryDataflow::exitReachableAnalysis () {
435
- llvm::SmallVector<BlockState *, 16 > workList;
436
- for (BlockState &state : blockStates) {
437
- if (state .block -> getTerminator ()->isFunctionExiting ()) {
438
- state .exitReachability = ExitReachability::ReachesExit;
439
- workList.push_back (&state );
440
- } else if (isa<UnreachableInst>(state .block -> getTerminator ())) {
441
- state .exitReachability = ExitReachability::ReachesUnreachable;
442
- workList.push_back (&state );
420
+ llvm::SmallVector<SILBasicBlock *, 16 > workList;
421
+ for (auto bd : blockStates) {
422
+ if (bd .block . getTerminator ()->isFunctionExiting ()) {
423
+ bd. data .exitReachability = ExitReachability::ReachesExit;
424
+ workList.push_back (&bd. block );
425
+ } else if (isa<UnreachableInst>(bd .block . getTerminator ())) {
426
+ bd. data .exitReachability = ExitReachability::ReachesUnreachable;
427
+ workList.push_back (&bd. block );
443
428
}
444
429
}
445
430
while (!workList.empty ()) {
446
- BlockState *state = workList.pop_back_val ();
447
- for (SILBasicBlock *pred : state->block ->getPredecessorBlocks ()) {
448
- BlockState *predState = block2State[pred];
449
- if (predState->exitReachability < state->exitReachability ) {
431
+ SILBasicBlock *block = workList.pop_back_val ();
432
+ BlockState &state = blockStates[block];
433
+ for (SILBasicBlock *pred : block->getPredecessorBlocks ()) {
434
+ BlockState &predState = blockStates[pred];
435
+ if (predState.exitReachability < state.exitReachability ) {
450
436
// As there are 3 states, each block can be put into the workList 2
451
437
// times maximum.
452
- predState-> exitReachability = state-> exitReachability ;
453
- workList.push_back (predState );
438
+ predState. exitReachability = state. exitReachability ;
439
+ workList.push_back (pred );
454
440
}
455
441
}
456
442
}
@@ -462,18 +448,18 @@ void MemoryDataflow::solveForward(JoinOperation join) {
462
448
bool firstRound = true ;
463
449
do {
464
450
changed = false ;
465
- for (BlockState &st : blockStates) {
466
- Bits bits = st .entrySet ;
451
+ for (auto bd : blockStates) {
452
+ Bits bits = bd. data .entrySet ;
467
453
assert (!bits.empty ());
468
- for (SILBasicBlock *pred : st .block -> getPredecessorBlocks ()) {
469
- join (bits, block2State [pred]-> exitSet );
454
+ for (SILBasicBlock *pred : bd .block . getPredecessorBlocks ()) {
455
+ join (bits, blockStates [pred]. exitSet );
470
456
}
471
- if (firstRound || bits != st .entrySet ) {
457
+ if (firstRound || bits != bd. data .entrySet ) {
472
458
changed = true ;
473
- st .entrySet = bits;
474
- bits |= st .genSet ;
475
- bits.reset (st .killSet );
476
- st .exitSet = bits;
459
+ bd. data .entrySet = bits;
460
+ bits |= bd. data .genSet ;
461
+ bits.reset (bd. data .killSet );
462
+ bd. data .exitSet = bits;
477
463
}
478
464
}
479
465
firstRound = false ;
@@ -498,18 +484,18 @@ void MemoryDataflow::solveBackward(JoinOperation join) {
498
484
bool firstRound = true ;
499
485
do {
500
486
changed = false ;
501
- for (BlockState &st : llvm::reverse (blockStates)) {
502
- Bits bits = st .exitSet ;
487
+ for (auto bd : llvm::reverse (blockStates)) {
488
+ Bits bits = bd. data .exitSet ;
503
489
assert (!bits.empty ());
504
- for (SILBasicBlock *succ : st .block -> getSuccessorBlocks ()) {
505
- join (bits, block2State [succ]-> entrySet );
490
+ for (SILBasicBlock *succ : bd .block . getSuccessorBlocks ()) {
491
+ join (bits, blockStates [succ]. entrySet );
506
492
}
507
- if (firstRound || bits != st .exitSet ) {
493
+ if (firstRound || bits != bd. data .exitSet ) {
508
494
changed = true ;
509
- st .exitSet = bits;
510
- bits |= st .genSet ;
511
- bits.reset (st .killSet );
512
- st .entrySet = bits;
495
+ bd. data .exitSet = bits;
496
+ bits |= bd. data .genSet ;
497
+ bits.reset (bd. data .killSet );
498
+ bd. data .entrySet = bits;
513
499
}
514
500
}
515
501
firstRound = false ;
@@ -529,12 +515,12 @@ void MemoryDataflow::solveBackwardWithUnion() {
529
515
}
530
516
531
517
void MemoryDataflow::dump () const {
532
- for (const BlockState &st : blockStates) {
533
- llvm::dbgs () << " bb" << st .block -> getDebugID () << " :\n "
534
- << " entry: " << st .entrySet << ' \n '
535
- << " gen: " << st .genSet << ' \n '
536
- << " kill: " << st .killSet << ' \n '
537
- << " exit: " << st .exitSet << ' \n ' ;
518
+ for (auto bd : blockStates) {
519
+ llvm::dbgs () << " bb" << bd .block . getDebugID () << " :\n "
520
+ << " entry: " << bd. data .entrySet << ' \n '
521
+ << " gen: " << bd. data .genSet << ' \n '
522
+ << " kill: " << bd. data .killSet << ' \n '
523
+ << " exit: " << bd. data .exitSet << ' \n ' ;
538
524
}
539
525
}
540
526
@@ -585,7 +571,7 @@ class MemoryLifetimeVerifier {
585
571
void initDataflow (MemoryDataflow &dataFlow);
586
572
587
573
// / Initializes the data flow bits sets in the block state for a single block.
588
- void initDataflowInBlock (BlockState &state);
574
+ void initDataflowInBlock (SILBasicBlock *block, BlockState &state);
589
575
590
576
// / Helper function to set bits for function arguments and returns.
591
577
void setFuncOperandBits (BlockState &state, Operand &op,
@@ -658,36 +644,37 @@ void MemoryLifetimeVerifier::requireBitsSet(const Bits &bits, SILValue addr,
658
644
void MemoryLifetimeVerifier::initDataflow (MemoryDataflow &dataFlow) {
659
645
// Initialize the entry and exit sets to all-bits-set. Except for the function
660
646
// entry.
661
- for (BlockState &st : dataFlow) {
662
- if (st .block == function->getEntryBlock ()) {
663
- st .entrySet .reset ();
647
+ for (auto bs : dataFlow) {
648
+ if (&bs .block == function->getEntryBlock ()) {
649
+ bs. data .entrySet .reset ();
664
650
for (SILArgument *arg : function->getArguments ()) {
665
651
SILFunctionArgument *funcArg = cast<SILFunctionArgument>(arg);
666
652
if (funcArg->getArgumentConvention () !=
667
653
SILArgumentConvention::Indirect_Out) {
668
- locations.setBits (st .entrySet , arg);
654
+ locations.setBits (bs. data .entrySet , arg);
669
655
}
670
656
}
671
657
} else {
672
- st .entrySet .set ();
658
+ bs. data .entrySet .set ();
673
659
}
674
- st .exitSet .set ();
660
+ bs. data .exitSet .set ();
675
661
676
662
// Anything weired can happen in unreachable blocks. So just ignore them.
677
663
// Note: while solving the dataflow, unreachable blocks are implicitly
678
664
// ignored, because their entry/exit sets are all-ones and their gen/kill
679
665
// sets are all-zeroes.
680
- if (st .reachableFromEntry )
681
- initDataflowInBlock (st );
666
+ if (bs. data .reachableFromEntry )
667
+ initDataflowInBlock (&bs. block , bs. data );
682
668
}
683
669
}
684
670
685
- void MemoryLifetimeVerifier::initDataflowInBlock (BlockState &state) {
671
+ void MemoryLifetimeVerifier::initDataflowInBlock (SILBasicBlock *block,
672
+ BlockState &state) {
686
673
// Initialize the genSet with special cases, like the @out results of an
687
674
// try_apply in the predecessor block.
688
- setBitsOfPredecessor (state.genSet , state. block );
675
+ setBitsOfPredecessor (state.genSet , block);
689
676
690
- for (SILInstruction &I : *state. block ) {
677
+ for (SILInstruction &I : *block) {
691
678
switch (I.getKind ()) {
692
679
case SILInstructionKind::LoadInst: {
693
680
auto *LI = cast<LoadInst>(&I);
@@ -809,38 +796,38 @@ void MemoryLifetimeVerifier::checkFunction(MemoryDataflow &dataFlow) {
809
796
810
797
const Bits &nonTrivialLocations = locations.getNonTrivialLocations ();
811
798
Bits bits (locations.getNumLocations ());
812
- for (BlockState &st : dataFlow) {
813
- if (!st. reachableFromEntry || !st .exitReachable ())
799
+ for (auto bs : dataFlow) {
800
+ if (!bs. data . reachableFromEntry || !bs. data .exitReachable ())
814
801
continue ;
815
802
816
803
// Check all instructions in the block.
817
- bits = st .entrySet ;
818
- checkBlock (st .block , bits);
804
+ bits = bs. data .entrySet ;
805
+ checkBlock (&bs .block , bits);
819
806
820
807
// Check if there is a mismatch in location lifetime at the merge point.
821
- for (SILBasicBlock *pred : st .block -> getPredecessorBlocks ()) {
822
- BlockState * predState = dataFlow. getState ( pred) ;
823
- if (predState-> reachableFromEntry ) {
824
- require ((st. entrySet ^ predState-> exitSet ) & nonTrivialLocations,
825
- " lifetime mismatch in predecessors" , &*st .block -> begin ());
808
+ for (SILBasicBlock *pred : bs .block . getPredecessorBlocks ()) {
809
+ BlockState & predState = dataFlow[ pred] ;
810
+ if (predState. reachableFromEntry ) {
811
+ require ((bs. data . entrySet ^ predState. exitSet ) & nonTrivialLocations,
812
+ " lifetime mismatch in predecessors" , &*bs .block . begin ());
826
813
}
827
814
}
828
815
829
816
// Check the bits at function exit.
830
- TermInst *term = st .block -> getTerminator ();
831
- assert (bits == st .exitSet || isa<TryApplyInst>(term));
817
+ TermInst *term = bs .block . getTerminator ();
818
+ assert (bits == bs. data .exitSet || isa<TryApplyInst>(term));
832
819
switch (term->getKind ()) {
833
820
case SILInstructionKind::ReturnInst:
834
821
case SILInstructionKind::UnwindInst:
835
- require (expectedReturnBits & ~st .exitSet ,
822
+ require (expectedReturnBits & ~bs. data .exitSet ,
836
823
" indirect argument is not alive at function return" , term);
837
- require (st .exitSet & ~expectedReturnBits & nonTrivialLocations,
824
+ require (bs. data .exitSet & ~expectedReturnBits & nonTrivialLocations,
838
825
" memory is initialized at function return but shouldn't" , term);
839
826
break ;
840
827
case SILInstructionKind::ThrowInst:
841
- require (expectedThrowBits & ~st .exitSet ,
828
+ require (expectedThrowBits & ~bs. data .exitSet ,
842
829
" indirect argument is not alive at throw" , term);
843
- require (st .exitSet & ~expectedThrowBits & nonTrivialLocations,
830
+ require (bs. data .exitSet & ~expectedThrowBits & nonTrivialLocations,
844
831
" memory is initialized at throw but shouldn't" , term);
845
832
break ;
846
833
default :
0 commit comments