Skip to content

Commit d33ea9f

Browse files
committed
SIL: remove the JointPostDominanceSetComputer helper struct.
Instead make `findJointPostDominatingSet` a stand-alone function. There is no need to keep the temporary SmallVector alive across multiple calls of findJointPostDominatingSet for the purpose of re-using malloc'ed memory. The worklist usually contains way less elements than its small size.
1 parent b8e348c commit d33ea9f

File tree

14 files changed

+114
-211
lines changed

14 files changed

+114
-211
lines changed

include/swift/SIL/BasicBlockUtils.h

Lines changed: 43 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -90,80 +90,49 @@ class DeadEndBlocks {
9090
const SILFunction *getFunction() const { return f; }
9191
};
9292

93-
/// A struct that contains the intermediate state used in computing
94-
/// joint-dominance sets. Enables a pass to easily reuse the same small data
95-
/// structures with clearing (noting that clearing our internal state does not
96-
/// cause us to shrink meaning that once we malloc, we keep the malloced
97-
/// memory).
98-
struct JointPostDominanceSetComputer {
99-
/// The worklist that drives the algorithm.
100-
SmallVector<SILBasicBlock *, 32> worklist;
101-
102-
/// A subset of our initial blocks that we found as a predecessor of another
103-
/// block along our walk.
104-
SmallVector<SILBasicBlock *, 8> reachableInputBlocks;
105-
106-
/// As we process the worklist, any successors that we see that have not been
107-
/// visited yet are placed in here. At the end of our worklist, any blocks
108-
/// that remain here are "leaking blocks" that together with our initial set
109-
/// would provide a jointly-postdominating set of our dominating value.
110-
SmallVector<SILBasicBlock *, 32> blocksThatLeakIfNeverVisited;
111-
112-
DeadEndBlocks &deadEndBlocks;
113-
114-
JointPostDominanceSetComputer(DeadEndBlocks &deadEndBlocks)
115-
: deadEndBlocks(deadEndBlocks) {}
116-
117-
void clear() {
118-
worklist.clear();
119-
reachableInputBlocks.clear();
120-
blocksThatLeakIfNeverVisited.clear();
121-
}
122-
123-
/// Compute joint-postdominating set for \p dominatingBlock and \p
124-
/// dominatedBlockSet found by walking up the CFG from the latter to the
125-
/// former.
126-
///
127-
/// We pass back the following information via callbacks so our callers can
128-
/// use whatever container they need to:
129-
///
130-
/// * inputBlocksFoundDuringWalk: Any blocks from the "dominated
131-
/// block set" that was found as a predecessor block during our traversal is
132-
/// passed to this callback. These can occur for two reasons:
133-
///
134-
/// 1. We actually had a block in \p dominatedBlockSet that was reachable
135-
/// from another block in said set. This is a valid usage of the API
136-
/// since it could be that the user does not care about such uses and
137-
/// leave this callback empty.
138-
///
139-
/// 2. We had a block in \p dominatedBlockSet that is in a sub-loop in the
140-
/// loop-nest relative to \p dominatingBlock causing us to go around a
141-
/// backedge and hit the block during our traversal. In this case, we
142-
/// have already during the traversal passed the exiting blocks of the
143-
/// sub-loop as joint postdominace completion set blocks. This is useful
144-
/// if one is using this API for lifetime extension purposes of lifetime
145-
/// ending uses and one needs to insert compensating copy_value at these
146-
/// locations due to the lack of strong control-equivalence in between
147-
/// the block and \p dominatingBlock.
148-
///
149-
///
150-
/// * foundJointPostDomSetCompletionBlocks: The set of blocks not in \p
151-
/// dominatedBlockSet that together with \p dominatedBlockSet
152-
/// jointly-postdominate \p dominatedBlock. This is "completing" the joint
153-
/// post-dominance set.
154-
///
155-
/// * inputBlocksInJointPostDomSet: Any of our input blocks that were never
156-
/// found as a predecessor is passed to this callback. This block is in the
157-
/// final minimal joint-postdominance set and is passed to this
158-
/// callback. This is optional and we will avoid doing work if it is not
159-
/// set.
160-
void findJointPostDominatingSet(
161-
SILBasicBlock *dominatingBlock,
162-
ArrayRef<SILBasicBlock *> dominatedBlockSet,
163-
function_ref<void(SILBasicBlock *)> inputBlocksFoundDuringWalk,
164-
function_ref<void(SILBasicBlock *)> foundJointPostDomSetCompletionBlocks,
165-
function_ref<void(SILBasicBlock *)> inputBlocksInJointPostDomSet = {});
166-
};
93+
/// Compute joint-postdominating set for \p dominatingBlock and \p
94+
/// dominatedBlockSet found by walking up the CFG from the latter to the
95+
/// former.
96+
///
97+
/// We pass back the following information via callbacks so our callers can
98+
/// use whatever container they need to:
99+
///
100+
/// * inputBlocksFoundDuringWalk: Any blocks from the "dominated
101+
/// block set" that was found as a predecessor block during our traversal is
102+
/// passed to this callback. These can occur for two reasons:
103+
///
104+
/// 1. We actually had a block in \p dominatedBlockSet that was reachable
105+
/// from another block in said set. This is a valid usage of the API
106+
/// since it could be that the user does not care about such uses and
107+
/// leave this callback empty.
108+
///
109+
/// 2. We had a block in \p dominatedBlockSet that is in a sub-loop in the
110+
/// loop-nest relative to \p dominatingBlock causing us to go around a
111+
/// backedge and hit the block during our traversal. In this case, we
112+
/// have already during the traversal passed the exiting blocks of the
113+
/// sub-loop as joint postdominace completion set blocks. This is useful
114+
/// if one is using this API for lifetime extension purposes of lifetime
115+
/// ending uses and one needs to insert compensating copy_value at these
116+
/// locations due to the lack of strong control-equivalence in between
117+
/// the block and \p dominatingBlock.
118+
///
119+
///
120+
/// * foundJointPostDomSetCompletionBlocks: The set of blocks not in \p
121+
/// dominatedBlockSet that together with \p dominatedBlockSet
122+
/// jointly-postdominate \p dominatedBlock. This is "completing" the joint
123+
/// post-dominance set.
124+
///
125+
/// * inputBlocksInJointPostDomSet: Any of our input blocks that were never
126+
/// found as a predecessor is passed to this callback. This block is in the
127+
/// final minimal joint-postdominance set and is passed to this
128+
/// callback. This is optional and we will avoid doing work if it is not
129+
/// set.
130+
void findJointPostDominatingSet(
131+
SILBasicBlock *dominatingBlock,
132+
ArrayRef<SILBasicBlock *> dominatedBlockSet,
133+
function_ref<void(SILBasicBlock *)> inputBlocksFoundDuringWalk,
134+
function_ref<void(SILBasicBlock *)> foundJointPostDomSetCompletionBlocks,
135+
function_ref<void(SILBasicBlock *)> inputBlocksInJointPostDomSet = {});
167136

