|
| 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 |
0 commit comments