Skip to content

Commit 4d2753b

Browse files
committed
Remove updateForPredTerminators in ARCSequenceOpts
Historically TermInsts were handled specially while visiting blocks in bottom up order. TermInsts were not visited while traversing a block. They were visited while traversing successors, and the most conservative terminator of all predecessors would affect the refcount state in the dataflow. This was needed because ARCSequenceOpts also computed 'insertion points' for the purposes of ARC code motion. ARC code motion was then removed from ARCSequenceOpts and this code remained unchanged. With this change, arc significant terminators are handled like all other instructions while processing basic blocks bottom up. Also updateForSameLoopInst, updateForDifferentLoopInst, updateForPredTerminators all serve similar purpose with subtle differences. This change removes some code duplication due to this. Remove code duplication of isARCSignificantTerminator. Create ARCSequenceOptUtils for common utils used in ARCSequenceOpts
1 parent c2374f0 commit 4d2753b

File tree

7 files changed

+91
-183
lines changed

7 files changed

+91
-183
lines changed

lib/SILOptimizer/ARC/ARCRegionState.cpp

Lines changed: 5 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#define DEBUG_TYPE "arc-sequence-opts"
1414
#include "ARCRegionState.h"
15+
#include "ARCSequenceOptUtils.h"
1516
#include "RCStateTransitionVisitors.h"
1617
#include "swift/Basic/Range.h"
1718
#include "swift/SILOptimizer/Analysis/LoopRegionAnalysis.h"
@@ -155,77 +156,6 @@ void ARCRegionState::mergePredTopDown(ARCRegionState &PredRegionState) {
155156
// Bottom Up Dataflow
156157
//
157158

158-
static bool isARCSignificantTerminator(TermInst *TI) {
159-
switch (TI->getTermKind()) {
160-
case TermKind::UnreachableInst:
161-
// br is a forwarding use for its arguments. It cannot in of itself extend
162-
// the lifetime of an object (just like a phi-node) cannot.
163-
case TermKind::BranchInst:
164-
// A cond_br is a forwarding use for its non-operand arguments in a similar
165-
// way to br. Its operand must be an i1 that has a different lifetime from any
166-
// ref counted object.
167-
case TermKind::CondBranchInst:
168-
return false;
169-
// Be conservative for now. These actually perform some sort of operation
170-
// against the operand or can use the value in some way.
171-
case TermKind::ThrowInst:
172-
case TermKind::ReturnInst:
173-
case TermKind::UnwindInst:
174-
case TermKind::YieldInst:
175-
case TermKind::TryApplyInst:
176-
case TermKind::SwitchValueInst:
177-
case TermKind::SwitchEnumInst:
178-
case TermKind::SwitchEnumAddrInst:
179-
case TermKind::DynamicMethodBranchInst:
180-
case TermKind::CheckedCastBranchInst:
181-
case TermKind::CheckedCastValueBranchInst:
182-
case TermKind::CheckedCastAddrBranchInst:
183-
return true;
184-
}
185-
186-
llvm_unreachable("Unhandled TermKind in switch.");
187-
}
188-
189-
// Visit each one of our predecessor regions and see if any are blocks that can
190-
// use reference counted values. If any of them do, we advance the sequence for
191-
// the pointer. This state will be propagated
192-
// into all of our predecessors, allowing us to be conservatively correct in all
193-
// cases.
194-
//
195-
// The key thing to notice is that in general this cannot happen due to
196-
// critical edge splitting. To trigger this, one would need a terminator that
197-
// uses a reference counted value and only has one successor due to critical
198-
// edge splitting. This is just to be conservative when faced with the unknown
199-
// of future changes.
200-
//
201-
// We do not need to worry about loops here, since a loop exit block can only
202-
// have predecessors in the loop itself implying that loop exit blocks at the
203-
// loop region level always have only one predecessor, the loop itself.
204-
void ARCRegionState::processBlockBottomUpPredTerminators(
205-
const LoopRegion *R, AliasAnalysis *AA, LoopRegionFunctionInfo *LRFI,
206-
ImmutablePointerSetFactory<SILInstruction> &SetFactory) {
207-
llvm::TinyPtrVector<SILInstruction *> PredTerminators;
208-
for (unsigned PredID : R->getPreds()) {
209-
auto *PredRegion = LRFI->getRegion(PredID);
210-
if (!PredRegion->isBlock())
211-
continue;
212-
213-
auto *TermInst = PredRegion->getBlock()->getTerminator();
214-
if (!isARCSignificantTerminator(TermInst))
215-
continue;
216-
PredTerminators.push_back(TermInst);
217-
}
218-
219-
for (auto &OtherState : getBottomupStates()) {
220-
// If the other state's value is blotted, skip it.
221-
if (!OtherState.hasValue())
222-
continue;
223-
224-
OtherState->second.updateForPredTerminators(PredTerminators,
225-
SetFactory, AA);
226-
}
227-
}
228-
229159
static bool processBlockBottomUpInsts(
230160
ARCRegionState &State, SILBasicBlock &BB,
231161
BottomUpDataflowRCStateVisitor<ARCRegionState> &DataflowVisitor,
@@ -239,9 +169,9 @@ static bool processBlockBottomUpInsts(
239169
if (II == IE)
240170
return false;
241171

242-
// If II is the terminator, skip it since our terminator was already processed
243-
// in our successors.
244-
if (*II == BB.getTerminator())
172+
// If II is not an arc significant terminator, skip it.
173+
if (*II == BB.getTerminator() &&
174+
!isARCSignificantTerminator(cast<TermInst>(*II)))
245175
++II;
246176

247177
bool NestingDetected = false;
@@ -298,17 +228,10 @@ bool ARCRegionState::processBlockBottomUp(
298228
RCIA, EAFI, *this, FreezeOwnedArgEpilogueReleases, IncToDecStateMap,
299229
SetFactory);
300230

301-
// Visit each non-terminator arc relevant instruction I in BB visited in
302-
// reverse...
231+
// Visit each arc relevant instruction I in BB visited in reverse...
303232
bool NestingDetected =
304233
processBlockBottomUpInsts(*this, BB, DataflowVisitor, AA, SetFactory);
305234

306-
// Now visit each one of our predecessor regions and see if any are blocks
307-
// that can use reference counted values. If any of them do, we advance the
308-
// sequence for the pointer. This state will be propagated into all of our
309-
// predecessors, allowing us to be conservatively correct in all cases.
310-
processBlockBottomUpPredTerminators(R, AA, LRFI, SetFactory);
311-
312235
return NestingDetected;
313236
}
314237

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//===--- ARCSequenceOptUtils.cpp - ARCSequenceOpt utilities ------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 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+
#include "ARCSequenceOptUtils.h"
14+
15+
using namespace swift;
16+
namespace swift {
17+
bool isARCSignificantTerminator(TermInst *TI) {
18+
switch (TI->getTermKind()) {
19+
case TermKind::UnreachableInst:
20+
// br is a forwarding use for its arguments. It cannot in of itself extend
21+
// the lifetime of an object (just like a phi-node) cannot.
22+
case TermKind::BranchInst:
23+
// A cond_br is a forwarding use for its non-operand arguments in a similar
24+
// way to br. Its operand must be an i1 that has a different lifetime from any
25+
// ref counted object.
26+
case TermKind::CondBranchInst:
27+
return false;
28+
// Be conservative for now. These actually perform some sort of operation
29+
// against the operand or can use the value in some way.
30+
case TermKind::ThrowInst:
31+
case TermKind::ReturnInst:
32+
case TermKind::UnwindInst:
33+
case TermKind::YieldInst:
34+
case TermKind::TryApplyInst:
35+
case TermKind::SwitchValueInst:
36+
case TermKind::SwitchEnumInst:
37+
case TermKind::SwitchEnumAddrInst:
38+
case TermKind::DynamicMethodBranchInst:
39+
case TermKind::CheckedCastBranchInst:
40+
case TermKind::CheckedCastValueBranchInst:
41+
case TermKind::CheckedCastAddrBranchInst:
42+
return true;
43+
}
44+
45+
llvm_unreachable("Unhandled TermKind in switch.");
46+
}
47+
48+
} // end namespace 'swift'
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===--- ARCSequenceOptUtils.h - ARCSequenceOpts utilities ----*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 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+
/// Utilities used by the ARCSequenceOpts for analyzing and transforming
14+
/// SILInstructions.
15+
///
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef SWIFT_SILOPTIMIZER_ARC_ARCSEQUENCEOPTUTILS_H
19+
#define SWIFT_SILOPTIMIZER_ARC_ARCSEQUENCEOPTUTILS_H
20+
21+
#include "swift/SIL/SILInstruction.h"
22+
23+
namespace swift {
24+
bool isARCSignificantTerminator(TermInst *TI);
25+
} // end namespace swift
26+
27+
#endif

lib/SILOptimizer/ARC/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ target_sources(swiftSILOptimizer PRIVATE
44
ARCMatchingSet.cpp
55
ARCRegionState.cpp
66
ARCSequenceOpts.cpp
7+
ARCSequenceOptUtils.cpp
78
GlobalARCSequenceDataflow.cpp
89
GlobalLoopARCSequenceDataflow.cpp
910
RCStateTransition.cpp

lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp

Lines changed: 10 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define DEBUG_TYPE "arc-sequence-opts"
1414
#include "GlobalARCSequenceDataflow.h"
1515
#include "ARCBBState.h"
16+
#include "ARCSequenceOptUtils.h"
1617
#include "RCStateTransitionVisitors.h"
1718
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
1819
#include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
@@ -195,39 +196,6 @@ bool ARCSequenceDataflowEvaluator::processTopDown() {
195196
// Bottom Up Dataflow
196197
//===----------------------------------------------------------------------===//
197198

198-
// This is temporary code duplication. This will be removed when Loop ARC is
199-
// finished and Block ARC is removed.
200-
static bool isARCSignificantTerminator(TermInst *TI) {
201-
switch (TI->getTermKind()) {
202-
case TermKind::UnreachableInst:
203-
// br is a forwarding use for its arguments. It cannot in of itself extend
204-
// the lifetime of an object (just like a phi-node) cannot.
205-
case TermKind::BranchInst:
206-
// A cond_br is a forwarding use for its non-operand arguments in a similar
207-
// way to br. Its operand must be an i1 that has a different lifetime from any
208-
// ref counted object.
209-
case TermKind::CondBranchInst:
210-
return false;
211-
// Be conservative for now. These actually perform some sort of operation
212-
// against the operand or can use the value in some way.
213-
case TermKind::ThrowInst:
214-
case TermKind::ReturnInst:
215-
case TermKind::UnwindInst:
216-
case TermKind::YieldInst:
217-
case TermKind::TryApplyInst:
218-
case TermKind::SwitchValueInst:
219-
case TermKind::SwitchEnumInst:
220-
case TermKind::SwitchEnumAddrInst:
221-
case TermKind::DynamicMethodBranchInst:
222-
case TermKind::CheckedCastBranchInst:
223-
case TermKind::CheckedCastValueBranchInst:
224-
case TermKind::CheckedCastAddrBranchInst:
225-
return true;
226-
}
227-
228-
llvm_unreachable("Unhandled TermKind in switch.");
229-
}
230-
231199
/// Analyze a single BB for refcount inc/dec instructions.
232200
///
233201
/// If anything was found it will be added to DecToIncStateMap.
@@ -254,8 +222,15 @@ bool ARCSequenceDataflowEvaluator::processBBBottomUp(
254222
RCIA, EAFI, BBState, FreezeOwnedArgEpilogueReleases, IncToDecStateMap,
255223
SetFactory);
256224

257-
// For each terminator instruction I in BB visited in reverse...
258-
for (auto II = std::next(BB.rbegin()), IE = BB.rend(); II != IE;) {
225+
auto II = BB.rbegin();
226+
if (isa<TermInst>(*II)) {
227+
if (!isARCSignificantTerminator(&cast<TermInst>(*II))) {
228+
II++;
229+
}
230+
}
231+
232+
// For each instruction I in BB visited in reverse...
233+
for (auto IE = BB.rend(); II != IE;) {
259234
SILInstruction &I = *II;
260235
++II;
261236

@@ -292,31 +267,6 @@ bool ARCSequenceDataflowEvaluator::processBBBottomUp(
292267
}
293268
}
294269

295-
// This is ignoring the possibility that we may have a loop with an
296-
// interesting terminator but for which, we are going to clear all state
297-
// (since it is a loop boundary). We may in such a case, be too conservative
298-
// with our other predecessors. Luckily this cannot happen since cond_br is
299-
// the only terminator that allows for critical edges and all other
300-
// "interesting terminators" always having multiple successors. This means
301-
// that this block could not have multiple predecessors since otherwise, the
302-
// edge would be broken.
303-
llvm::TinyPtrVector<SILInstruction *> PredTerminators;
304-
for (SILBasicBlock *PredBB : BB.getPredecessorBlocks()) {
305-
auto *TermInst = PredBB->getTerminator();
306-
if (!isARCSignificantTerminator(TermInst))
307-
continue;
308-
PredTerminators.push_back(TermInst);
309-
}
310-
311-
for (auto &OtherState : BBState.getBottomupStates()) {
312-
// If the other state's value is blotted, skip it.
313-
if (!OtherState.hasValue())
314-
continue;
315-
316-
OtherState->second.updateForPredTerminators(PredTerminators,
317-
SetFactory, AA);
318-
}
319-
320270
return NestingDetected;
321271
}
322272

lib/SILOptimizer/ARC/RefCountState.cpp

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -500,40 +500,6 @@ void BottomUpRefCountState::updateForDifferentLoopInst(
500500
<< getRCRoot());
501501
}
502502

503-
void BottomUpRefCountState::updateForPredTerminators(
504-
ArrayRef<SILInstruction *> Terms,
505-
ImmutablePointerSetFactory<SILInstruction> &SetFactory, AliasAnalysis *AA) {
506-
// If this state is not tracking anything, there is nothing to update.
507-
if (!isTrackingRefCount())
508-
return;
509-
510-
if (valueCanBeGuaranteedUsedGivenLatticeState() &&
511-
std::any_of(Terms.begin(), Terms.end(),
512-
[this, &AA](SILInstruction *I) -> bool {
513-
return mayGuaranteedUseValue(I, getRCRoot(), AA);
514-
})) {
515-
handleGuaranteedUser(getRCRoot(), SetFactory, AA);
516-
return;
517-
}
518-
519-
if (valueCanBeDecrementedGivenLatticeState() &&
520-
std::any_of(Terms.begin(), Terms.end(),
521-
[this, &AA](SILInstruction *I) -> bool {
522-
return mayDecrementRefCount(I, getRCRoot(), AA);
523-
})) {
524-
handleDecrement();
525-
return;
526-
}
527-
528-
if (!valueCanBeUsedGivenLatticeState() ||
529-
std::none_of(Terms.begin(), Terms.end(),
530-
[this, &AA](SILInstruction *I)
531-
-> bool { return mayHaveSymmetricInterference(I, getRCRoot(), AA); }))
532-
return;
533-
534-
handleUser(getRCRoot(), SetFactory, AA);
535-
}
536-
537503
//===----------------------------------------------------------------------===//
538504
// Top Down Ref Count State
539505
//===----------------------------------------------------------------------===//

lib/SILOptimizer/ARC/RefCountState.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,6 @@ class BottomUpRefCountState : public RefCountState {
205205
ImmutablePointerSetFactory<SILInstruction> &SetFactory,
206206
AliasAnalysis *AA);
207207

208-
// Determine the conservative effect of the given list of predecessor
209-
// terminators upon this reference count.
210-
void updateForPredTerminators(
211-
ArrayRef<SILInstruction *> PredTerms,
212-
ImmutablePointerSetFactory<SILInstruction> &SetFactory,
213-
AliasAnalysis *AA);
214-
215208
/// Attempt to merge \p Other into this ref count state. Return true if we
216209
/// succeed and false otherwise.
217210
bool merge(const BottomUpRefCountState &Other);

0 commit comments

Comments
 (0)