Skip to content

Commit 5dbcf9a

Browse files
committed
---
yaml --- r: 348499 b: refs/heads/master c: ee83fde h: refs/heads/master i: 348497: ad7073d 348495: 0284823
1 parent fea8af4 commit 5dbcf9a

File tree

4 files changed

+210
-141
lines changed

4 files changed

+210
-141
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: dbbd7d584b37fae5ee2dfd84ef0efb3c5e574182
2+
refs/heads/master: ee83fde6dc1ba80baee04f049341b3d1accfc663
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/SIL/SILInstructionWorklist.h

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,18 @@
2222
/// ensuring that removing an instruction is not unnecessarily expensive and
2323
/// that only valid instructions are removed from the list.
2424
///
25+
/// Additionally, SILInstructionWorklist provides conveniences for simple
26+
/// instruction modifications and ensuring that the appropriate instructions
27+
/// will be visited accordingly. For example, if provides a method for
28+
/// replacing an operation which has already been removed with a new instruction
29+
/// determined by a SILInstructionVisitor.
30+
///
2531
//===----------------------------------------------------------------------===//
2632

2733
#include "swift/Basic/BlotSetVector.h"
2834
#include "swift/SIL/SILInstruction.h"
2935
#include "swift/SIL/SILValue.h"
36+
#include "swift/SILOptimizer/Utils/Local.h"
3037
#include "llvm/ADT/DenseMap.h"
3138
#include "llvm/ADT/SmallVector.h"
3239

