Skip to content

Commit 62ccf81

Browse files
authored
Merge pull request #27417 from atrick/cleanup-cfg-utils
2 parents 3db3525 + 22500e7 commit 62ccf81

File tree

111 files changed

+4711
-4601
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+4711
-4601
lines changed

include/swift/SIL/OptimizationRemark.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@ class Emitter {
157157
using RemarkT = decltype(RemarkBuilder());
158158
// Avoid building the remark unless remarks are enabled.
159159
if (isEnabled<RemarkT>() || Module.getOptRecordStream()) {
160-
auto R = RemarkBuilder();
161-
R.setPassName(PassName);
162-
emit(R);
160+
auto rb = RemarkBuilder();
161+
rb.setPassName(PassName);
162+
emit(rb);
163163
}
164164
}
165165

include/swift/SIL/SILInstructionWorklist.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include "swift/Basic/BlotSetVector.h"
3434
#include "swift/SIL/SILInstruction.h"
3535
#include "swift/SIL/SILValue.h"
36-
#include "swift/SILOptimizer/Utils/Local.h"
36+
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
3737
#include "llvm/ADT/DenseMap.h"
3838
#include "llvm/ADT/SmallVector.h"
3939

include/swift/SIL/TypeSubstCloner.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
#include "swift/AST/GenericEnvironment.h"
2222
#include "swift/AST/ProtocolConformance.h"
2323
#include "swift/AST/Type.h"
24-
#include "swift/SIL/SILCloner.h"
2524
#include "swift/SIL/DynamicCasts.h"
25+
#include "swift/SIL/SILCloner.h"
2626
#include "swift/SIL/SILFunctionBuilder.h"
27-
#include "swift/SILOptimizer/Utils/Local.h"
27+
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
2828
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
2929
#include "llvm/Support/Debug.h"
3030

include/swift/SILOptimizer/Analysis/CFG.h

Lines changed: 0 additions & 50 deletions
This file was deleted.

