Skip to content

Commit 122a084

Browse files
authored
Merge pull request swiftlang#30731 from eeckstein/fix-destroy-hoisting
DestroyHoisting: correctly detect if debug_value_addr instructions need to be deleted.
2 parents c30b6fd + 6d533e8 commit 122a084

File tree

2 files changed

+50
-5
lines changed

2 files changed

+50
-5
lines changed

lib/SILOptimizer/Transforms/DestroyHoisting.cpp

+19-5
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ class DestroyHoisting {
101101

102102
void moveDestroys(MemoryDataflow &dataFlow);
103103

104+
bool locationOverlaps(const MemoryLocations::Location *loc,
105+
const Bits &destroys);
106+
104107
void moveDestroysInBlock(SILBasicBlock *block, Bits &activeDestroys,
105108
SmallVectorImpl<SILInstruction *> &toRemove);
106109

@@ -415,6 +418,19 @@ void DestroyHoisting::moveDestroys(MemoryDataflow &dataFlow) {
415418
}
416419
}
417420

421+
bool DestroyHoisting::locationOverlaps(const MemoryLocations::Location *loc,
422+
const Bits &destroys) {
423+
// We cannot just check if 'loc->subLocations' has any common bits with
424+
// 'destroys', because subLocations don't include the "self" bit if all sub
425+
// locations cover the whole location.
426+
for (int subIdx = loc->subLocations.find_first(); subIdx >= 0;
427+
subIdx = loc->subLocations.find_next(subIdx)) {
428+
if (destroys.anyCommon(locations.getLocation(subIdx)->selfAndParents))
429+
return true;
430+
}
431+
return false;
432+
}
433+
418434
void DestroyHoisting::moveDestroysInBlock(
419435
SILBasicBlock *block, Bits &activeDestroys,
420436
SmallVectorImpl<SILInstruction *> &toRemove) {
@@ -435,11 +451,9 @@ void DestroyHoisting::moveDestroysInBlock(
435451
// debug_value_addr does not count as real use of a location. If we are
436452
// moving a destroy_addr above a debug_value_addr, just delete that
437453
// debug_value_addr.
438-
if (auto *dvaLoc = locations.getLocation(DVA->getOperand())) {
439-
if (activeDestroys.anyCommon(dvaLoc->subLocations) ||
440-
activeDestroys.anyCommon(dvaLoc->selfAndParents))
441-
toRemove.push_back(DVA);
442-
}
454+
auto *dvaLoc = locations.getLocation(DVA->getOperand());
455+
if (dvaLoc && locationOverlaps(dvaLoc, activeDestroys))
456+
toRemove.push_back(DVA);
443457
} else if (I.mayHaveSideEffects()) {
444458
// Delete all destroy_addr and debug_value_addr which are scheduled for
445459
// removal.

test/SILOptimizer/destroy_hoisting.sil

+31
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ struct Mixed {
2828
var i: Int
2929
}
3030

31+
public struct S2 {
32+
let s: S
33+
}
34+
35+
36+
public enum E {
37+
case A
38+
case B
39+
}
40+
3141
sil @unknown : $@convention(thin) () -> ()
3242
sil @use_S : $@convention(thin) (@in_guaranteed S) -> ()
3343

@@ -277,3 +287,24 @@ bb3:
277287
return %r : $()
278288
}
279289

290+
// CHECK-LABEL: sil [ossa] @test_debug_value
291+
// CHECK: bb0({{.*}}):
292+
// CHECK-NEXT: struct_element_addr
293+
// CHECK-NEXT: destroy_addr
294+
// CHECK-NEXT: br bb1
295+
// CHECK: } // end sil function 'test_debug_value'
296+
sil [ossa] @test_debug_value : $@convention(method) (@inout S2, @owned X, @owned S, @inout E) -> () {
297+
bb0(%0 : $*S2, %1 : @owned $X, %2 : @owned $S, %3 : $*E):
298+
debug_value_addr %0 : $*S2, var, name "self", argno 1
299+
br bb1
300+
301+
bb1:
302+
%60 = struct_element_addr %0 : $*S2, #S2.s
303+
destroy_addr %60 : $*S
304+
store %2 to [init] %60 : $*S
305+
%71 = struct_element_addr %60 : $*S, #S.x
306+
store %1 to [assign] %71 : $*X
307+
308+
%75 = tuple ()
309+
return %75 : $()
310+
}

0 commit comments

Comments
 (0)