Skip to content

Commit ec732b0

Browse files
authored
Merge pull request #17367 from gottesmm/pr-54f11c8bd266d77cf730855fefc3d2a135669272
2 parents 95ea694 + 00d9542 commit ec732b0

File tree

2 files changed

+178
-129
lines changed

2 files changed

+178
-129
lines changed

include/swift/SILOptimizer/Analysis/ARCAnalysis.h

Lines changed: 103 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,47 @@ class ConsumedArgToEpilogueReleaseMatcher {
204204
ExitKind Kind;
205205
ArrayRef<SILArgumentConvention> ArgumentConventions;
206206

207-
using InstListTy = TinyPtrVector<SILInstruction *>;
208-
llvm::SmallMapVector<SILArgument *, InstListTy, 8> ArgInstMap;
207+
class ArgumentState {
208+
/// The list of releases associated with this argument.
209+
TinyPtrVector<SILInstruction *> releases;
209210

210-
/// Set to true if we found some releases but not all for the argument.
211-
llvm::DenseSet<SILArgument *> FoundSomeReleases;
211+
/// If this is set to true, then we know that we were able to find
212+
/// a set of releases.
213+
bool jointPostDominatingReleaseSet;
214+
215+
public:
216+
ArgumentState(ArrayRef<SILInstruction *> releases)
217+
: releases(releases), jointPostDominatingReleaseSet(false) {}
218+
219+
void addRelease(SILInstruction *release) { releases.push_back(release); }
220+
void setHasJointPostDominatingReleaseSet() {
221+
jointPostDominatingReleaseSet = true;
222+
}
223+
224+
bool foundSomeButNotAllReleases() const {
225+
return releases.size() && !jointPostDominatingReleaseSet;
226+
}
227+
228+
/// If we were able to find a set of releases for this argument that joint
229+
/// post-dominate the argument, return our release set.
230+
Optional<ArrayRef<SILInstruction *>> getFullyPostDomReleases() const {
231+
if (releases.empty() || foundSomeButNotAllReleases())
232+
return None;
233+
return {releases};
234+
}
235+
236+
/// If we were able to find a set of releases for this argument, but those
237+
/// releases do not joint post-dominate the argument, return our release
238+
/// set.
239+
///
240+
/// *NOTE* This returns none if we did not find any releases.
241+
Optional<ArrayRef<SILInstruction *>> getPartiallyPostDomReleases() const {
242+
if (releases.empty() || !foundSomeButNotAllReleases())
243+
return None;
244+
return ArrayRef<SILInstruction *>(releases);
245+
}
246+
};
247+
llvm::SmallMapVector<SILArgument *, ArgumentState, 8> ArgInstMap;
212248

213249
/// Eventually this will be used in place of HasBlock.
214250
SILBasicBlock *ProcessedBlock;
@@ -227,95 +263,97 @@ class ConsumedArgToEpilogueReleaseMatcher {
227263

228264
bool hasBlock() const { return ProcessedBlock != nullptr; }
229265

230-
bool isEpilogueRelease(SILInstruction *I) const {
266+
bool isEpilogueRelease(SILInstruction *i) const {
231267
// This is not a release instruction in the epilogue block.
232-
if (I->getParent() != ProcessedBlock)
268+
if (i->getParent() != ProcessedBlock)
233269
return false;
234-
for (auto &X : ArgInstMap) {
235-
// Either did not find epilogue release or found exploded epilogue
236-
// releases.
237-
if (X.second.size() != 1)
238-
continue;
239-
if (*X.second.begin() == I)
240-
return true;
241-
}
242-
return false;
270+
271+
using PairTy = const std::pair<SILArgument *, ArgumentState>;
272+
return llvm::any_of(ArgInstMap, [&i](PairTy &p) {
273+
auto completeList = p.second.getFullyPostDomReleases();
274+
// If we did not have a complete post dominating release set, then we do
275+
// not want to treat any releases from p as epilogue releases.
276+
if (!completeList)
277+
return false;
278+
279+
// Then make sure that we either found an epilogue release or found
280+
// exploded epilogue releases. We rely on our callers to split up exploded
281+
// parameters.
282+
return completeList->size() == 1 && *completeList->begin() == i;
283+
});
243284
}
244285

245286
/// Return true if we've found some epilogue releases for the argument
246287
/// but not all.
247-
bool hasSomeReleasesForArgument(SILArgument *Arg) {
248-
return FoundSomeReleases.find(Arg) != FoundSomeReleases.end();
288+
bool hasSomeReleasesForArgument(SILArgument *arg) const {
289+
auto iter = ArgInstMap.find(arg);
290+
if (iter == ArgInstMap.end())
291+
return false;
292+
return iter->second.foundSomeButNotAllReleases();
249293
}
250294

251-
bool isSingleRelease(SILArgument *Arg) const {
252-
auto Iter = ArgInstMap.find(Arg);
253-
assert(Iter != ArgInstMap.end() && "Failed to get release list for argument");
254-
return Iter->second.size() == 1;
295+
bool isSingleRelease(SILArgument *arg) const {
296+
auto iter = ArgInstMap.find(arg);
297+
assert(iter != ArgInstMap.end() &&
298+
"Failed to get release list for argument");
299+
300+
// If we do not have a fully post dominating release set bail.
301+
auto completeList = iter->second.getFullyPostDomReleases();
302+
if (!completeList)
303+
return false;
304+
305+
return completeList->size() == 1;
255306
}
256307

257-
SILInstruction *getSingleReleaseForArgument(SILArgument *Arg) {
258-
auto I = ArgInstMap.find(Arg);
259-
if (I == ArgInstMap.end())
308+
SILInstruction *getSingleReleaseForArgument(SILArgument *arg) const {
309+
auto iter = ArgInstMap.find(arg);
310+
if (iter == ArgInstMap.end())
311+
return nullptr;
312+
if (!isSingleRelease(arg))
260313
return nullptr;
261-
if (!isSingleRelease(Arg))
314+
auto completeList = iter->second.getFullyPostDomReleases();
315+
if (!completeList)
262316
return nullptr;
263-
return *I->second.begin();
317+
return *completeList->begin();
264318
}
265319

266-
SILInstruction *getSingleReleaseForArgument(SILValue V) {
267-
auto *Arg = dyn_cast<SILArgument>(V);
268-
if (!Arg)
320+
SILInstruction *getSingleReleaseForArgument(SILValue value) const {
321+
auto *arg = dyn_cast<SILArgument>(value);
322+
if (!arg)
269323
return nullptr;
270-
return getSingleReleaseForArgument(Arg);
324+
return getSingleReleaseForArgument(arg);
271325
}
272326

273-
ArrayRef<SILInstruction *> getReleasesForArgument(SILArgument *Arg) {
274-
auto I = ArgInstMap.find(Arg);
275-
if (I == ArgInstMap.end())
327+
ArrayRef<SILInstruction *> getReleasesForArgument(SILArgument *arg) const {
328+
auto iter = ArgInstMap.find(arg);
329+
if (iter == ArgInstMap.end())
330+
return {};
331+
auto completeList = iter->second.getFullyPostDomReleases();
332+
if (!completeList)
276333
return {};
277-
return I->second;
334+
return completeList.getValue();
278335
}
279336

280-
ArrayRef<SILInstruction *> getReleasesForArgument(SILValue V) {
281-
auto *Arg = dyn_cast<SILArgument>(V);
282-
if (!Arg)
337+
ArrayRef<SILInstruction *> getReleasesForArgument(SILValue value) const {
338+
auto *arg = dyn_cast<SILArgument>(value);
339+
if (!arg)
283340
return {};
284-
return getReleasesForArgument(Arg);
341+
return getReleasesForArgument(arg);
285342
}
286343

287344
/// Recompute the mapping from argument to consumed arg.
288345
void recompute();
289346

290-
bool isSingleReleaseMatchedToArgument(SILInstruction *Inst) {
291-
return count_if(
292-
ArgInstMap,
293-
[&Inst](const std::pair<SILArgument *, ArrayRef<SILInstruction *>> &P)
294-
-> bool {
295-
if (P.second.size() > 1)
296-
return false;
297-
return *P.second.begin() == Inst;
298-
});
347+
bool isSingleReleaseMatchedToArgument(SILInstruction *inst) {
348+
using PairTy = const std::pair<SILArgument *, ArgumentState>;
349+
return count_if(ArgInstMap, [&inst](PairTy &p) {
350+
auto completeList = p.second.getFullyPostDomReleases();
351+
if (!completeList || completeList->size() > 1)
352+
return false;
353+
return *completeList->begin() == inst;
354+
});
299355
}
300356

301-
using iterator = decltype(ArgInstMap)::iterator;
302-
using const_iterator = decltype(ArgInstMap)::const_iterator;
303-
iterator begin() { return ArgInstMap.begin(); }
304-
iterator end() { return ArgInstMap.end(); }
305-
const_iterator begin() const { return ArgInstMap.begin(); }
306-
const_iterator end() const { return ArgInstMap.end(); }
307-
308-
using reverse_iterator = decltype(ArgInstMap)::reverse_iterator;
309-
using const_reverse_iterator = decltype(ArgInstMap)::const_reverse_iterator;
310-
reverse_iterator rbegin() { return ArgInstMap.rbegin(); }
311-
reverse_iterator rend() { return ArgInstMap.rend(); }
312-
const_reverse_iterator rbegin() const { return ArgInstMap.rbegin(); }
313-
const_reverse_iterator rend() const { return ArgInstMap.rend(); }
314-
315-
unsigned size() const { return ArgInstMap.size(); }
316-
317-
iterator_range<iterator> getRange() { return swift::make_range(begin(), end()); }
318-
319357
private:
320358
/// Return true if we have seen releases to part or all of \p Derived in
321359
/// \p Insts.

0 commit comments

Comments
 (0)