@@ -126,6 +133,181 @@ class SILInstructionWorklist : SILInstructionWorklistBase {
126133
// Do an explicit clear, shrinking the storage if needed.
127134
worklist.clear();
128135
}
136+
137+
/// Find usages of \p instruction and replace them with usages of \p result.
138+
///
139+
/// Intended to be called during visitation after \p instruction has been
140+
/// removed from the worklist.
141+
///
142+
/// \p instruction the instruction whose usages will be replaced
143+
/// \p result the instruction whose usages will replace \p instruction
144+
///
145+
/// \return whether the instruction was deleted or modified.
146+
bool replaceInstructionWithInstruction(SILInstruction *instruction,
147+
SILInstruction *result
148+
#ifndef NDNEBUG
149+
,
150+
std::string instructionDescription
151+
#endif
152+
) {
153+
if (result != instruction) {
154+
assert(&*std::prev(instruction->getIterator()) == result &&
155+
"Expected new instruction inserted before existing instruction!");
156+
157+
withDebugStream([&](llvm::raw_ostream &stream, StringRef loggingName) {
158+
stream << loggingName << ": Old = " << *instruction << '\n'
159+
<< " "
160+
<< " New = " << *result << '\n';
161+
});
162+
163+
// Everything uses the new instruction now.
164+
replaceInstUsesPairwiseWith(instruction, result);
165+
166+
// Push the new instruction and any users onto the worklist.
167+
add(result);
168+
addUsersOfAllResultsToWorklist(result);
169+
170+
eraseInstFromFunction(*instruction);
171+
172+
return true;
173+
} else {
174+
withDebugStream([&](llvm::raw_ostream &stream, StringRef loggingName) {
175+
stream << loggingName << ": Mod = " << instructionDescription << '\n'
176+
<< " "
177+
<< " New = " << *instruction << '\n';
178+
});
179+
180+
// If the instruction was modified, it's possible that it is now dead.
181+
// if so, remove it.
182+
if (isInstructionTriviallyDead(instruction)) {
183+
eraseInstFromFunction(*instruction);
184+
} else {
185+
add(instruction);
186+
addUsersOfAllResultsToWorklist(instruction);
187+
}
188+
return false;
189+
}
190+
}
191+
192+
// Insert the instruction newInstruction before instruction old in old's
193+
// parent block. Add newInstruction to the worklist.
194+
SILInstruction *insertNewInstBefore(SILInstruction *newInstruction,
195+
SILInstruction &old) {
196+
assert(newInstruction && newInstruction->getParent() == nullptr &&
197+
"newInstruction instruction already inserted into a basic block!");
198+
SILBasicBlock *block = old.getParent();
199+
block->insert(&old, newInstruction); // Insert inst
200+
add(newInstruction);
201+
return newInstruction;
202+
}
203+
204+
// This method is to be used when an instruction is found to be dead,
205+
// replaceable with another preexisting expression. Here we add all uses of
206+
// instruction to the worklist, and replace all uses of instruction with the
207+
// new value.
208+
void replaceInstUsesWith(SingleValueInstruction &instruction,
209+
ValueBase *value) {
210+
addUsersToWorklist(&instruction); // Add all modified instrs to worklist.
211+
212+
withDebugStream([&](llvm::raw_ostream &stream, StringRef loggingName) {
213+
stream << loggingName << ": Replacing " << instruction << '\n'
214+
<< " "
215+
<< " with " << *value << '\n';
216+
});
217+
218+
instruction.replaceAllUsesWith(value);
219+
}
220+
221+
// This method is to be used when a value is found to be dead,
222+
// replaceable with another preexisting expression. Here we add all
223+
// uses of oldValue to the worklist, replace all uses of oldValue
224+
// with newValue.
225+
void replaceValueUsesWith(SILValue oldValue, SILValue newValue) {
226+
addUsersToWorklist(oldValue); // Add all modified instrs to worklist.
227+
228+
withDebugStream([&](llvm::raw_ostream &stream, StringRef loggingName) {
229+
stream << loggingName << ": Replacing " << oldValue << '\n'
230+
<< " "
231+
<< " with " << newValue << '\n';
232+
});
233+
234+
oldValue->replaceAllUsesWith(newValue);
235+
}
236+
237+
void replaceInstUsesPairwiseWith(SILInstruction *oldI, SILInstruction *newI) {
238+
withDebugStream([&](llvm::raw_ostream &stream, StringRef loggingName) {
239+
stream << loggingName << ": Replacing " << *oldI << '\n'
240+
<< " "
241+
<< " with " << *newI << '\n';
242+
});
243+
244+
auto oldResults = oldI->getResults();
245+
auto newResults = newI->getResults();
246+
assert(oldResults.size() == newResults.size());
247+
for (auto i : indices(oldResults)) {
248+
// Add all modified instrs to worklist.
249+
addUsersToWorklist(oldResults[i]);
250+
251+
oldResults[i]->replaceAllUsesWith(newResults[i]);
252+
}
253+
}
254+
255+
// Some instructions can never be "trivially dead" due to side effects or
256+
// producing a void value. In those cases, visit methods should use this
257+
// method to delete the given instruction.
258+
void eraseInstFromFunction(SILInstruction &instruction,
259+
SILBasicBlock::iterator &iterator,
260+
bool addOperandsToWorklist = true) {
261+
// Delete any debug users first.
262+
for (auto result : instruction.getResults()) {
263+
while (!result->use_empty()) {
264+
auto *user = result->use_begin()->getUser();
265+
assert(user->isDebugInstruction());
266+
if (iterator == user->getIterator())
267+
++iterator;
268+
erase(user);
269+
user->eraseFromParent();
270+
}
271+
}
272+
if (iterator == instruction.getIterator())
273+
++iterator;
274+
275+
eraseSingleInstFromFunction(instruction, addOperandsToWorklist);
276+
}
277+
278+
void eraseInstFromFunction(SILInstruction &instruction,
279+
bool addOperandsToWorklist = true) {
280+
SILBasicBlock::iterator nullIter;
281+
return eraseInstFromFunction(instruction, nullIter, addOperandsToWorklist);
282+
}
283+
284+
void eraseSingleInstFromFunction(SILInstruction &instruction,
285+
bool addOperandsToWorklist) {
286+
withDebugStream([&](llvm::raw_ostream &stream, StringRef loggingName) {
287+
stream << loggingName << ": ERASE " << instruction << '\n';
288+
});
289+
290+
assert(!instruction.hasUsesOfAnyResult() &&
291+
"Cannot erase instruction that is used!");
292+
293+
// Make sure that we reprocess all operands now that we reduced their
294+
// use counts.
295+
if (instruction.getNumOperands() < 8 && addOperandsToWorklist) {
296+
for (auto &operand : instruction.getAllOperands()) {
297+
if (auto *operandInstruction =
298+
operand.get()->getDefiningInstruction()) {
299+
withDebugStream([&](llvm::raw_ostream &stream,
300+
StringRef loggingName) {
301+
stream << loggingName << ": add op " << *operandInstruction << '\n'
302+
<< " from erased inst to worklist\n";
303+
});
304+
add(operandInstruction);
305+
}
306+
}
307+
}
308+
erase(&instruction);
309+
instruction.eraseFromParent();
310+
}
129311
};
130312

