Skip to content

Commit a8b01bf

Browse files
Merge pull request #72497 from nate-chandler/cherrypick/release/6.0/rdar125103951
6.0: [MoveOnlyAddressChecker] Fix representation for consumed fields.
2 parents 75cab42 + 96b1809 commit a8b01bf

File tree

5 files changed

+167
-144
lines changed

5 files changed

+167
-144
lines changed

include/swift/SIL/FieldSensitivePrunedLiveness.h

Lines changed: 29 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -308,60 +308,7 @@ struct TypeTreeLeafTypeRange {
308308
/// This is a subset of (usually equal to) the bits of op->getType() in \p
309309
/// rootValue.
310310
static std::optional<TypeTreeLeafTypeRange> get(Operand *op,
311-
SILValue rootValue) {
312-
auto projectedValue = op->get();
313-
auto startEltOffset = SubElementOffset::compute(projectedValue, rootValue);
314-
if (!startEltOffset)
315-
return std::nullopt;
316-
317-
// A drop_deinit only consumes the deinit bit of its operand.
318-
if (isa<DropDeinitInst>(op->getUser())) {
319-
auto upperBound = *startEltOffset + TypeSubElementCount(projectedValue);
320-
return {{upperBound - 1, upperBound}};
321-
}
322-
323-
// An `inject_enum_addr` only initializes the enum tag.
324-
if (auto inject = dyn_cast<InjectEnumAddrInst>(op->getUser())) {
325-
auto upperBound = *startEltOffset + TypeSubElementCount(projectedValue);
326-
unsigned payloadUpperBound = 0;
327-
if (inject->getElement()->hasAssociatedValues()) {
328-
auto payloadTy = projectedValue->getType()
329-
.getEnumElementType(inject->getElement(), op->getFunction());
330-
331-
payloadUpperBound = *startEltOffset
332-
+ TypeSubElementCount(payloadTy, op->getFunction());
333-
}
334-
// TODO: account for deinit component if enum has deinit.
335-
assert(!projectedValue->getType().isValueTypeWithDeinit());
336-
return {{payloadUpperBound, upperBound}};
337-
}
338-
339-
// Uses that borrow a value do not involve the deinit bit.
340-
//
341-
// FIXME: This shouldn't be limited to applies.
342-
unsigned deinitBitOffset = 0;
343-
if (op->get()->getType().isValueTypeWithDeinit() &&
344-
op->getOperandOwnership() == OperandOwnership::Borrow &&
345-
ApplySite::isa(op->getUser())) {
346-
deinitBitOffset = 1;
347-
}
348-
349-
return {{*startEltOffset, *startEltOffset +
350-
TypeSubElementCount(projectedValue) -
351-
deinitBitOffset}};
352-
}
353-
354-
/// Given a type \p rootType and a set of needed elements specified by the bit
355-
/// vector \p neededElements, place into \p foundContiguousTypeRanges a set of
356-
/// TypeTreeLeafTypeRanges that are associated with the bit vectors
357-
/// elements. As a constraint, we ensure that if \p neededElements has bits
358-
/// set that are part of subsequent fields of a type that is only partially
359-
/// needed, the two fields are represented as separate ranges. This ensures
360-
/// that it is easy to use this API to correspond to independent operations
361-
/// for the fields.
362-
static void convertNeededElementsToContiguousTypeRanges(
363-
SILFunction *fn, SILType rootType, SmallBitVector &neededElements,
364-
SmallVectorImpl<TypeTreeLeafTypeRange> &foundContiguousTypeRanges);
311+
SILValue rootValue);
365312

