@@ -36,10 +36,6 @@ STATISTIC(NumEliminatedInsts, "number of removed instructions");
36
36
STATISTIC (NumLoadCopyConvertedToLoadBorrow,
37
37
" number of load_copy converted to load_borrow" );
38
38
39
- // ===----------------------------------------------------------------------===//
40
- // Utility
41
- // ===----------------------------------------------------------------------===//
42
-
43
39
// ===----------------------------------------------------------------------===//
44
40
// Live Range Modeling
45
41
// ===----------------------------------------------------------------------===//
@@ -653,12 +649,14 @@ bool SemanticARCOptVisitor::eliminateDeadLiveRangeCopyValue(CopyValueInst *cvi)
653
649
bool SemanticARCOptVisitor::visitCopyValueInst (CopyValueInst *cvi) {
654
650
// If our copy value inst has only destroy_value users, it is a dead live
655
651
// range. Try to eliminate them.
656
- if (eliminateDeadLiveRangeCopyValue (cvi))
652
+ if (eliminateDeadLiveRangeCopyValue (cvi)) {
657
653
return true ;
654
+ }
658
655
659
656
// Then try to perform the guaranteed copy value optimization.
660
- if (performGuaranteedCopyValueOptimization (cvi))
657
+ if (performGuaranteedCopyValueOptimization (cvi)) {
661
658
return true ;
659
+ }
662
660
663
661
return false ;
664
662
}
@@ -667,35 +665,12 @@ bool SemanticARCOptVisitor::visitCopyValueInst(CopyValueInst *cvi) {
667
665
// load [copy] Optimizations
668
666
// ===----------------------------------------------------------------------===//
669
667
670
- // A flow insensitive analysis that tells the load [copy] analysis if the
671
- // storage has 0, 1, >1 writes to it.
672
- //
673
- // In the case of 0 writes, we return CanOptimizeLoadCopyResult::Always.
674
- //
675
- // In the case of 1 write, we return OnlyIfStorageIsLocal. We are taking
676
- // advantage of definite initialization implying that an alloc_stack must be
677
- // written to once before any loads from the memory location. Thus if we are
678
- // local and see 1 write, we can still change to load_borrow if all other uses
679
- // check out.
680
- //
681
- // If there is 2+ writes, we can not optimize = (.
682
-
683
- bool mayFunctionMutateArgument (const AccessedStorage &storage, SILFunction &f) {
684
- auto *arg = cast<SILFunctionArgument>(storage.getArgument ());
685
-
686
- // Then check if we have an in_guaranteed argument. In this case, we can
687
- // always optimize load [copy] from this.
688
- if (arg->hasConvention (SILArgumentConvention::Indirect_In_Guaranteed))
689
- return false ;
690
-
691
- // For now just return false.
692
- return true ;
693
- }
694
-
695
- // Then find our accessed storage to determine whether it provides a guarantee
696
- // for the loaded value.
697
668
namespace {
698
669
670
+ // / A class that computes in a flow insensitive way if we can prove that our
671
+ // / storage is either never written to, or is initialized exactly once and never
672
+ // / written to again. In both cases, we can convert load [copy] -> load_borrow
673
+ // / safely.
699
674
class StorageGuaranteesLoadVisitor
700
675
: public AccessUseDefChainVisitor<StorageGuaranteesLoadVisitor>
701
676
{
@@ -733,9 +708,21 @@ class StorageGuaranteesLoadVisitor
733
708
}
734
709
735
710
void visitArgumentAccess (SILFunctionArgument *arg) {
736
- return answer (mayFunctionMutateArgument (
737
- AccessedStorage (arg, AccessedStorage::Argument),
738
- ARCOpt.F ));
711
+ // If this load_copy is from an indirect in_guaranteed argument, then we
712
+ // know for sure that it will never be written to.
713
+ if (arg->hasConvention (SILArgumentConvention::Indirect_In_Guaranteed)) {
714
+ return answer (false );
715
+ }
716
+
717
+ // TODO: This should be extended:
718
+ //
719
+ // 1. We should be able to analyze inout arguments and see if the inout
720
+ // argument is never actually written to in a flow insensitive way.
721
+ //
722
+ // 2. We should be able to analyze in arguments and see if they are only
723
+ // ever destroyed at the end of the function. In such a case, we may be
724
+ // able to also to promote load [copy] from such args to load_borrow.
725
+ return answer (true );
739
726
}
740
727
741
728
void visitGlobalAccess (SILValue global) {
0 commit comments