168137
} // namespace swift
169138

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -695,15 +695,13 @@ SILBasicBlock::iterator replaceSingleUse(Operand *use, SILValue newValue,
695695
/// and destroy at leaking blocks to adjust ownership and make available for use
696696
/// at \p inBlock.
697697
SILValue
698-
makeCopiedValueAvailable(SILValue value, SILBasicBlock *inBlock,
699-
JointPostDominanceSetComputer *jointPostDomComputer);
698+
makeCopiedValueAvailable(SILValue value, SILBasicBlock *inBlock);
700699

701700
/// Given a newly created @owned value \p value without any uses, this utility
702701
/// inserts control equivalent copy and destroy at leaking blocks to adjust
703702
/// ownership and make \p value available for use at \p inBlock.
704703
SILValue
705-
makeNewValueAvailable(SILValue value, SILBasicBlock *inBlock,
706-
JointPostDominanceSetComputer *jointPostDomComputer);
704+
makeNewValueAvailable(SILValue value, SILBasicBlock *inBlock);
707705

708706
/// Given a forwarding instruction, eliminate it if all of its users are debug
709707
/// instructions and ownership uses.

include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,7 @@ class LSValue : public LSBase {
255255
///
256256
/// In the case where we have a single value this can be materialized by
257257
/// applying Path to the Base.
258-
SILValue materialize(SILInstruction *Inst,
259-
JointPostDominanceSetComputer *jointPostDomComputer) {
258+
SILValue materialize(SILInstruction *Inst) {
260259
if (CoveringValue)
261260
return SILValue();
262261
auto Val = Base;
@@ -269,8 +268,7 @@ class LSValue : public LSBase {
269268
}
270269
auto Res = Path.getValue().createExtract(Val, &*InsertPt, true);
271270
if (Val != Base) {
272-
Res = makeCopiedValueAvailable(Res, Inst->getParent(),
273-
jointPostDomComputer);
271+
Res = makeCopiedValueAvailable(Res, Inst->getParent());
274272
Builder.emitEndBorrowOperation(InsertPt->getLoc(), Val);
275273
// Insert a destroy on the Base
276274
SILBuilderWithScope(Inst).emitDestroyValueOperation(Inst->getLoc(), Base);
@@ -296,11 +294,9 @@ class LSValue : public LSBase {
296294
/// location holds. This may involve extracting and aggregating available
297295
/// values.
298296
static void reduceInner(LSLocation &B, SILModule *M, LSLocationValueMap &Vals,
299-
SILInstruction *InsertPt,
300-
JointPostDominanceSetComputer *jointPostDomComputer);
297+
SILInstruction *InsertPt);
301298
static SILValue reduce(LSLocation &B, SILModule *M, LSLocationValueMap &Vals,
302-
SILInstruction *InsertPt,
303-
JointPostDominanceSetComputer *jointPostDomComputer);
299+
SILInstruction *InsertPt);
304300
};
305301

306302
static inline llvm::hash_code hash_value(const LSValue &V) {

include/swift/SILOptimizer/Utils/OwnershipOptUtils.h

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ struct OwnershipFixupContext {
3737
Optional<InstModCallbacks> inlineCallbacks;
3838
InstModCallbacks &callbacks;
3939
DeadEndBlocks &deBlocks;
40-
JointPostDominanceSetComputer &jointPostDomSetComputer;
4140

4241
SmallVector<Operand *, 8> transitiveBorrowedUses;
4342
SmallVector<std::pair<SILBasicBlock *, unsigned>, 8> recursiveReborrows;
@@ -64,30 +63,16 @@ struct OwnershipFixupContext {
6463
};
6564
AddressFixupContext extraAddressFixupInfo;
6665

67-
OwnershipFixupContext(InstModCallbacks &callbacks, DeadEndBlocks &deBlocks,
68-
JointPostDominanceSetComputer &jointPostDomSetComputer)
69-
: callbacks(callbacks), deBlocks(deBlocks),
70-
jointPostDomSetComputer(jointPostDomSetComputer) {}
66+
OwnershipFixupContext(InstModCallbacks &callbacks, DeadEndBlocks &deBlocks)
67+
: callbacks(callbacks), deBlocks(deBlocks) {}
7168

7269
void clear() {
73-
jointPostDomSetComputer.clear();
7470
transitiveBorrowedUses.clear();
7571
recursiveReborrows.clear();
7672
extraAddressFixupInfo.allAddressUsesFromOldValue.clear();
7773
extraAddressFixupInfo.intPtrOp = InteriorPointerOperand();
7874
}
7975

80-
/// Gets access to the joint post dominance computer and clears it after \p
81-
/// callback.
82-
template <typename ResultTy>
83-
ResultTy withJointPostDomComputer(
84-
function_ref<ResultTy(JointPostDominanceSetComputer &)> callback) {
85-
// Make sure we clear the joint post dom computer after callback.
86-
SWIFT_DEFER { jointPostDomSetComputer.clear(); };
87-
// Then return callback passing in the computer.
88-
return callback(jointPostDomSetComputer);
89-
}
90-
9176
private:
9277
/// Helper method called to determine if we discovered we needed interior
9378
/// pointer fixups while simplifying.

lib/SIL/Utils/BasicBlockUtils.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ static bool endsInUnreachable(SILBasicBlock *block) {
398398
return isa<UnreachableInst>(block->getTerminator());
399399
}
400400

401-
void JointPostDominanceSetComputer::findJointPostDominatingSet(
401+
void swift::findJointPostDominatingSet(
402402
SILBasicBlock *dominatingBlock, ArrayRef<SILBasicBlock *> dominatedBlockSet,
403403
function_ref<void(SILBasicBlock *)> inputBlocksFoundDuringWalk,
404404
function_ref<void(SILBasicBlock *)> foundJointPostDomSetCompletionBlocks,
@@ -418,9 +418,8 @@ void JointPostDominanceSetComputer::findJointPostDominatingSet(
418418
return;
419419
}
420420

421-
// At the top of where we for sure are going to use state... make sure we
422-
// always clean up any resources that we use!
423-
SWIFT_DEFER { clear(); };
421+
/// The worklist that drives the algorithm.
422+
SmallVector<SILBasicBlock *, 32> worklist;
424423

425424
/// All blocks visited during the backwards walk of the CFG, but not including
426425
/// the initial blocks in `dominatedBlockSet`.

lib/SILOptimizer/Analysis/SimplifyInstruction.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -759,8 +759,7 @@ swift::replaceAllSimplifiedUsesAndErase(SILInstruction *i, SILValue result,
759759
assert(svi != result && "Cannot RAUW a value with itself");
760760

761761
if (svi->getFunction()->hasOwnership()) {
762-
JointPostDominanceSetComputer computer(*deadEndBlocks);
763-
OwnershipFixupContext ctx{callbacks, *deadEndBlocks, computer};
762+
OwnershipFixupContext ctx{callbacks, *deadEndBlocks};
764763
OwnershipRAUWHelper helper(ctx, svi, result);
765764
return helper.perform();
766765
}
@@ -812,8 +811,7 @@ SILBasicBlock::iterator swift::simplifyAndReplaceAllSimplifiedUsesAndErase(
812811
if (!deadEndBlocks)
813812
return next;
814813

815-
JointPostDominanceSetComputer computer(*deadEndBlocks);
816-
OwnershipFixupContext ctx{callbacks, *deadEndBlocks, computer};
814+
OwnershipFixupContext ctx{callbacks, *deadEndBlocks};
817815
OwnershipRAUWHelper helper(ctx, svi, result);
818816

819817
// If our RAUW helper is invalid, we do not support RAUWing this case, so

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,6 @@ class SILCombiner :
9393
/// edges so it is safe to use this here.
9494
DeadEndBlocks deBlocks;
9595

96-
/// A utility struct used by OwnershipFixupContext to map sets of partially
97-
/// post-dominating blocks to a full jointly post-dominating set.
98-
JointPostDominanceSetComputer jPostDomComputer;
99-
10096
/// External context struct used by \see ownershipRAUWHelper.
10197
OwnershipFixupContext ownershipFixupContext;
10298

@@ -131,8 +127,8 @@ class SILCombiner :
131127
use->set(newValue);
132128
Worklist.add(use->getUser());
133129
}),
134-
deBlocks(&B.getFunction()), jPostDomComputer(deBlocks),
135-
ownershipFixupContext(instModCallbacks, deBlocks, jPostDomComputer) {}
130+
deBlocks(&B.getFunction()),
131+
ownershipFixupContext(instModCallbacks, deBlocks) {}
136132

137133
bool runOnFunction(SILFunction &F);
138134

@@ -438,17 +434,6 @@ class SILCombiner :
438434
bool hasOwnership() const {
439435
return Builder.hasOwnership();
440436
}
441-
442-
/// Gets access to the joint post dominance computer and clears it after \p
443-
/// callback.
444-
template <typename ResultTy>
445-
ResultTy withJointPostDomComputer(
446-
function_ref<ResultTy(JointPostDominanceSetComputer &)> callback) {
447-
// Make sure we clear the joint post dom computer after callback.
448-
SWIFT_DEFER { jPostDomComputer.clear(); };
449-
// Then return callback passing in the computer.
450-
return callback(jPostDomComputer);
451-
}
452437
};
453438

454439
} // end namespace swift

lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,10 +1062,8 @@ SILCombiner::visitConvertFunctionInst(ConvertFunctionInst *cfi) {
10621062
continue;
10631063
SmallVector<SILValue, 4> args(pa->getArguments().begin(),
10641064
pa->getArguments().end());
1065-
auto newValue = withJointPostDomComputer<SILValue>([&](auto &j) {
1066-
return makeCopiedValueAvailable(cfi->getConverted(), pa->getParent(),
1067-
&j);
1068-
});
1065+
auto newValue = makeCopiedValueAvailable(cfi->getConverted(),
1066+
pa->getParent());
10691067

10701068
SILBuilderWithScope localBuilder(std::next(pa->getIterator()), Builder);
10711069
auto *newPA = localBuilder.createPartialApply(

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,12 +1963,11 @@ SILInstruction *SILCombiner::visitCondBranchInst(CondBranchInst *CBI) {
19631963
}
19641964

19651965
SILValue selectEnumOperand = SEI->getEnumOperand();
1966-
auto switchEnumOperand = withJointPostDomComputer<SILValue>([&](auto &j) {
1967-
if (selectEnumOperand.getOwnershipKind() == OwnershipKind::None)
1968-
return selectEnumOperand;
1969-
return makeCopiedValueAvailable(selectEnumOperand,
1970-
Builder.getInsertionBB(), &j);
1971-
});
1966+
SILValue switchEnumOperand = selectEnumOperand;
1967+
if (selectEnumOperand.getOwnershipKind() != OwnershipKind::None) {
1968+
switchEnumOperand = makeCopiedValueAvailable(selectEnumOperand,
1969+
Builder.getInsertionBB());
1970+
}
19721971
return Builder.createSwitchEnum(SEI->getLoc(), switchEnumOperand, DefaultBB,
19731972
Cases);
19741973
}

lib/SILOptimizer/Transforms/CSE.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,9 +1397,8 @@ class SILCSE : public SILFunctionTransform {
13971397

13981398
auto *Fn = getFunction();
13991399
DeadEndBlocks DeadEndBBs(Fn);
1400-
JointPostDominanceSetComputer Computer(DeadEndBBs);
14011400
InstModCallbacks callbacks;
1402-
OwnershipFixupContext FixupCtx{callbacks, DeadEndBBs, Computer};
1401+
OwnershipFixupContext FixupCtx{callbacks, DeadEndBBs};
14031402
CSE C(RunsOnHighLevelSil, SEA, FuncBuilder, DeadEndBBs, FixupCtx);
14041403
bool Changed = false;
14051404

0 commit comments

Comments
 (0)