Skip to content

Commit 82ba69e

Browse files
committed
[MoveOnlyAddressChecker] Fix used fields repr.
The address checker records uses in its livenessUses map. Previously, that map mapped from an instruction to a range of fields of the type. But an instruction can use multiple discontiguous fields of a single value. Here, such instructions are properly recorded by fixing the map to store a bit vector for each instruction. rdar://110676577
1 parent 2bfa723 commit 82ba69e

File tree

5 files changed

+315
-170
lines changed

5 files changed

+315
-170
lines changed

include/swift/SIL/FieldSensitivePrunedLiveness.h

+77-7
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,16 @@ struct TypeTreeLeafTypeRange {
345345
return TypeTreeLeafTypeRange(start, end);
346346
}
347347

348+
/// Whether \p bits contains any of the in-range bits.
349+
bool intersects(SmallBitVector const &bits) const {
350+
for (auto element : getRange()) {
351+
if (bits.test(element)) {
352+
return true;
353+
}
354+
}
355+
return false;
356+
}
357+
348358
/// Is the given leaf type specified by \p singleLeafElementNumber apart of
349359
/// our \p range of leaf type values in the our larger type.
350360
bool contains(SubElementOffset singleLeafElementNumber) const {
@@ -696,6 +706,14 @@ class FieldSensitivePrunedLiveness {
696706
}
697707
}
698708

