Skip to content

Commit bddc69c

Browse files
committed
Organize SILOptimizer/Utils headers. Remove Local.h.
The XXOptUtils.h convention is already established and parallels the SIL/XXUtils convention. New: - InstOptUtils.h - CFGOptUtils.h - BasicBlockOptUtils.h - ValueLifetime.h Removed: - Local.h - Two conflicting CFG.h files This reorganization is helpful before I introduce more utilities for block cloning similar to SinkAddressProjections. Move the control flow utilies out of Local.h, which was an unreadable, unprincipled mess. Rename it to InstOptUtils.h, and confine it to small APIs for working with individual instructions. These are the optimizer's additions to /SIL/InstUtils.h. Rename CFG.h to CFGOptUtils.h and remove the one in /Analysis. Now there is only SIL/CFG.h, resolving the naming conflict within the swift project (this has always been a problem for source tools). Limit this header to low-level APIs for working with branches and CFG edges. Add BasicBlockOptUtils.h for block level transforms (it makes me sad that I can't use BBOptUtils.h, but SIL already has BasicBlockUtils.h). These are larger APIs for cloning or removing whole blocks.
1 parent 5883345 commit bddc69c

File tree

107 files changed

+1502
-1416
lines changed

Some content is hidden

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

107 files changed

+1502
-1416
lines changed

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 &Fn);
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 UI : V->getUses())
49+
if (UI->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 *L, DominanceInfo *DT, SILLoopInfo *LI,
61+
bool RotateSingleBlockLoops, SILBasicBlock *UpTo,
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 *DT, SILLoopInfo *LI);
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 *Old, SILInstruction *New) {
159+
if (Filter(New))
160+
InstructionPairs.push_back(std::make_pair(New, Old));
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)