Skip to content

Commit 88f1545

Browse files
committed
[mandatory-combiner] Some small cleanups.
Specifically, I split the mandatory combiner class into four different sections: 1. Utility. Small little high level loops that really do not need to be in the combiner class. E.x.: allValuesAreTrivial. 2. Interface. 3. Non-Visitor Implementation. 4. Visitor Implementation. This section will allow this code to grow more naturally and be split eventually into headers and separate implementation files for the visitors and the "utility" functionality that assist the visitors. The visitors part of this code is the natural place where this code will grow as shown by the growth in SILCombine itself. I am doing this in preparation for moving some non-diagnostic transforms from diagnostic constant propagation into this pass.
1 parent dff4c78 commit 88f1545

File tree

1 file changed

+160
-139
lines changed

1 file changed

+160
-139
lines changed

lib/SILOptimizer/Mandatory/MandatoryCombine.cpp

Lines changed: 160 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,23 @@
3939

4040
using namespace swift;
4141

42+
//===----------------------------------------------------------------------===//
43+
// Utility
44+
//===----------------------------------------------------------------------===//
45+
46+
/// \returns whether all the values are of trivial type in the provided
47+
/// function.
48+
template <typename Values>
49+
static bool areAllValuesTrivial(Values values, SILFunction &function) {
50+
return llvm::all_of(values, [&](SILValue value) -> bool {
51+
return value->getType().isTrivial(function);
52+
});
53+
}
54+
55+
//===----------------------------------------------------------------------===//
56+
// MandatoryCombiner Interface
57+
//===----------------------------------------------------------------------===//
58+
4259
namespace {
4360

4461
class MandatoryCombiner final
@@ -71,182 +88,186 @@ class MandatoryCombiner final
7188
[&](SILInstruction *instruction) { worklist.add(instruction); }),
7289
createdInstructions(createdInstructions){};
7390

74-
/// Base visitor that does not do anything.
75-
SILInstruction *visitSILInstruction(SILInstruction *) { return nullptr; }
91+
void addReachableCodeToWorklist(SILFunction &function);
7692

77-
/// \returns whether all the values are of trivial type in the provided
78-
/// function.
79-
template <typename Values>
80-
static bool areAllValuesTrivial(Values values, SILFunction &function) {
81-
return llvm::all_of(values, [&](SILValue value) -> bool {
82-
return value->getType().isTrivial(function);
83-
});
84-
}
93+
/// \return whether a change was made.
94+
bool doOneIteration(SILFunction &function, unsigned iteration);
8595

86-
SILInstruction *visitApplyInst(ApplyInst *instruction) {
87-
// Apply this pass only to partial applies all of whose arguments are
88-
// trivial.
89-
auto calledValue = instruction->getCallee();
90-
if (calledValue == nullptr) {
91-
return nullptr;
92-
}
93-
auto fullApplyCallee = calledValue->getDefiningInstruction();
94-
if (fullApplyCallee == nullptr) {
95-
return nullptr;
96-
}
97-
auto partialApply = dyn_cast<PartialApplyInst>(fullApplyCallee);
98-
if (partialApply == nullptr) {
99-
return nullptr;
100-
}
101-
auto *function = partialApply->getCalleeFunction();
102-
if (function == nullptr) {
103-
return nullptr;
104-
}
105-
ApplySite fullApplySite(instruction);
106-
auto fullApplyArguments = fullApplySite.getArguments();
107-
if (!areAllValuesTrivial(fullApplyArguments, *function)) {
108-
return nullptr;
109-
}
110-
auto partialApplyArguments = ApplySite(partialApply).getArguments();
111-
if (!areAllValuesTrivial(partialApplyArguments, *function)) {
112-
return nullptr;
113-
}
96+
void clear() {
97+
iteration = 0;
98+
worklist.resetChecked();
99+
madeChange = false;
100+
}
114101

115-
auto callee = partialApply->getCallee();
102+
/// Applies the MandatoryCombiner to the provided function.
103+
///
104+
/// \param function the function to which to apply the MandatoryCombiner.
105+
///
106+
/// \return whether a change was made.
107+
bool runOnFunction(SILFunction &function) {
108+
bool changed = false;
116109

117-
ApplySite partialApplySite(partialApply);
110+
while (doOneIteration(function, iteration)) {
111+
changed = true;
112+
++iteration;
113+
}
118114

119-
SmallVector<SILValue, 8> argsVec;
120-
llvm::copy(fullApplyArguments, std::back_inserter(argsVec));
121-
llvm::copy(partialApplyArguments, std::back_inserter(argsVec));
115+
return changed;
116+
}
122117

123-
SILBuilderWithScope builder(instruction, &createdInstructions);
124-
ApplyInst *replacement = builder.createApply(
125-
/*Loc=*/instruction->getDebugLocation().getLocation(), /*Fn=*/callee,
126-
/*Subs=*/partialApply->getSubstitutionMap(),
127-
/*Args*/ argsVec,
128-
/*isNonThrowing=*/instruction->isNonThrowing(),
129-
/*SpecializationInfo=*/partialApply->getSpecializationInfo());
118+
/// Base visitor that does not do anything.
119+
SILInstruction *visitSILInstruction(SILInstruction *) { return nullptr; }
120+
SILInstruction *visitApplyInst(ApplyInst *instruction);
121+
};
130122