131313
// TODO: This name is somewhat unpleasant. Once the type is templated over its

trunk/lib/SILOptimizer/SILCombiner/SILCombine.cpp

Lines changed: 8 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -101,29 +101,6 @@ void SILCombiner::addReachableCodeToWorklist(SILBasicBlock *BB) {
101101
addInitialGroup(InstrsForSILCombineWorklist);
102102
}
103103

104-
static void eraseSingleInstFromFunction(
105-
SILInstruction &I,
106-
SmallSILInstructionWorklist<256> &Worklist,
107-
bool AddOperandsToWorklist) {
108-
LLVM_DEBUG(llvm::dbgs() << "SC: ERASE " << I << '\n');
109-
110-
assert(!I.hasUsesOfAnyResult() && "Cannot erase instruction that is used!");
111-
112-
// Make sure that we reprocess all operands now that we reduced their
113-
// use counts.
114-
if (I.getNumOperands() < 8 && AddOperandsToWorklist) {
115-
for (auto &OpI : I.getAllOperands()) {
116-
if (auto *Op = OpI.get()->getDefiningInstruction()) {
117-
LLVM_DEBUG(llvm::dbgs() << "SC: add op " << *Op
118-
<< " from erased inst to worklist\n");
119-
Worklist.add(Op);
120-
}
121-
}
122-
}
123-
Worklist.erase(&I);
124-
I.eraseFromParent();
125-
}
126-
127104
//===----------------------------------------------------------------------===//
128105
// Implementation
129106
//===----------------------------------------------------------------------===//
@@ -147,8 +124,8 @@ class SILCombineCanonicalize final : CanonicalizeInstruction {
147124
// Just delete the given 'inst' and record its operands. The callback isn't
148125
// allowed to mutate any other instructions.
149126
void killInstruction(SILInstruction *inst) override {
150-
eraseSingleInstFromFunction(*inst, Worklist,
151-
/*AddOperandsToWorklist*/ true);
127+
Worklist.eraseSingleInstFromFunction(*inst,
128+
/*AddOperandsToWorklist*/ true);
152129
changed = true;
153130
}
154131

@@ -216,34 +193,12 @@ bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) {
216193
if (SILInstruction *Result = visit(I)) {
217194
++NumCombined;
218195
// Should we replace the old instruction with a new one?
219-
if (Result != I) {
220-
assert(&*std::prev(SILBasicBlock::iterator(I)) == Result &&
221-
"Expected new instruction inserted before existing instruction!");
222-
223-
LLVM_DEBUG(llvm::dbgs() << "SC: Old = " << *I << '\n'
224-
<< " New = " << *Result << '\n');
225-
226-
// Everything uses the new instruction now.
227-
replaceInstUsesPairwiseWith(I, Result);
228-
229-
// Push the new instruction and any users onto the worklist.
230-
Worklist.add(Result);
231-
Worklist.addUsersOfAllResultsToWorklist(Result);
232-
233-
eraseInstFromFunction(*I);
234-
} else {
235-
LLVM_DEBUG(llvm::dbgs() << "SC: Mod = " << OrigI << '\n'
236-
<< " New = " << *I << '\n');
237-
238-
// If the instruction was modified, it's possible that it is now dead.
239-
// if so, remove it.
240-
if (isInstructionTriviallyDead(I)) {
241-
eraseInstFromFunction(*I);
242-
} else {
243-
Worklist.add(I);
244-
Worklist.addUsersOfAllResultsToWorklist(I);
245-
}
246-
}
196+
Worklist.replaceInstructionWithInstruction(I, Result
197+
#ifndef NDEBUG
198+
,
199+
OrigI
200+
#endif
201+
);
247202
MadeChange = true;
248203
}
249204

@@ -278,88 +233,6 @@ bool SILCombiner::runOnFunction(SILFunction &F) {
278233
return Changed;
279234
}
280235

281-
// Insert the instruction New before instruction Old in Old's parent BB. Add
282-
// New to the worklist.
283-
SILInstruction *SILCombiner::insertNewInstBefore(SILInstruction *New,
284-
SILInstruction &Old) {
285-
assert(New && New->getParent() == nullptr &&
286-
"New instruction already inserted into a basic block!");
287-
SILBasicBlock *BB = Old.getParent();
288-
BB->insert(&Old, New); // Insert inst
289-
Worklist.add(New);
290-
return New;
291-
}
292-
293-
// This method is to be used when an instruction is found to be dead,
294-
// replaceable with another preexisting expression. Here we add all uses of I
295-
// to the worklist, replace all uses of I with the new value, then return I,
296-
// so that the combiner will know that I was modified.
297-
void SILCombiner::replaceInstUsesWith(SingleValueInstruction &I, ValueBase *V) {
298-
Worklist.addUsersToWorklist(&I); // Add all modified instrs to worklist.
299-
300-
LLVM_DEBUG(llvm::dbgs() << "SC: Replacing " << I << "\n"
301-
<< " with " << *V << '\n');
302-
303-
I.replaceAllUsesWith(V);
304-
}
305-
306-
void SILCombiner::replaceValueUsesWith(SILValue oldValue, SILValue newValue) {
307-
Worklist.addUsersToWorklist(oldValue); // Add all modified instrs to worklist.
308-
309-
LLVM_DEBUG(llvm::dbgs() << "SC: Replacing " << oldValue << "\n"
310-
<< " with " << newValue << '\n');
311-
312-
oldValue->replaceAllUsesWith(newValue);
313-
}
314-
315-
/// Replace all of the results of the old instruction with the
316-
/// corresponding results of the new instruction.
317-
void SILCombiner::replaceInstUsesPairwiseWith(SILInstruction *oldI,
318-
SILInstruction *newI) {
319-
LLVM_DEBUG(llvm::dbgs() << "SC: Replacing " << *oldI << "\n"
320-
<< " with " << *newI << '\n');
321-
322-
auto oldResults = oldI->getResults();
323-
auto newResults = newI->getResults();
324-
assert(oldResults.size() == newResults.size());
325-
for (auto i : indices(oldResults)) {
326-
// Add all modified instrs to worklist.
327-
Worklist.addUsersToWorklist(oldResults[i]);
328-
329-
oldResults[i]->replaceAllUsesWith(newResults[i]);
330-
}
331-
}
332-
333-
// Some instructions can never be "trivially dead" due to side effects or
334-
// producing a void value. In those cases, since we cannot rely on
335-
// SILCombines trivially dead instruction DCE in order to delete the
336-
// instruction, visit methods should use this method to delete the given
337-
// instruction and upon completion of their peephole return the value returned
338-
// by this method.
339-
SILInstruction *
340-
SILCombiner::eraseInstFromFunction(SILInstruction &I,
341-
SILBasicBlock::iterator &InstIter,
342-
bool AddOperandsToWorklist) {
343-
// Delete any debug users first.
344-
for (auto result : I.getResults()) {
345-
while (!result->use_empty()) {
346-
auto *user = result->use_begin()->getUser();
347-
assert(user->isDebugInstruction());
348-
if (InstIter == user->getIterator())
349-
++InstIter;
350-
Worklist.erase(user);
351-
user->eraseFromParent();
352-
}
353-
}
354-
if (InstIter == I.getIterator())
355-
++InstIter;
356-
357-
eraseSingleInstFromFunction(I, Worklist, AddOperandsToWorklist);
358-
MadeChange = true;
359-
// Dummy return, so the caller doesn't need to explicitly return nullptr.
360-
return nullptr;
361-
}
362-
363236
//===----------------------------------------------------------------------===//
364237
// Entry Points
365238
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)