Skip to content

Commit a50b940

Browse files
authored
Merge pull request #28865 from gottesmm/pr-0437ed0a25aba3ef32d53473cb1ab2c68287ca77
2 parents 9209e4f + 3e47e23 commit a50b940

File tree

1 file changed

+23
-36
lines changed

1 file changed

+23
-36
lines changed

lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ STATISTIC(NumEliminatedInsts, "number of removed instructions");
3636
STATISTIC(NumLoadCopyConvertedToLoadBorrow,
3737
"number of load_copy converted to load_borrow");
3838

39-
//===----------------------------------------------------------------------===//
40-
// Utility
41-
//===----------------------------------------------------------------------===//
42-
4339
//===----------------------------------------------------------------------===//
4440
// Live Range Modeling
4541
//===----------------------------------------------------------------------===//
@@ -653,12 +649,14 @@ bool SemanticARCOptVisitor::eliminateDeadLiveRangeCopyValue(CopyValueInst *cvi)
653649
bool SemanticARCOptVisitor::visitCopyValueInst(CopyValueInst *cvi) {
654650
// If our copy value inst has only destroy_value users, it is a dead live
655651
// range. Try to eliminate them.
656-
if (eliminateDeadLiveRangeCopyValue(cvi))
652+
if (eliminateDeadLiveRangeCopyValue(cvi)) {
657653
return true;
654+
}
658655

659656
// Then try to perform the guaranteed copy value optimization.
660-
if (performGuaranteedCopyValueOptimization(cvi))
657+
if (performGuaranteedCopyValueOptimization(cvi)) {
661658
return true;
659+
}
662660

663661
return false;
664662
}
@@ -667,35 +665,12 @@ bool SemanticARCOptVisitor::visitCopyValueInst(CopyValueInst *cvi) {
667665
// load [copy] Optimizations
668666
//===----------------------------------------------------------------------===//
669667

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.
697668
namespace {
698669

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.
699674
class StorageGuaranteesLoadVisitor
700675
: public AccessUseDefChainVisitor<StorageGuaranteesLoadVisitor>
701676
{
@@ -733,9 +708,21 @@ class StorageGuaranteesLoadVisitor
733708
}
734709

735710
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);
739726
}
740727

741728
void visitGlobalAccess(SILValue global) {

0 commit comments

Comments
 (0)