Skip to content

Commit 4968dcc

Browse files
committed
[SIL] Took SILInstructionWorklist from SILCombine.
SILCombine had a dedicated worklist type that is generally useful. Here that type is extracted into SIL as SILInstructionWorklist so that it can be reused. Minor style changes were made as well.
1 parent 88f8592 commit 4968dcc

File tree

3 files changed

+154
-0
lines changed

3 files changed

+154
-0
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+
}

0 commit comments

Comments
 (0)