Skip to content

Commit 1259125

Browse files
Merge pull request #66945 from nate-chandler/rdar111356251
[MoveOnlyAddressChecker] Fix representation for reinit'd fields.
2 parents 91a4624 + 4a5009a commit 1259125

File tree

4 files changed

+103
-14
lines changed

4 files changed

+103
-14
lines changed

include/swift/SIL/FieldSensitivePrunedLiveness.h

+9
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,10 @@ struct TypeTreeLeafTypeRange {
321321
SmallVectorImpl<std::pair<SILValue, TypeTreeLeafTypeRange>>
322322
&resultingProjections);
323323

324+
static void visitContiguousRanges(
325+
SmallBitVector const &bits,
326+
llvm::function_ref<void(TypeTreeLeafTypeRange)> callback);
327+
324328
bool operator==(const TypeTreeLeafTypeRange &other) const {
325329
return startEltOffset == other.startEltOffset &&
326330
endEltOffset == other.endEltOffset;
@@ -1217,6 +1221,11 @@ class FieldSensitiveMultiDefPrunedLiveRange
12171221
defBlocks.setFrozen();
12181222
}
12191223

1224+
void initializeDef(SILInstruction *def, SmallBitVector const &bits) {
1225+
TypeTreeLeafTypeRange::visitContiguousRanges(
1226+
bits, [&](auto range) { initializeDef(def, range); });
1227+
}
1228+
12201229
void initializeDef(SILValue def, TypeTreeLeafTypeRange span) {
12211230
assert(Super::isInitialized());
12221231
defs.insert(def, span);

lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,29 @@ void TypeTreeLeafTypeRange::constructProjectionsForNeededElements(
474474
}
475475
}
476476

477+
void TypeTreeLeafTypeRange::visitContiguousRanges(
478+
SmallBitVector const &bits,
479+
llvm::function_ref<void(TypeTreeLeafTypeRange)> callback) {
480+
if (bits.size() == 0)
481+
return;
482+
483+
llvm::Optional<unsigned> current = llvm::None;
484+
for (unsigned bit = 0, size = bits.size(); bit < size; ++bit) {
485+
auto isSet = bits.test(bit);
486+
if (current) {
487+
if (!isSet) {
488+
callback(TypeTreeLeafTypeRange(*current, bit));
489+
current = llvm::None;
490+
}
491+
} else if (isSet) {
492+
current = bit;
493+
}
494+
}
495+
if (current) {
496+
callback(TypeTreeLeafTypeRange(*current, bits.size()));
497+
}
498+
}
499+
477500
//===----------------------------------------------------------------------===//
478501
// MARK: FieldSensitivePrunedLiveBlocks
479502
//===----------------------------------------------------------------------===//

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

