|
65 | 65 | #include "llvm/Transforms/Scalar/GVNExpression.h" |
66 | 66 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" |
67 | 67 | #include "llvm/Transforms/Utils/Local.h" |
| 68 | +#include "llvm/Transforms/Utils/LockstepReverseIterator.h" |
68 | 69 | #include <cassert> |
69 | 70 | #include <cstddef> |
70 | 71 | #include <cstdint> |
@@ -96,87 +97,6 @@ static bool isMemoryInst(const Instruction *I) { |
96 | 97 | (isa<CallInst>(I) && !cast<CallInst>(I)->doesNotAccessMemory()); |
97 | 98 | } |
98 | 99 |
|
99 | | -/// Iterates through instructions in a set of blocks in reverse order from the |
100 | | -/// first non-terminator. For example (assume all blocks have size n): |
101 | | -/// LockstepReverseIterator I([B1, B2, B3]); |
102 | | -/// *I-- = [B1[n], B2[n], B3[n]]; |
103 | | -/// *I-- = [B1[n-1], B2[n-1], B3[n-1]]; |
104 | | -/// *I-- = [B1[n-2], B2[n-2], B3[n-2]]; |
105 | | -/// ... |
106 | | -/// |
107 | | -/// It continues until all blocks have been exhausted. Use \c getActiveBlocks() |
108 | | -/// to |
109 | | -/// determine which blocks are still going and the order they appear in the |
110 | | -/// list returned by operator*. |
111 | | -class LockstepReverseIterator { |
112 | | - ArrayRef<BasicBlock *> Blocks; |
113 | | - SmallSetVector<BasicBlock *, 4> ActiveBlocks; |
114 | | - SmallVector<Instruction *, 4> Insts; |
115 | | - bool Fail; |
116 | | - |
117 | | -public: |
118 | | - LockstepReverseIterator(ArrayRef<BasicBlock *> Blocks) : Blocks(Blocks) { |
119 | | - reset(); |
120 | | - } |
121 | | - |
122 | | - void reset() { |
123 | | - Fail = false; |
124 | | - ActiveBlocks.clear(); |
125 | | - for (BasicBlock *BB : Blocks) |
126 | | - ActiveBlocks.insert(BB); |
127 | | - Insts.clear(); |
128 | | - for (BasicBlock *BB : Blocks) { |
129 | | - if (BB->size() <= 1) { |
130 | | - // Block wasn't big enough - only contained a terminator. |
131 | | - ActiveBlocks.remove(BB); |
132 | | - continue; |
133 | | - } |
134 | | - Insts.push_back(BB->getTerminator()->getPrevNonDebugInstruction()); |
135 | | - } |
136 | | - if (Insts.empty()) |
137 | | - Fail = true; |
138 | | - } |
139 | | - |
140 | | - bool isValid() const { return !Fail; } |
141 | | - ArrayRef<Instruction *> operator*() const { return Insts; } |
142 | | - |
143 | | - // Note: This needs to return a SmallSetVector as the elements of |
144 | | - // ActiveBlocks will be later copied to Blocks using std::copy. The |
145 | | - // resultant order of elements in Blocks needs to be deterministic. |
146 | | - // Using SmallPtrSet instead causes non-deterministic order while |
147 | | - // copying. And we cannot simply sort Blocks as they need to match the |
148 | | - // corresponding Values. |
149 | | - SmallSetVector<BasicBlock *, 4> &getActiveBlocks() { return ActiveBlocks; } |
150 | | - |
151 | | - void restrictToBlocks(SmallSetVector<BasicBlock *, 4> &Blocks) { |
152 | | - for (auto II = Insts.begin(); II != Insts.end();) { |
153 | | - if (!Blocks.contains((*II)->getParent())) { |
154 | | - ActiveBlocks.remove((*II)->getParent()); |
155 | | - II = Insts.erase(II); |
156 | | - } else { |
157 | | - ++II; |
158 | | - } |
159 | | - } |
160 | | - } |
161 | | - |
162 | | - void operator--() { |
163 | | - if (Fail) |
164 | | - return; |
165 | | - SmallVector<Instruction *, 4> NewInsts; |
166 | | - for (auto *Inst : Insts) { |
167 | | - if (Inst == &Inst->getParent()->front()) |
168 | | - ActiveBlocks.remove(Inst->getParent()); |
169 | | - else |
170 | | - NewInsts.push_back(Inst->getPrevNonDebugInstruction()); |
171 | | - } |
172 | | - if (NewInsts.empty()) { |
173 | | - Fail = true; |
174 | | - return; |
175 | | - } |
176 | | - Insts = NewInsts; |
177 | | - } |
178 | | -}; |
179 | | - |
180 | 100 | //===----------------------------------------------------------------------===// |
181 | 101 |
|
182 | 102 | /// Candidate solution for sinking. There may be different ways to |
@@ -634,9 +554,11 @@ class GVNSink { |
634 | 554 | /// The main heuristic function. Analyze the set of instructions pointed to by |
635 | 555 | /// LRI and return a candidate solution if these instructions can be sunk, or |
636 | 556 | /// std::nullopt otherwise. |
637 | | - std::optional<SinkingInstructionCandidate> analyzeInstructionForSinking( |
638 | | - LockstepReverseIterator &LRI, unsigned &InstNum, unsigned &MemoryInstNum, |
639 | | - ModelledPHISet &NeededPHIs, SmallPtrSetImpl<Value *> &PHIContents); |
| 557 | + std::optional<SinkingInstructionCandidate> |
| 558 | + analyzeInstructionForSinking(LockstepReverseIterator<false> &LRI, |
| 559 | + unsigned &InstNum, unsigned &MemoryInstNum, |
| 560 | + ModelledPHISet &NeededPHIs, |
| 561 | + SmallPtrSetImpl<Value *> &PHIContents); |
640 | 562 |
|
641 | 563 | /// Create a ModelledPHI for each PHI in BB, adding to PHIs. |
642 | 564 | void analyzeInitialPHIs(BasicBlock *BB, ModelledPHISet &PHIs, |
@@ -675,7 +597,7 @@ class GVNSink { |
675 | 597 | }; |
676 | 598 |
|
677 | 599 | std::optional<SinkingInstructionCandidate> |
678 | | -GVNSink::analyzeInstructionForSinking(LockstepReverseIterator &LRI, |
| 600 | +GVNSink::analyzeInstructionForSinking(LockstepReverseIterator<false> &LRI, |
679 | 601 | unsigned &InstNum, |
680 | 602 | unsigned &MemoryInstNum, |
681 | 603 | ModelledPHISet &NeededPHIs, |
@@ -827,7 +749,7 @@ unsigned GVNSink::sinkBB(BasicBlock *BBEnd) { |
827 | 749 | return BB->getTerminator()->getNumSuccessors() != 1; |
828 | 750 | }); |
829 | 751 |
|
830 | | - LockstepReverseIterator LRI(Preds); |
| 752 | + LockstepReverseIterator<false> LRI(Preds); |
831 | 753 | SmallVector<SinkingInstructionCandidate, 4> Candidates; |
832 | 754 | unsigned InstNum = 0, MemoryInstNum = 0; |
833 | 755 | ModelledPHISet NeededPHIs; |
|
0 commit comments