include/swift/SILOptimizer/Analysis/CallerAnalysis.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "swift/SIL/SILInstruction.h"
1818
#include "swift/SIL/SILModule.h"
1919
#include "swift/SILOptimizer/Analysis/Analysis.h"
20-
#include "swift/SILOptimizer/Utils/Local.h"
20+
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
2121
#include "llvm/ADT/ArrayRef.h"
2222
#include "llvm/ADT/DenseMap.h"
2323
#include "llvm/ADT/SmallSet.h"
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
//===--- BasicBlockOptUtils.h - SIL basic block utilities -------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 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 SILOptimizer for analyzing and operating on whole
14+
/// basic blocks, including as removal, cloning, and SSA update.
15+
///
16+
/// CFGOptUtils.h provides lower-level CFG branch and edge utilities.
17+
///
18+
/// SIL/BasicBlockUtils.h provides essential SILBasicBlock utilities.
19+
///
20+
//===----------------------------------------------------------------------===//
21+
22+
#ifndef SWIFT_SILOPTIMIZER_UTILS_BASICBLOCKOPTUTILS_H
23+
#define SWIFT_SILOPTIMIZER_UTILS_BASICBLOCKOPTUTILS_H
24+
25+
#include "swift/SIL/SILInstruction.h"
26+
#include "swift/SIL/SILBasicBlock.h"
27+
#include "swift/SIL/SILCloner.h"
28+
29+
namespace swift {
30+
31+
class BasicBlockCloner;
32+
class SILLoop;
33+
class SILLoopInfo;
34+
35+
/// Remove all instructions in the body of \p bb in safe manner by using
36+
/// undef.
37+
void clearBlockBody(SILBasicBlock *bb);
38+
39+
/// Handle the mechanical aspects of removing an unreachable block.
40+
void removeDeadBlock(SILBasicBlock *bb);
41+
42+
/// Remove all unreachable blocks in a function.
43+
bool removeUnreachableBlocks(SILFunction &f);
44+
45+
/// Return true if there are any users of v outside the specified block.
46+
inline bool isUsedOutsideOfBlock(SILValue v) {
47+
auto *bb = v->getParentBlock();
48+
for (auto *use : v->getUses())
49+
if (use->getUser()->getParent() != bb)
50+
return true;
51+
return false;
52+
}
53+
54+
/// Rotate a loop's header as long as it is exiting and not equal to the
55+
/// passed basic block.
56+
/// If \p RotateSingleBlockLoops is true a single basic block loop will be
57+
/// rotated once. ShouldVerify specifies whether to perform verification after
58+
/// the transformation.
59+
/// Returns true if the loop could be rotated.
60+
bool rotateLoop(SILLoop *loop, DominanceInfo *domInfo, SILLoopInfo *loopInfo,
61+
bool rotateSingleBlockLoops, SILBasicBlock *upToBB,
62+
bool shouldVerify);
63+
64+
/// Helper function to perform SSA updates in case of jump threading.
65+
void updateSSAAfterCloning(BasicBlockCloner &cloner, SILBasicBlock *srcBB,
66+
SILBasicBlock *destBB);
67+
68+
/// Clone a single basic block and any required successor edges within the same
69+
/// function.
70+
class BasicBlockCloner : public SILCloner<BasicBlockCloner> {
71+
using SuperTy = SILCloner<BasicBlockCloner>;
72+
friend class SILCloner<BasicBlockCloner>;
73+
74+
protected:
75+
/// The original block to be cloned.
76+
SILBasicBlock *origBB;
77+
78+
public:
79+
/// An ordered list of old to new available value pairs.
80+
///
81+
/// updateSSAAfterCloning() expects this public field to hold values that may
82+
/// be remapped in the cloned block and live out.
83+
SmallVector<std::pair<SILValue, SILValue>, 16> AvailVals;
84+
85+
// Clone blocks starting at `origBB`, within the same function.
86+
BasicBlockCloner(SILBasicBlock *origBB)
87+
: SILCloner(*origBB->getParent()), origBB(origBB) {}
88+
89+
void cloneBlock(SILBasicBlock *insertAfterBB = nullptr) {
90+
SmallVector<SILBasicBlock *, 4> successorBBs;
91+
successorBBs.reserve(origBB->getSuccessors().size());
92+
llvm::copy(origBB->getSuccessors(), std::back_inserter(successorBBs));
93+
cloneReachableBlocks(origBB, successorBBs, insertAfterBB);
94+
}
95+
96+
/// Clone the given branch instruction's destination block, splitting
97+
/// its successors, and rewrite the branch instruction.
98+
void cloneBranchTarget(BranchInst *bi) {
99+
assert(origBB == bi->getDestBB());
100+
101+
cloneBlock(/*insertAfter*/ bi->getParent());
102+
103+
SILBuilderWithScope(bi).createBranch(bi->getLoc(), getNewBB(),
104+
bi->getArgs());
105+
bi->eraseFromParent();
106+
}
107+
108+
/// Get the newly cloned block corresponding to `origBB`.
109+
SILBasicBlock *getNewBB() {
110+
return remapBasicBlock(origBB);
111+
}
112+
113+
/// Call this after processing all instructions to fix the control flow
114+
/// graph. The branch cloner may have left critical edges.
115+
bool splitCriticalEdges(DominanceInfo *domInfo, SILLoopInfo *loopInfo);
116+
117+
protected:
118+
// MARK: CRTP overrides.
119+
120+
/// Override getMappedValue to allow values defined outside the block to be
121+
/// cloned to be reused in the newly cloned block.
122+
SILValue getMappedValue(SILValue value) {
123+
if (auto si = value->getDefiningInstruction()) {
124+
if (!isBlockCloned(si->getParent()))
125+
return value;
126+
} else if (auto bbArg = dyn_cast<SILArgument>(value)) {
127+
if (!isBlockCloned(bbArg->getParent()))
128+
return value;
129+
} else {
130+
assert(isa<SILUndef>(value) && "Unexpected Value kind");
131+
return value;
132+
}
133+
// `value` is not defined outside the cloned block, so consult the cloner's
134+
// map of cloned values.
135+
return SuperTy::getMappedValue(value);
136+
}
137+
138+
void mapValue(SILValue origValue, SILValue mappedValue) {
139+
SuperTy::mapValue(origValue, mappedValue);
140+
AvailVals.emplace_back(origValue, mappedValue);
141+
}
142+
};
143+
144+
// Helper class that provides a callback that can be used in
145+
// inliners/cloners for collecting new call sites.
146+
class CloneCollector {
147+
public:
148+
typedef std::pair<SILInstruction *, SILInstruction *> value_type;
149+
typedef std::function<void(SILInstruction *, SILInstruction *)> CallbackType;
150+
typedef std::function<bool (SILInstruction *)> FilterType;
151+
152+
private:
153+
FilterType filter;
154+
155+
// Pairs of collected instructions; (new, old)
156+
llvm::SmallVector<value_type, 4> instructionpairs;
157+
158+
void collect(SILInstruction *oldI, SILInstruction *newI) {
159+
if (filter(newI))
160+
instructionpairs.push_back(std::make_pair(newI, oldI));
161+
}
162+
163+
public:
164+
CloneCollector(FilterType filter) : filter(filter) {}
165+
166+
CallbackType getCallback() {
167+
return std::bind(&CloneCollector::collect, this, std::placeholders::_1,
168+
std::placeholders::_2);
169+
}
170+
171+
llvm::SmallVectorImpl<value_type> &getInstructionPairs() {
172+
return instructionpairs;
173+
}
174+
};
175+
176+
/// Sink address projections to their out-of-block uses. This is
177+
/// required after cloning a block and before calling
178+
/// updateSSAAfterCloning to avoid address-type phis.
179+
///
180+
/// This clones address projections at their use points, but does not
181+
/// mutate the block containing the projections.
182+
class SinkAddressProjections {
183+
// Projections ordered from last to first in the chain.
184+
SmallVector<SingleValueInstruction *, 4> projections;
185+
SmallSetVector<SILValue, 4> inBlockDefs;
186+
187+
public:
188+
/// Check for an address projection chain ending at \p inst. Return true if
189+
/// the given instruction is successfully analyzed.
190+
///
191+
/// If \p inst does not produce an address, then return
192+
/// true. getInBlockDefs() will contain \p inst if any of its
193+
/// (non-address) values are used outside its block.
194+
///
195+
/// If \p inst does produce an address, return true only of the
196+
/// chain of address projections within this block is clonable at
197+
/// their use sites. getInBlockDefs will return all non-address
198+
/// operands in the chain that are also defined in this block. These
199+
/// may require phis after cloning the projections.
200+
bool analyzeAddressProjections(SILInstruction *inst);
201+
202+
/// After analyzing projections, returns the list of (non-address) values
203+
/// defined in the same block as the projections which will have uses outside
204+
/// the block after cloning.
205+
ArrayRef<SILValue> getInBlockDefs() const {
206+
return inBlockDefs.getArrayRef();
207+
}
208+
/// Clone the chain of projections at their use sites.
209+
///
210+
/// Return true if anything was done.
211+
///
212+
/// getInBlockProjectionOperandValues() can be called before or after cloning.
213+
bool cloneProjections();
214+
};
215+
216+
/// Utility class for cloning init values into the static initializer of a
217+
/// SILGlobalVariable.
218+
class StaticInitCloner : public SILCloner<StaticInitCloner> {
219+
friend class SILInstructionVisitor<StaticInitCloner>;
220+
friend class SILCloner<StaticInitCloner>;
221+
222+
/// The number of not yet cloned operands for each instruction.
223+
llvm::DenseMap<SILInstruction *, int> numOpsToClone;
224+
225+
/// List of instructions for which all operands are already cloned (or which
226+
/// don't have any operands).
227+
llvm::SmallVector<SILInstruction *, 8> readyToClone;
228+
229+
public:
230+
StaticInitCloner(SILGlobalVariable *gVar)
231+
: SILCloner<StaticInitCloner>(gVar) {}
232+
233+
/// Add \p InitVal and all its operands (transitively) for cloning.
234+
///
235+
/// Note: all init values must are added, before calling clone().
236+
void add(SILInstruction *initVal);
237+
238+
/// Clone \p InitVal and all its operands into the initializer of the
239+
/// SILGlobalVariable.
240+
///
241+
/// \return Returns the cloned instruction in the SILGlobalVariable.
242+
SingleValueInstruction *clone(SingleValueInstruction *initVal);
243+
244+
/// Convenience function to clone a single \p InitVal.
245+
static void appendToInitializer(SILGlobalVariable *gVar,
246+
SingleValueInstruction *initVal) {
247+
StaticInitCloner cloner(gVar);
248+
cloner.add(initVal);
249+
cloner.clone(initVal);
250+
}
251+
252+
protected:
253+
SILLocation remapLocation(SILLocation loc) {
254+
return ArtificialUnreachableLocation();
255+
}
256+
};
257+
258+
} // namespace swift
259+
260+
#endif

0 commit comments

Comments
 (0)