Skip to content

Commit 680d3ac

Browse files
committed
auto
1 parent f5969c6 commit 680d3ac

File tree

8 files changed

+1600
-861
lines changed

8 files changed

+1600
-861
lines changed

include/swift/Basic/SmallBitVector.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//===--- SmallBitVector.h -------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_BASIC_SMALLBITVECTOR_H
14+
#define SWIFT_BASIC_SMALLBITVECTOR_H
15+
16+
#include "llvm/ADT/SmallBitVector.h"
17+
#include "llvm/Support/raw_ostream.h"
18+
19+
namespace llvm {
20+
21+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
22+
const SmallBitVector &bv) {
23+
for (unsigned i = 0, e = bv.size(); i != e; ++i)
24+
os << (bv[i] ? '1' : '0');
25+
return os;
26+
}
27+
28+
} // namespace llvm
29+
30+
#endif

include/swift/SIL/FieldSensitivePrunedLiveness.h

Lines changed: 186 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@
1414
#define SWIFT_SIL_FIELDSENSITIVEPRUNTEDLIVENESS_H
1515

1616
#include "swift/AST/TypeExpansionContext.h"
17+
#include "swift/Basic/Debug.h"
18+
#include "swift/Basic/FrozenMultiMap.h"
1719
#include "swift/SIL/PrunedLiveness.h"
20+
#include "llvm/ADT/SmallBitVector.h"
21+
#include "llvm/Support/raw_ostream.h"
1822