+28-13
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ struct UseState {
626626

627627
/// memInstMustReinitialize insts. Contains both insts like copy_addr/store
628628
/// [assign] that are reinits that we will convert to inits and true reinits.
629-
llvm::SmallMapVector<SILInstruction *, TypeTreeLeafTypeRange, 4> reinitInsts;
629+
llvm::SmallMapVector<SILInstruction *, SmallBitVector, 4> reinitInsts;
630630

631631
/// The set of drop_deinits of this mark_must_check
632632
SmallSetVector<SILInstruction *, 2> dropDeinitInsts;
@@ -668,9 +668,17 @@ struct UseState {
668668

669669
void recordLivenessUse(SILInstruction *inst, TypeTreeLeafTypeRange range) {
670670
auto &bits = getOrCreateLivenessUse(inst);
671-
for (auto element : range.getRange()) {
672-
bits.set(element);
671+
range.setBits(bits);
672+
}
673+
674+
void recordReinitUse(SILInstruction *inst, TypeTreeLeafTypeRange range) {
675+
auto iter = reinitInsts.find(inst);
676+
if (iter == reinitInsts.end()) {
677+
iter =
678+
reinitInsts.insert({inst, SmallBitVector(getNumSubelements())}).first;
673679
}
680+
auto &bits = iter->second;
681+
range.setBits(bits);
674682
}
675683

676684
/// Returns true if this is a terminator instruction that although it doesn't
@@ -765,14 +773,24 @@ struct UseState {
765773
}
766774
}
767775

768-
void recordConsumingBlock(SILBasicBlock *block, TypeTreeLeafTypeRange range) {
776+
SmallBitVector &getOrCreateConsumingBlock(SILBasicBlock *block) {
769777
auto iter = consumingBlocks.find(block);
770778
if (iter == consumingBlocks.end()) {
771779
iter =
772780
consumingBlocks.insert({block, SmallBitVector(getNumSubelements())})
773781
.first;
774782
}
775-
range.setBits(iter->second);
783+
return iter->second;
784+
}
785+
786+
void recordConsumingBlock(SILBasicBlock *block, TypeTreeLeafTypeRange range) {
787+
auto &consumingBits = getOrCreateConsumingBlock(block);
788+
range.setBits(consumingBits);
789+
}
790+
791+
void recordConsumingBlock(SILBasicBlock *block, SmallBitVector &bits) {
792+
auto &consumingBits = getOrCreateConsumingBlock(block);
793+
consumingBits |= bits;
776794
}
777795

778796
void
@@ -839,7 +857,7 @@ struct UseState {
839857
if (!isReinitToInitConvertibleInst(inst)) {
840858
auto iter = reinitInsts.find(inst);
841859
if (iter != reinitInsts.end()) {
842-
if (span.setIntersection(iter->second))
860+
if (span.intersects(iter->second))
843861
return true;
844862
}
845863
}
@@ -864,7 +882,7 @@ struct UseState {
864882
if (isReinitToInitConvertibleInst(inst)) {
865883
auto iter = reinitInsts.find(inst);
866884
if (iter != reinitInsts.end()) {
867-
if (span.setIntersection(iter->second))
885+
if (span.intersects(iter->second))
868886
return true;
869887
}
870888
}
@@ -1741,11 +1759,10 @@ bool GatherUsesVisitor::visitUse(Operand *op) {
17411759

17421760
if (::memInstMustReinitialize(op)) {
17431761
LLVM_DEBUG(llvm::dbgs() << "Found reinit: " << *user);
1744-
assert(!useState.reinitInsts.count(user));
17451762
auto leafRange = TypeTreeLeafTypeRange::get(op->get(), getRootAddress());
17461763
if (!leafRange)
17471764
return false;
1748-
useState.reinitInsts.insert({user, *leafRange});
1765+
useState.recordReinitUse(user, *leafRange);
17491766
return true;
17501767
}
17511768

@@ -2730,9 +2747,7 @@ void MoveOnlyAddressCheckerPImpl::rewriteUses(
27302747
for (auto reinitPair : addressUseState.reinitInsts) {
27312748
if (!isReinitToInitConvertibleInst(reinitPair.first))
27322749
continue;
2733-
SmallBitVector bits(liveness.getNumSubElements());
2734-
reinitPair.second.setBits(bits);
2735-
if (!consumes.claimConsume(reinitPair.first, bits))
2750+
if (!consumes.claimConsume(reinitPair.first, reinitPair.second))
27362751
convertMemoryReinitToInitForm(reinitPair.first, debugVar);
27372752
}
27382753

@@ -2923,7 +2938,7 @@ void ExtendUnconsumedLiveness::run() {
29232938
}
29242939
}
29252940
for (auto pair : addressUseState.reinitInsts) {
2926-
if (pair.second.contains(element)) {
2941+
if (pair.second.test(element)) {
29272942
destroys[pair.first] = DestroyKind::Reinit;
29282943
}
29292944
}

test/SILOptimizer/moveonly_addresschecker_unmaximized.sil

+43-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct M4 {
1616
sil @get_M4 : $@convention(thin) () -> @owned M4
1717
sil @end_2 : $@convention(thin) (@owned M, @owned M) -> ()
1818
sil @see_addr_2 : $@convention(thin) (@in_guaranteed M, @in_guaranteed M) -> ()
19-
19+
sil @replace_2 : $@convention(thin) (@inout M, @inout M) -> ()
2020

2121
/// Two non-contiguous fields (#M4.s2, #M4.s4) are borrowed by @see_addr_2.
2222
/// Two non-contiguous fields (#M4.s1, #M$.s3) are consumed by @end_2.
@@ -65,3 +65,45 @@ bb0:
6565
return %22 : $()
6666
}
6767

68+
// CHECK-LABEL: sil [ossa] @rdar111356251 : $@convention(thin) () -> () {
69+
// CHECK: [[STACK:%[^,]+]] = alloc_stack $M4
70+
// CHECK: [[GET_M4:%[^,]+]] = function_ref @get_M4 : $@convention(thin) () -> @owned M4
71+
// CHECK: [[INSTANCE:%[^,]+]] = apply [[GET_M4]]() : $@convention(thin) () -> @owned M4
72+
// CHECK: store [[INSTANCE]] to [init] [[STACK]] : $*M4
73+
// CHECK: [[S2_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s2
74+
// CHECK: [[S4_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s4
75+
// CHECK: [[REPLACE_2:%[^,]+]] = function_ref @replace_2 : $@convention(thin) (@inout M, @inout M) -> ()
76+
// CHECK: apply [[REPLACE_2]]([[S2_ADDR]], [[S4_ADDR]]) : $@convention(thin) (@inout M, @inout M) -> ()
77+
// CHECK: [[S4_ADDR_2:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s4
78+
// CHECK: destroy_addr [[S4_ADDR_2]] : $*M
79+
// CHECK: [[S2_ADDR_2:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s2
80+
// CHECK: destroy_addr [[S2_ADDR_2]] : $*M
81+
// CHECK: [[S1_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s1
82+
// CHECK: [[S1:%[^,]+]] = load [take] [[S1_ADDR]] : $*M
83+
// CHECK: [[S3_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s3
84+
// CHECK: [[S3:%[^,]+]] = load [take] [[S3_ADDR]] : $*M
85+
// CHECK: [[END_2:%[^,]+]] = function_ref @end_2 : $@convention(thin) (@owned M, @owned M) -> ()
86+
// CHECK: apply [[END_2]]([[S1]], [[S3]]) : $@convention(thin) (@owned M, @owned M) -> ()
87+
// CHECK-LABEL: } // end sil function 'rdar111356251'
88+
sil [ossa] @rdar111356251 : $@convention(thin) () -> () {
89+
bb0:
90+
%stack_addr = alloc_stack $M4
91+
%stack = mark_must_check [consumable_and_assignable] %stack_addr : $*M4
92+
%get_M4 = function_ref @get_M4 : $@convention(thin) () -> @owned M4
93+
%instance = apply %get_M4() : $@convention(thin) () -> @owned M4
94+
store %instance to [init] %stack : $*M4
95+
%s2_addr = struct_element_addr %stack : $*M4, #M4.s2
96+
%s4_addr = struct_element_addr %stack : $*M4, #M4.s4
97+
%replace_2 = function_ref @replace_2 : $@convention(thin) (@inout M, @inout M) -> ()
98+
apply %replace_2(%s2_addr, %s4_addr) : $@convention(thin) (@inout M, @inout M) -> ()
99+
%12 = struct_element_addr %stack : $*M4, #M4.s1
100+
%13 = load [copy] %12 : $*M
101+
%14 = struct_element_addr %stack : $*M4, #M4.s3
102+
%15 = load [copy] %14 : $*M
103+
%16 = function_ref @end_2 : $@convention(thin) (@owned M, @owned M) -> ()
104+
%17 = apply %16(%13, %15) : $@convention(thin) (@owned M, @owned M) -> ()
105+
destroy_addr %stack : $*M4
106+
dealloc_stack %stack_addr : $*M4
107+
%22 = tuple ()
108+
return %22 : $()
109+
}

0 commit comments

Comments
 (0)