Skip to content

Commit c8a4125

Browse files
authored
Merge pull request #27020 from nate-chandler/instruction-worklist
2 parents bf6f046 + 1eacf8b commit c8a4125

File tree

5 files changed

+160
-105
lines changed

5 files changed

+160
-105
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//===--- SILInstructionWorklist.h -------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 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+
/// \file
14+
///
15+
/// When visiting the instructions in a function/basic block, one often modifies
16+
/// the list of instructions to be visited. That fact introduces complexity in
17+
/// the form of ensuring that no effort is wasted moving items down in the list
18+
/// when an item is removed from it and also in the form of ensuring that no
19+
/// instructions which have been modified/deleted are visited.
20+
///
21+
/// The SILInstructionWorklist manages that complexity. It is responsible for
22+
/// ensuring that removing an instruction is not unnecessarily expensive and
23+
/// that only valid instructions are removed from the list.
24+
///
25+
//===----------------------------------------------------------------------===//
26+
27+
#include "swift/SIL/SILInstruction.h"
28+
#include "swift/SIL/SILValue.h"
29+
#include "llvm/ADT/DenseMap.h"
30+
#include "llvm/ADT/SmallVector.h"
31+
32+
namespace swift {
33+
34+
/// Manages a list of instructions awaiting visitation.
35+
class SILInstructionWorklist final {
36+
llvm::SmallVector<SILInstruction *, 256> worklist;
37+
llvm::DenseMap<SILInstruction *, unsigned> worklistMap;
38+
StringRef loggingName;
39+
40+
void operator=(const SILInstructionWorklist &rhs) = delete;
41+
SILInstructionWorklist(const SILInstructionWorklist &worklist) = delete;
42+
43+
public:
44+
SILInstructionWorklist(const char *loggingName = "InstructionWorklist")
45+
: loggingName(loggingName) {}
46+
47+
/// Returns true if the worklist is empty.
48+
bool isEmpty() const { return worklist.empty(); }
49+
50+
/// Add the specified instruction to the worklist if it isn't already in it.
51+
void add(SILInstruction *instruction);
52+
53+
/// If the given ValueBase is a SILInstruction add it to the worklist.
54+
void addValue(ValueBase *value) {
55+
if (auto *instruction = value->getDefiningInstruction())
56+
add(instruction);
57+
}
58+
59+
/// Add the given list of instructions in reverse order to the worklist. This
60+
/// routine assumes that the worklist is empty and the given list has no
61+
/// duplicates.
62+
void addInitialGroup(ArrayRef<SILInstruction *> list);
63+
64+
// If instruction is in the worklist, remove it.
65+
void remove(SILInstruction *instruction) {
66+
auto iterator = worklistMap.find(instruction);
67+
if (iterator == worklistMap.end())
68+
return; // Not in worklist.
69+
70+
// Don't bother moving everything down, just null out the slot. We will
71+
// check before we process any instruction if it is null.
72+
worklist[iterator->second] = nullptr;
73+
worklistMap.erase(iterator);
74+
}
75+
76+
/// Remove the top element from the worklist.
77+
SILInstruction *removeOne() {
78+
SILInstruction *instruction = worklist.pop_back_val();
79+
worklistMap.erase(instruction);
80+
return instruction;
81+
}
82+
83+
/// When an instruction has been simplified, add all of its users to the
84+
/// worklist, since additional simplifications of its users may have been
85+
/// exposed.
86+
void addUsersToWorklist(ValueBase *instruction) {
87+
for (auto *use : instruction->getUses())
88+
add(use->getUser());
89+
}
90+
91+
void addUsersToWorklist(SILValue value) {
92+
for (auto *use : value->getUses())
93+
add(use->getUser());
94+
}
95+
96+
/// When an instruction has been simplified, add all of its users to the
97+
/// worklist, since additional simplifications of its users may have been
98+
/// exposed.
99+
void addUsersOfAllResultsToWorklist(SILInstruction *instruction) {
100+
for (auto result : instruction->getResults()) {
101+
addUsersToWorklist(result);
102+
}
103+
}
104+
105+
/// Check that the worklist is empty and nuke the backing store for the map if
106+
/// it is large.
107+
void zap() {
108+
assert(worklistMap.empty() && "Worklist empty, but the map is not?");
109+
110+
// Do an explicit clear, this shrinks the map if needed.
111+
worklistMap.clear();
112+
}
113+
};
114+
115+
} // end namespace swift