1923
namespace swift {
2024

@@ -234,11 +238,10 @@ struct TypeTreeLeafTypeRange {
234238
SubElementNumber startEltOffset;
235239
SubElementNumber endEltOffset;
236240

237-
private:
241+
public:
238242
TypeTreeLeafTypeRange(SubElementNumber start, SubElementNumber end)
239243
: startEltOffset(start), endEltOffset(end) {}
240244

241-
public:
242245
/// The leaf type range for the entire type tree.
243246
TypeTreeLeafTypeRange(SILValue rootAddress)
244247
: startEltOffset(0), endEltOffset(TypeSubElementCount(rootAddress)) {}
@@ -280,6 +283,17 @@ struct TypeTreeLeafTypeRange {
280283
SILValue rootValue, SILInstruction *insertPt, SmallBitVector &neededElements,
281284
SmallVectorImpl<SILValue> &resultingProjections);
282285

286+
static void constructProjectionsForNeededElements(
287+
SILValue rootValue, SILInstruction *insertPt,
288+
SmallBitVector &neededElements,
289+
SmallVectorImpl<std::pair<SILValue, TypeTreeLeafTypeRange>>
290+
&resultingProjections);
291+
292+
static void constructProjectionsForNeededElements(
293+
SILValue rootValue, SILInstruction *insertPt, TypeTreeLeafTypeRange span,
294+
SmallVectorImpl<std::pair<SILValue, TypeTreeLeafTypeRange>>
295+
&resultingProjections);
296+
283297
bool operator==(const TypeTreeLeafTypeRange &other) const {
284298
return startEltOffset == other.startEltOffset &&
285299
endEltOffset == other.endEltOffset;
@@ -289,27 +303,32 @@ struct TypeTreeLeafTypeRange {
289303
return !(*this == other);
290304
}
291305

306+
/// Return the type tree leaf type range that is the intersection of \p this
307+
/// and \p other.
308+
Optional<TypeTreeLeafTypeRange>
309+
setIntersection(const TypeTreeLeafTypeRange &other) const {
310+
unsigned start = startEltOffset;
311+
if (startEltOffset < other.startEltOffset)
312+
start = other.startEltOffset;
313+
unsigned end = endEltOffset;
314+
if (endEltOffset >= other.endEltOffset)
315+
end = other.endEltOffset;
316+
if (start >= end)
317+
return None;
318+
return TypeTreeLeafTypeRange(start, end);
319+
}
320+
292321
/// Is the given leaf type specified by \p singleLeafElementNumber apart of
293322
/// our \p range of leaf type values in the our larger type.
294323
bool contains(SubElementNumber singleLeafElementNumber) const {
295324
return startEltOffset <= singleLeafElementNumber &&
296325
singleLeafElementNumber < endEltOffset;
297326
}
298327

299-
/// Returns true if either of this overlaps at all with the given range.
328+
/// Returns true if \p range is completely within this range.
300329
bool contains(TypeTreeLeafTypeRange range) const {
301-
if (startEltOffset <= range.startEltOffset &&
302-
range.startEltOffset < endEltOffset)
303-
return true;
304-
305-
// If our start and end offsets, our extent is only 1 and we know that our
306-
// value
307-
unsigned rangeLastElt = range.endEltOffset - 1;
308-
if (range.startEltOffset == rangeLastElt)
309-
return false;
310-
311-
// Othrwise, see if endEltOffset - 1 is within the range.
312-
return startEltOffset <= rangeLastElt && rangeLastElt < endEltOffset;
330+
return startEltOffset <= range.startEltOffset &&
331+
endEltOffset >= range.endEltOffset;
313332
}
314333

315334
IntRange<unsigned> getRange() const {
@@ -320,12 +339,21 @@ struct TypeTreeLeafTypeRange {
320339

321340
unsigned size() const { return endEltOffset - startEltOffset; }
322341

323-
void getPerFieldTypeRange(SILType type, SILFunction *fn, llvm::function_ref<void (SILType, TypeTreeLeafTypeRange)> callback);
342+
void getPerFieldTypeRange(
343+
SILType type, SILFunction *fn,
344+
llvm::function_ref<void(SILType, TypeTreeLeafTypeRange)> callback);
324345

325346
/// Construct per field projections if the projection range has any bits in
326347
/// common with filterBitVector.
327-
void constructFilteredProjections(SILValue value, SILInstruction *insertPt, SmallBitVector &filterBitVector,
328-
llvm::function_ref<void (SILValue, TypeTreeLeafTypeRange)> callback);
348+
void constructFilteredProjections(
349+
SILValue value, SILInstruction *insertPt, SmallBitVector &filterBitVector,
350+
llvm::function_ref<void(SILValue, TypeTreeLeafTypeRange)> callback);
351+
352+
void print(llvm::raw_ostream &os) const {
353+
os << "TypeTreeLeafTypeRange: (start: " << startEltOffset
354+
<< ", end: " << endEltOffset << ")";
355+
}
356+
void dump() const { print(llvm::dbgs()); }
329357
};
330358

331359
/// This is exactly like pruned liveness except that instead of tracking a
@@ -417,7 +445,8 @@ class FieldSensitivePrunedLiveness {
417445
return UserBlockRange(getAllUsers(), op);
418446
}
419447

420-
void initializeDefBlock(SILBasicBlock *defBB, TypeTreeLeafTypeRange span) {
448+
void initializeDefBlock(SILBasicBlock *defBB, TypeTreeLeafTypeRange span)
449+
__attribute__((optnone)) {
421450
liveBlocks.initializeDefBlock(defBB, span.startEltOffset,
422451
span.endEltOffset);
423452
}
@@ -443,10 +472,7 @@ class FieldSensitivePrunedLiveness {
443472
/// Return the liveness for this specific sub-element of our root value.
444473
PrunedLiveBlocks::IsLive getBlockLiveness(SILBasicBlock *bb,
445474
unsigned subElementNumber) const {
446-
SmallVector<PrunedLiveBlocks::IsLive, 1> isLive;
447-
liveBlocks.getBlockLiveness(bb, subElementNumber, subElementNumber + 1,
448-
isLive);
449-
return isLive[0];
475+
return liveBlocks.getBlockLiveness(bb, subElementNumber);
450476
}
451477

452478
void getBlockLiveness(
@@ -456,6 +482,10 @@ class FieldSensitivePrunedLiveness {
456482
foundLiveness);
457483
}
458484

485+
void getBlockLiveness(SILBasicBlock *bb, SmallBitVector &liveWithinBits,
486+
SmallBitVector &liveOutBits,
487+
SmallBitVector &deadBits) const;
488+
459489
enum IsInterestingUser { NonUser, NonLifetimeEndingUse, LifetimeEndingUse };
460490

461491
/// Return a result indicating whether the given user was identified as an
@@ -471,6 +501,96 @@ class FieldSensitivePrunedLiveness {
471501
}
472502

473503
unsigned getNumSubElements() const { return liveBlocks.getNumBitsToTrack(); }
504+
505+
void print(llvm::raw_ostream &os) const { liveBlocks.print(os); }
506+
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
507+
};
508+
509+
/// Record the last use points and CFG edges that form the boundary of
510+
/// PrunedLiveness.
511+
///
512+
/// Dead defs may occur even when the liveness result has uses for every
513+
/// definition because those uses may occur in unreachable blocks. A dead def
514+
/// must either be a SILInstruction or SILArgument. This supports memory
515+
/// location liveness, so there isn't necessary a defining SILValue.
516+
///
517+
/// Each boundary edge is identified by its target block. The source of the edge
518+
/// is the target block's single predecessor which must have at least one other
519+
/// non-boundary successor.
520+
class FieldSensitivePrunedLivenessBoundary {
521+
llvm::SmallMapVector<SILInstruction *, SmallBitVector, 8> lastUsers;
522+
llvm::SmallMapVector<SILBasicBlock *, SmallBitVector, 8> boundaryEdges;
523+
llvm::SmallMapVector<SILNode *, SmallBitVector, 1> deadDefs;
524+
unsigned numBits;
525+
526+
public:
527+
FieldSensitivePrunedLivenessBoundary(unsigned numBits) : numBits(numBits) {}
528+
529+
/// Sanity check meant for NDEBUG mode.
530+
unsigned getNumLastUsersAndDeadDefs(unsigned bitNo) const {
531+
#ifdef NDEBUG
532+
llvm_unreachable("Only call in asserts build!\n");
533+
#else
534+
unsigned count = 0;
535+
for (auto &pair : lastUsers) {
536+
count += unsigned(pair.second[bitNo]);
537+
}
538+
for (auto &pair : deadDefs) {
539+
count += unsigned(pair.second[bitNo]);
540+
}
541+
return count;
542+
#endif
543+
}
544+
545+
using LastUserRange = iterator_range<decltype(lastUsers)::iterator>;
546+
LastUserRange getLastUsers() {
547+
return make_range(lastUsers.begin(), lastUsers.end());
548+
}
549+
550+
using BoundaryEdgeRange = iterator_range<decltype(boundaryEdges)::iterator>;
551+
BoundaryEdgeRange getBoundaryEdges() {
552+
return make_range(boundaryEdges.begin(), boundaryEdges.end());
553+
}
554+
555+
using DeadDefRange = iterator_range<decltype(deadDefs)::iterator>;
556+
DeadDefRange getDeadDefs() {
557+
return make_range(deadDefs.begin(), deadDefs.end());
558+
}
559+
560+
/// Helper entry point to get the last user that creates the correct size
561+
/// small bit vector if we haven't seen this last user yet.
562+
SmallBitVector &getLastUserBits(SILInstruction *inst) {
563+
auto iter = lastUsers.insert({inst, SmallBitVector()});
564+
if (iter.second) {
565+
iter.first->second.resize(numBits);
566+
}
567+
return iter.first->second;
568+
}
569+
570+
SmallBitVector &getBoundaryEdgeBits(SILBasicBlock *block) {
571+
auto iter = boundaryEdges.insert({block, SmallBitVector()});
572+
if (iter.second) {
573+
iter.first->second.resize(numBits);
574+
}
575+
return iter.first->second;
576+
}
577+
578+
SmallBitVector &getDeadDefsBits(SILNode *def) {
579+
auto iter = deadDefs.insert({def, SmallBitVector()});
580+
if (iter.second) {
581+
iter.first->second.resize(numBits);
582+
}
583+
return iter.first->second;
584+
}
585+
586+
void clear() {
587+
lastUsers.clear();
588+
boundaryEdges.clear();
589+
deadDefs.clear();
590+
}
591+
592+
void print(llvm::raw_ostream &os) const;
593+
void dump() const;
474594
};
475595

476596
template <typename LivenessWithDefs>
@@ -489,7 +609,18 @@ class FieldSensitivePrunedLiveRange : public FieldSensitivePrunedLiveness {
489609
/// liveness boundary for bits in \p span.
490610
///
491611
/// NOTE: It is assumed that \p inst is correctly described by span.
492-
bool isWithinBoundary(SILInstruction *inst, TypeTreeLeafTypeRange span) const __attribute__((optnone));
612+
bool isWithinBoundary(SILInstruction *inst, TypeTreeLeafTypeRange span) const;
613+
614+
/// Compute the boundary from the blocks discovered during liveness analysis.
615+
///
616+
/// Precondition: \p liveness.getDiscoveredBlocks() is a valid list of all
617+
/// live blocks with no duplicates.
618+
///
619+
/// The computed boundary will completely post-dominate, including dead end
620+
/// paths. The client should query DeadEndBlocks to ignore those dead end
621+
/// paths.
622+
void computeBoundary(FieldSensitivePrunedLivenessBoundary &boundary) const
623+
__attribute__((optnone));
493624
};
494625

495626
/// Single defined liveness.
@@ -549,6 +680,10 @@ class FieldSensitiveSSAPrunedLiveRange
549680
bool isDefBlock(SILBasicBlock *block, unsigned bit) const {
550681
return def.first->getParentBlock() == block && def.second->contains(bit);
551682
}
683+
684+
void
685+
findBoundariesInBlock(SILBasicBlock *block, unsigned bitNo, bool isLiveOut,
686+
FieldSensitivePrunedLivenessBoundary &boundary) const;
552687
};
553688

554689
/// MultiDefPrunedLiveness is computed incrementally by calling updateForUse.
@@ -594,6 +729,13 @@ class FieldSensitiveMultiDefPrunedLiveRange
594729
return iter->second.contains(bit);
595730
}
596731

732+
bool isDefBlock(SILBasicBlock *block, TypeTreeLeafTypeRange span) const {
733+
auto iter = defBlocks.find(block);
734+
if (iter == defBlocks.end())
735+
return false;
736+
return span.setIntersection(iter->second).hasValue();
737+
}
738+
597739
bool isDef(SILInstruction *inst, unsigned bit) const {
598740
auto iter = defs.find(cast<SILNode>(inst));
599741
if (iter == defs.end())
@@ -607,6 +749,26 @@ class FieldSensitiveMultiDefPrunedLiveRange
607749
return false;
608750
return iter->second.contains(bit);
609751
}
752+
753+
bool isDef(SILInstruction *inst, TypeTreeLeafTypeRange span) const {
754+
auto iter = defs.find(cast<SILNode>(inst));
755+
if (iter == defs.end())
756+
return false;
757+
return span.setIntersection(iter->second).hasValue();
758+
}
759+
760+
bool isDef(SILValue value, TypeTreeLeafTypeRange span) const
761+
__attribute__((optnone)) {
762+
auto iter = defs.find(cast<SILNode>(value));
763+
if (iter == defs.end())
764+
return false;
765+
return span.setIntersection(iter->second).hasValue();
766+
}
767+
768+
void
769+
findBoundariesInBlock(SILBasicBlock *block, unsigned bitNo, bool isLiveOut,
770+
FieldSensitivePrunedLivenessBoundary &boundary) const
771+
__attribute__((optnone));
610772
};
611773

612774
} // namespace swift

0 commit comments

Comments
 (0)