131-
worklist.replaceInstructionWithInstruction(instruction, replacement
132-
#ifndef NDEBUG
133-
,
134-
/*instructionDescription=*/""
135-
#endif
136-
);
137-
tryDeleteDeadClosure(partialApply, instModCallbacks);
138-
return nullptr;
139-
}
123+
} // end anonymous namespace
140124

141-
void addReachableCodeToWorklist(SILFunction &function) {
142-
SmallBlotSetVector<SILBasicBlock *, 32> blockWorklist;
143-
SmallBlotSetVector<SILBasicBlock *, 32> blocksVisited;
144-
SmallVector<SILInstruction *, 128> instructions;
125+
//===----------------------------------------------------------------------===//
126+
// MandatoryCombiner Non-Visitor Utility Methods
127+
//===----------------------------------------------------------------------===//
145128

146-
blockWorklist.insert(&*function.begin());
147-
while (!blockWorklist.empty()) {
148-
auto *block = blockWorklist.pop_back_val().getValueOr(nullptr);
149-
if (block == nullptr) {
150-
continue;
151-
}
129+
void MandatoryCombiner::addReachableCodeToWorklist(SILFunction &function) {
130+
SmallBlotSetVector<SILBasicBlock *, 32> blockWorklist;
131+
SmallBlotSetVector<SILBasicBlock *, 32> blocksVisited;
132+
SmallVector<SILInstruction *, 128> instructions;
152133

153-
if (!blocksVisited.insert(block).second) {
154-
continue;
155-
}
134+
blockWorklist.insert(&*function.begin());
135+
while (!blockWorklist.empty()) {
136+
auto *block = blockWorklist.pop_back_val().getValueOr(nullptr);
137+
if (block == nullptr) {
138+
continue;
139+
}
156140

157-
for (auto iterator = block->begin(), end = block->end(); iterator != end;) {
158-
auto *instruction = &*iterator;
159-
++iterator;
141+
if (!blocksVisited.insert(block).second) {
142+
continue;
143+
}
160144

161-
if (isInstructionTriviallyDead(instruction)) {
162-
continue;
163-
}
145+
for (auto iterator = block->begin(), end = block->end(); iterator != end;) {
146+
auto *instruction = &*iterator;
147+
++iterator;
164148

165-
instructions.push_back(instruction);
149+
if (isInstructionTriviallyDead(instruction)) {
150+
continue;
166151
}
167152

168-
for_each(block->getSuccessorBlocks(), [&](SILBasicBlock *block) {
169-
blockWorklist.insert(block);
170-
});
153+
instructions.push_back(instruction);
171154
}
172155

173-
worklist.addInitialGroup(instructions);
156+
for_each(block->getSuccessorBlocks(),
157+
[&](SILBasicBlock *block) { blockWorklist.insert(block); });
174158
}
175159

176-
/// \return whether a change was made.
177-
bool doOneIteration(SILFunction &function, unsigned iteration) {
178-
madeChange = false;
160+
worklist.addInitialGroup(instructions);
161+
}
179162

180-
addReachableCodeToWorklist(function);
163+
bool MandatoryCombiner::doOneIteration(SILFunction &function,
164+
unsigned iteration) {
165+
madeChange = false;
181166

182-
while (!worklist.isEmpty()) {
183-
auto *instruction = worklist.pop_back_val();
184-
if (instruction == nullptr) {
185-
continue;
186-
}
167+
addReachableCodeToWorklist(function);
168+
169+
while (!worklist.isEmpty()) {
170+
auto *instruction = worklist.pop_back_val();
171+
if (instruction == nullptr) {
172+
continue;
173+
}
187174

188175
#ifndef NDEBUG
189-
std::string instructionDescription;
176+
std::string instructionDescription;
190177
#endif
191-
LLVM_DEBUG(llvm::raw_string_ostream SS(instructionDescription);
192-
instruction->print(SS); instructionDescription = SS.str(););
193-
LLVM_DEBUG(llvm::dbgs()
194-
<< "MC: Visiting: " << instructionDescription << '\n');
178+
LLVM_DEBUG(llvm::raw_string_ostream SS(instructionDescription);
179+
instruction->print(SS); instructionDescription = SS.str(););
180+
LLVM_DEBUG(llvm::dbgs()
181+
<< "MC: Visiting: " << instructionDescription << '\n');
195182

196-
if (auto replacement = visit(instruction)) {
197-
worklist.replaceInstructionWithInstruction(instruction, replacement
183+
if (auto replacement = visit(instruction)) {
184+
worklist.replaceInstructionWithInstruction(instruction, replacement
198185
#ifndef NDEBUG
199-
, instructionDescription
186+
,
187+
instructionDescription
200188
#endif
201-
);
202-
}
203-
204-
for (SILInstruction *instruction : instructionsPendingDeletion) {
205-
worklist.eraseInstFromFunction(*instruction);
206-
}
207-
instructionsPendingDeletion.clear();
208-
209-
// Our tracking list has been accumulating instructions created by the
210-
// SILBuilder during this iteration. Go through the tracking list and add
211-
// its contents to the worklist and then clear said list in preparation
212-
// for the next iteration.
213-
for (SILInstruction *instruction : createdInstructions) {
214-
LLVM_DEBUG(llvm::dbgs() << "MC: add " << *instruction
215-
<< " from tracking list to worklist\n");
216-
worklist.add(instruction);
217-
}
218-
createdInstructions.clear();
189+
);
219190
}
220191

221-
worklist.resetChecked();
222-
return madeChange;
192+
for (SILInstruction *instruction : instructionsPendingDeletion) {
193+
worklist.eraseInstFromFunction(*instruction);
194+
}
195+
instructionsPendingDeletion.clear();
196+
197+
// Our tracking list has been accumulating instructions created by the
198+
// SILBuilder during this iteration. Go through the tracking list and add
199+
// its contents to the worklist and then clear said list in preparation
200+
// for the next iteration.
201+
for (SILInstruction *instruction : createdInstructions) {
202+
LLVM_DEBUG(llvm::dbgs() << "MC: add " << *instruction
203+
<< " from tracking list to worklist\n");
204+
worklist.add(instruction);
205+
}
206+
createdInstructions.clear();
223207
}
224208

225-
void clear() {
226-
iteration = 0;
227-
worklist.resetChecked();
228-
madeChange = false;
209+
worklist.resetChecked();
210+
return madeChange;
211+
}
212+
213+
//===----------------------------------------------------------------------===//
214+
// MandatoryCombiner Visitor Methods
215+
//===----------------------------------------------------------------------===//
216+
217+
SILInstruction *MandatoryCombiner::visitApplyInst(ApplyInst *instruction) {
218+
// Apply this pass only to partial applies all of whose arguments are
219+
// trivial.
220+
auto calledValue = instruction->getCallee();
221+
if (calledValue == nullptr) {
222+
return nullptr;
223+
}
224+
auto fullApplyCallee = calledValue->getDefiningInstruction();
225+
if (fullApplyCallee == nullptr) {
226+
return nullptr;
227+
}
228+
auto partialApply = dyn_cast<PartialApplyInst>(fullApplyCallee);
229+
if (partialApply == nullptr) {
230+
return nullptr;
231+
}
232+
auto *function = partialApply->getCalleeFunction();
233+
if (function == nullptr) {
234+
return nullptr;
235+
}
236+
ApplySite fullApplySite(instruction);
237+
auto fullApplyArguments = fullApplySite.getArguments();
238+
if (!areAllValuesTrivial(fullApplyArguments, *function)) {
239+
return nullptr;
240+
}
241+
auto partialApplyArguments = ApplySite(partialApply).getArguments();
242+
if (!areAllValuesTrivial(partialApplyArguments, *function)) {
243+
return nullptr;
229244
}
230245

246+
auto callee = partialApply->getCallee();
231247

232-
/// Applies the MandatoryCombiner to the provided function.
233-
///
234-
/// \param function the function to which to apply the MandatoryCombiner.
235-
///
236-
/// \return whether a change was made.
237-
bool runOnFunction(SILFunction &function) {
238-
bool changed = false;
248+
ApplySite partialApplySite(partialApply);
239249

240-
while (doOneIteration(function, iteration)) {
241-
changed = true;
242-
++iteration;
243-
}
250+
SmallVector<SILValue, 8> argsVec;
251+
llvm::copy(fullApplyArguments, std::back_inserter(argsVec));
252+
llvm::copy(partialApplyArguments, std::back_inserter(argsVec));
244253

245-
return changed;
246-
}
247-
};
254+
SILBuilderWithScope builder(instruction, &createdInstructions);
255+
ApplyInst *replacement = builder.createApply(
256+
/*Loc=*/instruction->getDebugLocation().getLocation(), /*Fn=*/callee,
257+
/*Subs=*/partialApply->getSubstitutionMap(),
258+
/*Args*/ argsVec,
259+
/*isNonThrowing=*/instruction->isNonThrowing(),
260+
/*SpecializationInfo=*/partialApply->getSpecializationInfo());
248261

249-
} // end anonymous namespace
262+
worklist.replaceInstructionWithInstruction(instruction, replacement
263+
#ifndef NDEBUG
264+
,
265+
/*instructionDescription=*/""
266+
#endif
267+
);
268+
tryDeleteDeadClosure(partialApply, instModCallbacks);
269+
return nullptr;
270+
}
250271

251272
//===----------------------------------------------------------------------===//
252273
// Top Level Entrypoint

0 commit comments

Comments
 (0)