lib/SIL/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ add_swift_host_library(swiftSIL STATIC
3131
SILGlobalVariable.cpp
3232
SILInstruction.cpp
3333
SILInstructions.cpp
34+
SILInstructionWorklist.cpp
3435
SILLocation.cpp
3536
SILModule.cpp
3637
SILFunctionBuilder.cpp

lib/SIL/SILInstructionWorklist.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===--- SILInstructionWorklist.cpp ---------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 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+
#define DEBUG_TYPE "sil-instruction-worklist"
14+
#include "swift/SIL/SILInstructionWorklist.h"
15+
16+
using namespace swift;
17+
18+
void SILInstructionWorklist::add(SILInstruction *instruction) {
19+
if (!worklistMap.insert(std::make_pair(instruction, worklist.size())).second)
20+
return;
21+
22+
LLVM_DEBUG(llvm::dbgs() << loggingName << ": ADD: " << *instruction << '\n');
23+
worklist.push_back(instruction);
24+
}
25+
26+
void SILInstructionWorklist::addInitialGroup(ArrayRef<SILInstruction *> list) {
27+
assert(worklist.empty() && "worklist must be empty to add initial group");
28+
worklist.reserve(list.size() + 16);
29+
worklistMap.reserve(list.size());
30+
LLVM_DEBUG(llvm::dbgs() << loggingName << ": ADDING: " << list.size()
31+
<< " instrs to worklist\n");
32+
while (!list.empty()) {
33+
SILInstruction *instruction = list.back();
34+
list = list.slice(0, list.size() - 1);
35+
worklistMap.insert(std::make_pair(instruction, worklist.size()));
36+
worklist.push_back(instruction);
37+
}
38+
}

lib/SILOptimizer/SILCombiner/SILCombine.cpp

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void SILCombiner::addReachableCodeToWorklist(SILBasicBlock *BB) {
102102
}
103103

104104
static void eraseSingleInstFromFunction(SILInstruction &I,
105-
SILCombineWorklist &Worklist,
105+
SILInstructionWorklist &Worklist,
106106
bool AddOperandsToWorklist) {
107107
LLVM_DEBUG(llvm::dbgs() << "SC: ERASE " << I << '\n');
108108

@@ -127,21 +127,13 @@ static void eraseSingleInstFromFunction(SILInstruction &I,
127127
// Implementation
128128
//===----------------------------------------------------------------------===//
129129

130-
void SILCombineWorklist::add(SILInstruction *I) {
131-
if (!WorklistMap.insert(std::make_pair(I, Worklist.size())).second)
132-
return;
133-
134-
LLVM_DEBUG(llvm::dbgs() << "SC: ADD: " << *I << '\n');
135-
Worklist.push_back(I);
136-
}
137-
138130
// Define a CanonicalizeInstruction subclass for use in SILCombine.
139131
class SILCombineCanonicalize final : CanonicalizeInstruction {
140-
SILCombineWorklist &Worklist;
132+
SILInstructionWorklist &Worklist;
141133
bool changed = false;
142134

143135
public:
144-
SILCombineCanonicalize(SILCombineWorklist &Worklist)
136+
SILCombineCanonicalize(SILInstructionWorklist &Worklist)
145137
: CanonicalizeInstruction(DEBUG_TYPE), Worklist(Worklist) {}
146138

147139
void notifyNewInstruction(SILInstruction *inst) override {
@@ -270,20 +262,6 @@ bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) {
270262
return MadeChange;
271263
}
272264

273-
void SILCombineWorklist::addInitialGroup(ArrayRef<SILInstruction *> List) {
274-
assert(Worklist.empty() && "Worklist must be empty to add initial group");
275-
Worklist.reserve(List.size()+16);
276-
WorklistMap.reserve(List.size());
277-
LLVM_DEBUG(llvm::dbgs() << "SC: ADDING: " << List.size()
278-
<< " instrs to worklist\n");
279-
while (!List.empty()) {
280-
SILInstruction *I = List.back();
281-
List = List.slice(0, List.size()-1);
282-
WorklistMap.insert(std::make_pair(I, Worklist.size()));
283-
Worklist.push_back(I);
284-
}
285-
}
286-
287265
bool SILCombiner::runOnFunction(SILFunction &F) {
288266
clear();
289267

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 3 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "swift/SIL/SILBuilder.h"
2525
#include "swift/SIL/SILInstruction.h"
26+
#include "swift/SIL/SILInstructionWorklist.h"
2627
#include "swift/SIL/SILValue.h"
2728
#include "swift/SIL/SILVisitor.h"
2829
#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h"
@@ -37,84 +38,6 @@ namespace swift {
3738

3839
class AliasAnalysis;
3940

40-
/// This is the worklist management logic for SILCombine.
41-
class SILCombineWorklist {
42-
llvm::SmallVector<SILInstruction *, 256> Worklist;
43-
llvm::DenseMap<SILInstruction *, unsigned> WorklistMap;
44-
45-
void operator=(const SILCombineWorklist &RHS) = delete;
46-
SILCombineWorklist(const SILCombineWorklist &Worklist) = delete;
47-
public:
48-
SILCombineWorklist() {}
49-
50-
/// Returns true if the worklist is empty.
51-
bool isEmpty() const { return Worklist.empty(); }
52-
53-
/// Add the specified instruction to the worklist if it isn't already in it.
54-
void add(SILInstruction *I);
55-
56-
/// If the given ValueBase is a SILInstruction add it to the worklist.
57-
void addValue(ValueBase *V) {
58-
if (auto *I = V->getDefiningInstruction())
59-
add(I);
60-
}
61-
62-
/// Add the given list of instructions in reverse order to the worklist. This
63-
/// routine assumes that the worklist is empty and the given list has no
64-
/// duplicates.
65-
void addInitialGroup(ArrayRef<SILInstruction *> List);
66-
67-
// If I is in the worklist, remove it.
68-
void remove(SILInstruction *I) {
69-
auto It = WorklistMap.find(I);
70-
if (It == WorklistMap.end())
71-
return; // Not in worklist.
72-
73-
// Don't bother moving everything down, just null out the slot. We will
74-
// check before we process any instruction if it is null.
75-
Worklist[It->second] = nullptr;
76-
WorklistMap.erase(It);
77-
}
78-
79-
/// Remove the top element from the worklist.
80-
SILInstruction *removeOne() {
81-
SILInstruction *I = Worklist.pop_back_val();
82-
WorklistMap.erase(I);
83-
return I;
84-
}
85-
86-
/// When an instruction has been simplified, add all of its users to the
87-
/// worklist, since additional simplifications of its users may have been
88-
/// exposed.
89-
void addUsersToWorklist(ValueBase *I) {
90-
for (auto UI : I->getUses())
91-
add(UI->getUser());
92-
}
93-
94-
void addUsersToWorklist(SILValue value) {
95-
for (auto *use : value->getUses())
96-
add(use->getUser());
97-
}
98-
99-
/// When an instruction has been simplified, add all of its users to the
100-
/// worklist, since additional simplifications of its users may have been
101-
/// exposed.
102-
void addUsersOfAllResultsToWorklist(SILInstruction *I) {
103-
for (auto result : I->getResults()) {
104-
addUsersToWorklist(result);
105-
}
106-
}
107-
108-
/// Check that the worklist is empty and nuke the backing store for the map if
109-
/// it is large.
110-
void zap() {
111-
assert(WorklistMap.empty() && "Worklist empty, but the map is not?");
112-
113-
// Do an explicit clear, this shrinks the map if needed.
114-
WorklistMap.clear();
115-
}
116-
};
117-
11841
/// This is a class which maintains the state of the combiner and simplifies
11942
/// many operations such as removing/adding instructions and syncing them with
12043
/// the worklist.
@@ -134,7 +57,7 @@ class SILCombiner :
13457
ClassHierarchyAnalysis *CHA;
13558

13659
/// Worklist containing all of the instructions primed for simplification.
137-
SILCombineWorklist Worklist;
60+
SILInstructionWorklist Worklist;
13861

13962
/// Variable to track if the SILCombiner made any changes.
14063
bool MadeChange;
@@ -156,7 +79,7 @@ class SILCombiner :
15679
AliasAnalysis *AA, DominanceAnalysis *DA,
15780
ProtocolConformanceAnalysis *PCA, ClassHierarchyAnalysis *CHA,
15881
bool removeCondFails)
159-
: AA(AA), DA(DA), PCA(PCA), CHA(CHA), Worklist(), MadeChange(false),
82+
: AA(AA), DA(DA), PCA(PCA), CHA(CHA), Worklist("SC"), MadeChange(false),
16083
RemoveCondFails(removeCondFails), Iteration(0), Builder(B),
16184
CastOpt(FuncBuilder, nullptr /*SILBuilderContext*/,
16285
/* ReplaceValueUsesAction */

0 commit comments

Comments
 (0)