709+
/// Record that the instruction uses the bits in \p bits.
710+
void addUses(SmallBitVector const &bits, bool lifetimeEnding) {
711+
liveBits |= bits;
712+
if (lifetimeEnding) {
713+
consumingBits |= bits;
714+
}
715+
}
716+
699717
/// Populates the provided vector with contiguous ranges of bits which are
700718
/// users of the same sort.
701719
void getContiguousRanges(
@@ -838,6 +856,9 @@ class FieldSensitivePrunedLiveness {
838856
void updateForUse(SILInstruction *user, TypeTreeLeafTypeRange span,
839857
bool lifetimeEnding);
840858

859+
void updateForUse(SILInstruction *user, SmallBitVector const &bits,
860+
bool lifetimeEnding);
861+
841862
void getBlockLiveness(SILBasicBlock *bb, TypeTreeLeafTypeRange span,
842863
SmallVectorImpl<FieldSensitivePrunedLiveBlocks::IsLive>
843864
&resultingFoundLiveness) const {
@@ -862,6 +883,14 @@ class FieldSensitivePrunedLiveness {
862883
SmallBitVector &liveOutBits,
863884
SmallBitVector &deadBits) const;
864885

886+
InterestingUser &getOrCreateInterestingUser(SILInstruction *user) {
887+
auto iter = users.find(user);
888+
if (iter == users.end()) {
889+
iter = users.insert({user, InterestingUser(getNumSubElements())}).first;
890+
}
891+
return *&iter->second;
892+
}
893+
865894
/// If \p user has had uses recored, return a pointer to the InterestingUser
866895
/// where they've been recorded.
867896
InterestingUser const *getInterestingUser(SILInstruction *user) const {
@@ -885,11 +914,12 @@ class FieldSensitivePrunedLiveness {
885914
bool isInterestingUserOfKind(SILInstruction *user, IsInterestingUser kind,
886915
TypeTreeLeafTypeRange range) const {
887916
auto *record = getInterestingUser(user);
888-
if (!record)
917+
if (!record) {
889918
return kind == IsInterestingUser::NonUser;
919+
}
890920

891921
for (auto element : range.getRange()) {
892-
if (isInterestingUser(user, element) != kind)
922+
if (record->isInterestingUser(element) != kind)
893923
return false;
894924
}
895925
return true;
@@ -918,11 +948,12 @@ class FieldSensitivePrunedLiveness {
918948
/// argument must be copied.
919949
void addInterestingUser(SILInstruction *user, TypeTreeLeafTypeRange range,
920950
bool lifetimeEnding) {
921-
auto iter = users.find(user);
922-
if (iter == users.end()) {
923-
iter = users.insert({user, InterestingUser(getNumSubElements())}).first;
924-
}
925-
iter->second.addUses(range, lifetimeEnding);
951+
getOrCreateInterestingUser(user).addUses(range, lifetimeEnding);
952+
}
953+
954+
void addInterestingUser(SILInstruction *user, SmallBitVector const &bits,
955+
bool lifetimeEnding) {
956+
getOrCreateInterestingUser(user).addUses(bits, lifetimeEnding);
926957
}
927958
};
928959

@@ -1036,6 +1067,11 @@ class FieldSensitivePrunedLiveRange : public FieldSensitivePrunedLiveness {
10361067
void updateForUse(SILInstruction *user, TypeTreeLeafTypeRange span,
10371068
bool lifetimeEnding);
10381069

1070+
/// Customize updateForUse for FieldSensitivePrunedLiveness such that we check
1071+
/// that we consider defs as stopping liveness from being propagated up.
1072+
void updateForUse(SILInstruction *user, SmallBitVector const &bits,
1073+
bool lifetimeEnding);
1074+
10391075
/// Compute the boundary from the blocks discovered during liveness analysis.
10401076
///
10411077
/// Precondition: \p liveness.getDiscoveredBlocks() is a valid list of all
@@ -1107,6 +1143,16 @@ class FieldSensitiveSSAPrunedLiveRange
11071143
return inst == defInst.first && defInst.second->contains(bit);
11081144
}
11091145

1146+
bool isDef(SILInstruction *inst, SmallBitVector const &bits) const {
1147+
if (inst != defInst.first)
1148+
return false;
1149+
for (auto bit : bits.set_bits()) {
1150+
if (!defInst.second->contains(bit))
1151+
return false;
1152+
}
1153+
return true;
1154+
}
1155+
11101156
bool isDef(SILInstruction *inst, TypeTreeLeafTypeRange span) const {
11111157
return inst == defInst.first &&
11121158
defInst.second->setIntersection(span).has_value();
@@ -1217,6 +1263,30 @@ class FieldSensitiveMultiDefPrunedLiveRange
12171263
*iter, [&](TypeTreeLeafTypeRange span) { return span.contains(bit); });
12181264
}
12191265

1266+
bool isDef(SILValue value, SmallBitVector const &bits) const {
1267+
assert(isInitialized());
1268+
auto iter = defs.find(cast<SILNode>(value));
1269+
if (!iter)
1270+
return false;
1271+
SmallBitVector allBits(bits.size());
1272+
for (auto range : *iter) {
1273+
range.setBits(allBits);
1274+
}
1275+
return (bits & allBits) == bits;
1276+
}
1277+
1278+
bool isDef(SILInstruction *inst, SmallBitVector const &bits) const {
1279+
assert(isInitialized());
1280+
auto iter = defs.find(cast<SILNode>(inst));
1281+
if (!iter)
1282+
return false;
1283+
SmallBitVector allBits(bits.size());
1284+
for (auto range : *iter) {
1285+
range.setBits(allBits);
1286+
}
1287+
return (bits & allBits) == bits;
1288+
}
1289+
12201290
bool isDef(SILInstruction *inst, TypeTreeLeafTypeRange span) const {
12211291
assert(isInitialized());
12221292
auto iter = defs.find(cast<SILNode>(inst));

lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp

+46
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,16 @@ void FieldSensitivePrunedLiveness::updateForUse(SILInstruction *user,
609609
addInterestingUser(user, range, lifetimeEnding);
610610
}
611611

612+
void FieldSensitivePrunedLiveness::updateForUse(SILInstruction *user,
613+
SmallBitVector const &bits,
614+
bool lifetimeEnding) {
615+
for (auto bit : bits.set_bits()) {
616+
liveBlocks.updateForUse(user, bit);
617+
}
618+
619+
addInterestingUser(user, bits, lifetimeEnding);
620+
}
621+
612622
//===----------------------------------------------------------------------===//
613623
// MARK: FieldSensitivePrunedLiveRange
614624
//===----------------------------------------------------------------------===//
@@ -822,6 +832,42 @@ void FieldSensitivePrunedLiveRange<LivenessWithDefs>::updateForUse(
822832
FieldSensitivePrunedLiveness::updateForUse(user, range, lifetimeEnding);
823833
}
824834

835+
template <typename LivenessWithDefs>
836+
void FieldSensitivePrunedLiveRange<LivenessWithDefs>::updateForUse(
837+
SILInstruction *user, SmallBitVector const &bits, bool lifetimeEnding) {
838+
PRUNED_LIVENESS_LOG(
839+
llvm::dbgs()
840+
<< "Begin FieldSensitivePrunedLiveRange<LivenessWithDefs>::updateForUse "
841+
"for: "
842+
<< *user);
843+
PRUNED_LIVENESS_LOG(llvm::dbgs()
844+
<< "Looking for def instruction earlier in the block!\n");
845+
846+
auto *parentBlock = user->getParent();
847+
for (auto ii = std::next(user->getReverseIterator()),
848+
ie = parentBlock->rend();
849+
ii != ie; ++ii) {
850+
// If we find the def, just mark this instruction as being an interesting
851+
// instruction.
852+
if (asImpl().isDef(&*ii, bits)) {
853+
PRUNED_LIVENESS_LOG(llvm::dbgs() << " Found def: " << *ii);
854+
PRUNED_LIVENESS_LOG(
855+
llvm::dbgs()
856+
<< " Marking inst as interesting user and returning!\n");
857+
addInterestingUser(user, bits, lifetimeEnding);
858+
return;
859+
}
860+
}
861+
862+
// Otherwise, just delegate to our parent class's update for use. This will
863+
// update liveness for our predecessor blocks and add this instruction as an
864+
// interesting user.
865+
PRUNED_LIVENESS_LOG(llvm::dbgs()
866+
<< "No defs found! Delegating to "
867+
"FieldSensitivePrunedLiveness::updateForUse.\n");
868+
FieldSensitivePrunedLiveness::updateForUse(user, bits, lifetimeEnding);
869+
}
870+
825871
//===----------------------------------------------------------------------===//
826872
// MARK: Boundary Computation Utilities
827873
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)