366313
static void constructProjectionsForNeededElements(
367314
SILValue rootValue, SILInstruction *insertPt,
@@ -533,10 +480,10 @@ class FieldSensitivePrunedLiveBlocks {
533480

534481
/// Returns the liveness in \p resultingFoundLiveness. We only return the
535482
/// bits for endBitNo - startBitNo.
536-
void getLiveness(unsigned startBitNo, unsigned endBitNo,
483+
void getLiveness(SmallBitVector const &bitsOfInterest,
537484
SmallVectorImpl<IsLive> &resultingFoundLiveness) const {
538-
for (unsigned i = startBitNo, e = endBitNo; i != e; ++i) {
539-
resultingFoundLiveness.push_back(getLiveness(i));
485+
for (auto bit : bitsOfInterest.set_bits()) {
486+
resultingFoundLiveness.push_back(getLiveness(bit));
540487
}
541488
}
542489

@@ -654,17 +601,26 @@ class FieldSensitivePrunedLiveBlocks {
654601
void getBlockLiveness(SILBasicBlock *bb, unsigned startBitNo,
655602
unsigned endBitNo,
656603
SmallVectorImpl<IsLive> &foundLivenessInfo) const {
604+
SmallBitVector bits(*numBitsToTrack);
605+
for (auto index = startBitNo; index < endBitNo; ++index) {
606+
bits.set(index);
607+
}
608+
getBlockLiveness(bb, bits, foundLivenessInfo);
609+
}
610+
611+
void getBlockLiveness(SILBasicBlock *bb, SmallBitVector const &bits,
612+
SmallVectorImpl<IsLive> &foundLivenessInfo) const {
657613
assert(isInitialized());
658614
auto liveBlockIter = liveBlocks.find(bb);
659615
if (liveBlockIter == liveBlocks.end()) {
660-
for (unsigned i : range(endBitNo - startBitNo)) {
661-
(void)i;
616+
for (auto bit : bits.set_bits()) {
617+
(void)bit;
662618
foundLivenessInfo.push_back(Dead);
663619
}
664620
return;
665621
}
666622

667-
liveBlockIter->second.getLiveness(startBitNo, endBitNo, foundLivenessInfo);
623+
liveBlockIter->second.getLiveness(bits, foundLivenessInfo);
668624
}
669625

670626
llvm::StringRef getStringRef(IsLive isLive) const;
@@ -972,6 +928,12 @@ class FieldSensitivePrunedLiveness {
972928
resultingFoundLiveness);
973929
}
974930

931+
void getBlockLiveness(SILBasicBlock *bb, SmallBitVector const &bits,
932+
SmallVectorImpl<FieldSensitivePrunedLiveBlocks::IsLive>
933+
&foundLivenessInfo) const {
934+
liveBlocks.getBlockLiveness(bb, bits, foundLivenessInfo);
935+
}
936+
975937
/// Return the liveness for this specific sub-element of our root value.
976938
FieldSensitivePrunedLiveBlocks::IsLive
977939
getBlockLiveness(SILBasicBlock *bb, unsigned subElementNumber) const {
@@ -1016,16 +978,16 @@ class FieldSensitivePrunedLiveness {
1016978
return record->isInterestingUser(element);
1017979
}
1018980

1019-
/// Whether \p user uses the fields in \p range as indicated by \p kind.
981+
/// Whether \p user uses the fields in \p bits as indicated by \p kind.
1020982
bool isInterestingUserOfKind(SILInstruction *user, IsInterestingUser kind,
1021-
TypeTreeLeafTypeRange range) const {
983+
SmallBitVector const &bits) const {
1022984
auto *record = getInterestingUser(user);
1023985
if (!record) {
1024986
return kind == IsInterestingUser::NonUser;
1025987
}
1026988

1027-
for (auto element : range.getRange()) {
1028-
if (record->isInterestingUser(element) != kind)
989+
for (auto bit : bits.set_bits()) {
990+
if (record->isInterestingUser(bit) != kind)
1029991
return false;
1030992
}
1031993
return true;
@@ -1172,10 +1134,10 @@ class FieldSensitivePrunedLiveRange : public FieldSensitivePrunedLiveness {
11721134
: FieldSensitivePrunedLiveness(fn, discoveredBlocks) {}
11731135

11741136
/// Check if \p inst occurs in between the definition of a def and the
1175-
/// liveness boundary for bits in \p span.
1137+
/// liveness boundary for \p bits.
11761138
///
1177-
/// NOTE: It is assumed that \p inst is correctly described by span.
1178-
bool isWithinBoundary(SILInstruction *inst, TypeTreeLeafTypeRange span) const;
1139+
/// NOTE: It is assumed that \p inst is correctly described by \p bits.
1140+
bool isWithinBoundary(SILInstruction *inst, SmallBitVector const &bits) const;
11791141

11801142
/// Customize updateForUse for FieldSensitivePrunedLiveness such that we check
11811143
/// that we consider defs as stopping liveness from being propagated up.

lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,50 @@ void TypeTreeLeafTypeRange::constructFilteredProjections(
473473
llvm_unreachable("Not understand subtype");
474474
}
475475

476+
std::optional<TypeTreeLeafTypeRange>
477+
TypeTreeLeafTypeRange::get(Operand *op, SILValue rootValue) {
478+
auto projectedValue = op->get();
479+
auto startEltOffset = SubElementOffset::compute(projectedValue, rootValue);
480+
if (!startEltOffset)
481+
return std::nullopt;
482+
483+
// A drop_deinit only consumes the deinit bit of its operand.
484+
if (isa<DropDeinitInst>(op->getUser())) {
485+
auto upperBound = *startEltOffset + TypeSubElementCount(projectedValue);
486+
return {{upperBound - 1, upperBound}};
487+
}
488+
489+
// An `inject_enum_addr` only initializes the enum tag.
490+
if (auto inject = dyn_cast<InjectEnumAddrInst>(op->getUser())) {
491+
auto upperBound = *startEltOffset + TypeSubElementCount(projectedValue);
492+
unsigned payloadUpperBound = 0;
493+
if (inject->getElement()->hasAssociatedValues()) {
494+
auto payloadTy = projectedValue->getType().getEnumElementType(
495+
inject->getElement(), op->getFunction());
496+
497+
payloadUpperBound =
498+
*startEltOffset + TypeSubElementCount(payloadTy, op->getFunction());
499+
}
500+
// TODO: account for deinit component if enum has deinit.
501+
assert(!projectedValue->getType().isValueTypeWithDeinit());
502+
return {{payloadUpperBound, upperBound}};
503+
}
504+
505+
// Uses that borrow a value do not involve the deinit bit.
506+
//
507+
// FIXME: This shouldn't be limited to applies.
508+
unsigned deinitBitOffset = 0;
509+
if (op->get()->getType().isValueTypeWithDeinit() &&
510+
op->getOperandOwnership() == OperandOwnership::Borrow &&
511+
ApplySite::isa(op->getUser())) {
512+
deinitBitOffset = 1;
513+
}
514+
515+
return {{*startEltOffset, *startEltOffset +
516+
TypeSubElementCount(projectedValue) -
517+
deinitBitOffset}};
518+
}
519+
476520
void TypeTreeLeafTypeRange::constructProjectionsForNeededElements(
477521
SILValue rootValue, SILInstruction *insertPt,
478522
SmallBitVector &neededElements,
@@ -831,16 +875,15 @@ static FunctionTest FieldSensitiveSSAUseLivenessTest(
831875

832876
template <typename LivenessWithDefs>
833877
bool FieldSensitivePrunedLiveRange<LivenessWithDefs>::isWithinBoundary(
834-
SILInstruction *inst, TypeTreeLeafTypeRange span) const {
878+
SILInstruction *inst, SmallBitVector const &bits) const {
835879
assert(asImpl().isInitialized());
836880

837-
PRUNED_LIVENESS_LOG(
838-
llvm::dbgs() << "FieldSensitivePrunedLiveRange::isWithinBoundary!\n"
839-
<< "Span: ";
840-
span.print(llvm::dbgs()); llvm::dbgs() << '\n');
881+
PRUNED_LIVENESS_LOG(llvm::dbgs()
882+
<< "FieldSensitivePrunedLiveRange::isWithinBoundary!\n"
883+
<< "Bits: " << bits << "\n");
841884

842885
// If we do not have any span, return true since we have no counter examples.
843-
if (span.empty()) {
886+
if (bits.empty()) {
844887
PRUNED_LIVENESS_LOG(llvm::dbgs() << " span is empty! Returning true!\n");
845888
return true;
846889
}
@@ -850,13 +893,13 @@ bool FieldSensitivePrunedLiveRange<LivenessWithDefs>::isWithinBoundary(
850893
auto *block = inst->getParent();
851894

852895
SmallVector<IsLive, 8> outVector;
853-
getBlockLiveness(block, span, outVector);
896+
getBlockLiveness(block, bits, outVector);
854897

855-
for (auto pair : llvm::enumerate(outVector)) {
856-
unsigned bit = span.startEltOffset + pair.index();
898+
for (auto bitAndIndex : llvm::enumerate(bits.set_bits())) {
899+
unsigned bit = bitAndIndex.value();
857900
PRUNED_LIVENESS_LOG(llvm::dbgs() << " Visiting bit: " << bit << '\n');
858901
bool isLive = false;
859-
switch (pair.value()) {
902+
switch (outVector[bitAndIndex.index()]) {
860903
case FieldSensitivePrunedLiveBlocks::DeadToLiveEdge:
861904
case FieldSensitivePrunedLiveBlocks::Dead:
862905
PRUNED_LIVENESS_LOG(llvm::dbgs() << " Dead... continuing!\n");

0 commit comments

Comments
 (0)