Skip to content

Commit f8034ac

Browse files
committed
PredictableMemOpt: be more conservative about address_to_pointer
Handling address_to_pointer as a plain inout missed some mutations and lead to miscompiles. We now treat address_to_pointer as escaping address. Fixes SR-3554
1 parent b465eb4 commit f8034ac

File tree

5 files changed

+53
-8
lines changed

5 files changed

+53
-8
lines changed

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,15 @@ namespace {
408408
/// top level of a 'self' variable in a non-delegating init method.
409409
bool IsSelfOfNonDelegatingInitializer;
410410

411+
/// How should address_to_pointer be handled?
412+
///
413+
/// In DefinitInitialization it is considered as an inout parameter to get
414+
/// diagnostics about passing a let variable to an inout mutable-pointer
415+
/// argument.
416+
/// In PredictableMemOpt it is considered as an escape point to be
417+
/// conservative.
418+
bool TreatAddressToPointerAsInout;
419+
411420
/// When walking the use list, if we index into a struct element, keep track
412421
/// of this, so that any indexes into tuple subelements don't affect the
413422
/// element we attribute an access to.
@@ -421,11 +430,13 @@ namespace {
421430
SmallVectorImpl<DIMemoryUse> &Uses,
422431
SmallVectorImpl<TermInst*> &FailableInits,
423432
SmallVectorImpl<SILInstruction*> &Releases,
424-
bool isDefiniteInitFinished)
433+
bool isDefiniteInitFinished,
434+
bool TreatAddressToPointerAsInout)
425435
: Module(TheMemory.MemoryInst->getModule()),
426436
TheMemory(TheMemory), Uses(Uses),
427437
FailableInits(FailableInits), Releases(Releases),
428-
isDefiniteInitFinished(isDefiniteInitFinished) {
438+
isDefiniteInitFinished(isDefiniteInitFinished),
439+
TreatAddressToPointerAsInout(TreatAddressToPointerAsInout) {
429440
}
430441

431442
/// This is the main entry point for the use walker. It collects uses from
@@ -765,7 +776,7 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
765776
llvm_unreachable("bad parameter convention");
766777
}
767778

768-
if (isa<AddressToPointerInst>(User)) {
779+
if (isa<AddressToPointerInst>(User) && TreatAddressToPointerAsInout) {
769780
// address_to_pointer is a mutable escape, which we model as an inout use.
770781
addElementUses(BaseEltNo, PointeeType, User, DIUseKind::InOutUse);
771782
continue;
@@ -1496,7 +1507,9 @@ void swift::collectDIElementUsesFrom(const DIMemoryObjectInfo &MemoryInfo,
14961507
SmallVectorImpl<DIMemoryUse> &Uses,
14971508
SmallVectorImpl<TermInst*> &FailableInits,
14981509
SmallVectorImpl<SILInstruction*> &Releases,
1499-
bool isDIFinished) {
1500-
ElementUseCollector(MemoryInfo, Uses, FailableInits, Releases, isDIFinished)
1510+
bool isDIFinished,
1511+
bool TreatAddressToPointerAsInout) {
1512+
ElementUseCollector(MemoryInfo, Uses, FailableInits, Releases, isDIFinished,
1513+
TreatAddressToPointerAsInout)
15011514
.collectFrom();
15021515
}

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,8 @@ void collectDIElementUsesFrom(const DIMemoryObjectInfo &MemoryInfo,
288288
SmallVectorImpl<DIMemoryUse> &Uses,
289289
SmallVectorImpl<TermInst*> &FailableInits,
290290
SmallVectorImpl<SILInstruction*> &Releases,
291-
bool isDefiniteInitFinished);
291+
bool isDefiniteInitFinished,
292+
bool TreatAddressToPointerAsInout);
292293

293294
} // end namespace swift
294295

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2615,7 +2615,8 @@ static bool processMemoryObject(SILInstruction *I) {
26152615
SmallVector<SILInstruction*, 4> Releases;
26162616

26172617
// Walk the use list of the pointer, collecting them into the Uses array.
2618-
collectDIElementUsesFrom(MemInfo, Uses, FailableInits, Releases, false);
2618+
collectDIElementUsesFrom(MemInfo, Uses, FailableInits, Releases, false,
2619+
/*TreatAddressToPointerAsInout*/ true);
26192620

26202621
LifetimeChecker(MemInfo, Uses, FailableInits, Releases).doIt();
26212622
return true;

lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,8 @@ static bool optimizeMemoryAllocations(SILFunction &Fn) {
982982
SmallVector<SILInstruction*, 4> Releases;
983983

984984
// Walk the use list of the pointer, collecting them.
985-
collectDIElementUsesFrom(MemInfo, Uses, FailableInits, Releases, true);
985+
collectDIElementUsesFrom(MemInfo, Uses, FailableInits, Releases, true,
986+
/*TreatAddressToPointerAsInout*/ false);
986987

987988
Changed |= AllocOptimize(Inst, Uses, Releases).doIt();
988989

test/SILOptimizer/predictable_memopt.sil

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,3 +387,32 @@ entry(%x : $Int):
387387
return %e : $IndirectCase
388388
}
389389

390+
sil @write_to_bool : $@convention(c) (UnsafeMutablePointer<Bool>) -> Int32
391+
392+
// CHECK-LABEL: sil @escaping_address
393+
sil @escaping_address : $@convention(thin) () -> Bool {
394+
bb0:
395+
// CHECK: [[A:%[0-9]+]] = alloc_stack
396+
%a = alloc_stack $Bool
397+
%f = function_ref @write_to_bool : $@convention(c) (UnsafeMutablePointer<Bool>) -> Int32
398+
%a2p = address_to_pointer %a : $*Bool to $Builtin.RawPointer
399+
%ump = struct $UnsafeMutablePointer<Bool> (%a2p : $Builtin.RawPointer)
400+
401+
%0 = integer_literal $Builtin.Int1, 0
402+
%b0 = struct $Bool (%0 : $Builtin.Int1)
403+
// CHECK: [[BV:%[0-9]+]] = struct_element_addr [[A]]
404+
%bv = struct_element_addr %a : $*Bool, #Bool._value
405+
store %b0 to %a : $*Bool
406+
407+
// CHECK: apply
408+
%ap = apply %f(%ump) : $@convention(c) (UnsafeMutablePointer<Bool>) -> Int32
409+
410+
// CHECK: [[L:%[0-9]+]] = load [[BV]]
411+
%l = load %bv : $*Builtin.Int1
412+
// CHECK: [[R:%[0-9]+]] = struct $Bool ([[L]]
413+
%r = struct $Bool (%l : $Builtin.Int1)
414+
dealloc_stack %a : $*Bool
415+
// CHECK: return [[R]]
416+
return %r : $Bool
417+
}
418+

0 commit comments

Comments
 (0)