-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[Utils] Consolidate LockstepReverseIterator into own header (NFC)
#116657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,160 @@ | ||||||||
| //===- LockstepReverseIterator.h ------------------------------*- C++ -*---===// | ||||||||
| // | ||||||||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||||||
| // See https://llvm.org/LICENSE.txt for license information. | ||||||||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||||||
| // | ||||||||
| //===----------------------------------------------------------------------===// | ||||||||
|
|
||||||||
| #ifndef LLVM_TRANSFORMS_UTILS_LOCKSTEPREVERSEITERATOR_H | ||||||||
| #define LLVM_TRANSFORMS_UTILS_LOCKSTEPREVERSEITERATOR_H | ||||||||
|
|
||||||||
| #include "llvm/ADT/ArrayRef.h" | ||||||||
| #include "llvm/ADT/SetVector.h" | ||||||||
| #include "llvm/ADT/SmallVector.h" | ||||||||
| #include "llvm/IR/BasicBlock.h" | ||||||||
| #include "llvm/IR/Instruction.h" | ||||||||
|
|
||||||||
| namespace llvm { | ||||||||
|
|
||||||||
| struct NoActiveBlocksOption { | ||||||||
| template <typename... Args> NoActiveBlocksOption(Args...) {} | ||||||||
| }; | ||||||||
|
|
||||||||
| struct ActiveBlocksOption { | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather favour
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW https://llvm.org/docs/CodingStandards.html#use-of-class-and-struct-keywords says to use struct when all members are public, which isn't the case here |
||||||||
| protected: | ||||||||
| SmallSetVector<BasicBlock *, 4> ActiveBlocks; | ||||||||
|
|
||||||||
| public: | ||||||||
| ActiveBlocksOption() = default; | ||||||||
| }; | ||||||||
|
|
||||||||
| /// Iterates through instructions in a set of blocks in reverse order from the | ||||||||
| /// first non-terminator. For example (assume all blocks have size n): | ||||||||
| /// LockstepReverseIterator I([B1, B2, B3]); | ||||||||
| /// *I-- = [B1[n], B2[n], B3[n]]; | ||||||||
| /// *I-- = [B1[n-1], B2[n-1], B3[n-1]]; | ||||||||
| /// *I-- = [B1[n-2], B2[n-2], B3[n-2]]; | ||||||||
| /// ... | ||||||||
| /// | ||||||||
| /// The iterator continues processing until all blocks have been exhausted if \p | ||||||||
| /// EarlyFailure is explicitly set to \c false. Use \c getActiveBlocks() to | ||||||||
| /// determine which blocks are still going and the order they appear in the list | ||||||||
| /// returned by operator*. | ||||||||
| template <bool EarlyFailure = true> | ||||||||
| class LockstepReverseIterator | ||||||||
| : public std::conditional_t<EarlyFailure, NoActiveBlocksOption, | ||||||||
| ActiveBlocksOption> { | ||||||||
|
||||||||
| private: | ||||||||
| using BasicBlockT = BasicBlock; | ||||||||
dtcxzyw marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||
| using InstructionT = Instruction; | ||||||||
|
|
||||||||
| ArrayRef<BasicBlockT *> Blocks; | ||||||||
| SmallVector<InstructionT *, 4> Insts; | ||||||||
| bool Fail; | ||||||||
|
|
||||||||
| public: | ||||||||
| LockstepReverseIterator(ArrayRef<BasicBlockT *> Blocks) : Blocks(Blocks) { | ||||||||
| reset(); | ||||||||
| } | ||||||||
|
|
||||||||
| void reset() { | ||||||||
| Fail = false; | ||||||||
| if constexpr (!EarlyFailure) { | ||||||||
| this->ActiveBlocks.clear(); | ||||||||
| for (BasicBlockT *BB : Blocks) | ||||||||
| this->ActiveBlocks.insert(BB); | ||||||||
| } | ||||||||
| Insts.clear(); | ||||||||
| for (BasicBlockT *BB : Blocks) { | ||||||||
| InstructionT *Prev = BB->getTerminator()->getPrevNonDebugInstruction(); | ||||||||
| if (!Prev) { | ||||||||
| // Block wasn't big enough - only contained a terminator. | ||||||||
| if constexpr (EarlyFailure) { | ||||||||
| Fail = true; | ||||||||
| return; | ||||||||
| } else { | ||||||||
| this->ActiveBlocks.remove(BB); | ||||||||
| continue; | ||||||||
| } | ||||||||
| } | ||||||||
| Insts.push_back(Prev); | ||||||||
| } | ||||||||
| if (Insts.empty()) | ||||||||
| Fail = true; | ||||||||
| } | ||||||||
|
|
||||||||
| bool isValid() const { return !Fail; } | ||||||||
| ArrayRef<InstructionT *> operator*() const { return Insts; } | ||||||||
|
|
||||||||
| // Note: This needs to return a SmallSetVector as the elements of | ||||||||
| // ActiveBlocks will be later copied to Blocks using std::copy. The | ||||||||
| // resultant order of elements in Blocks needs to be deterministic. | ||||||||
| // Using SmallPtrSet instead causes non-deterministic order while | ||||||||
| // copying. And we cannot simply sort Blocks as they need to match the | ||||||||
| // corresponding Values. | ||||||||
| template <bool C = EarlyFailure, std::enable_if_t<!C, int> = 0> | ||||||||
dtcxzyw marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||
| SmallSetVector<BasicBlockT *, 4> &getActiveBlocks() { | ||||||||
| return this->ActiveBlocks; | ||||||||
| } | ||||||||
|
|
||||||||
| template <bool C = EarlyFailure, std::enable_if_t<!C, int> = 0> | ||||||||
| void restrictToBlocks(SmallSetVector<BasicBlockT *, 4> &Blocks) { | ||||||||
| for (auto It = Insts.begin(); It != Insts.end();) { | ||||||||
| if (!Blocks.contains((*It)->getParent())) { | ||||||||
| this->ActiveBlocks.remove((*It)->getParent()); | ||||||||
| It = Insts.erase(It); | ||||||||
| } else { | ||||||||
| ++It; | ||||||||
| } | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| void operator--() { | ||||||||
|
||||||||
| if (Fail) | ||||||||
| return; | ||||||||
| SmallVector<InstructionT *, 4> NewInsts; | ||||||||
| for (InstructionT *Inst : Insts) { | ||||||||
| InstructionT *Prev = Inst->getPrevNonDebugInstruction(); | ||||||||
| if (!Prev) { | ||||||||
| if constexpr (!EarlyFailure) { | ||||||||
| this->ActiveBlocks.remove(Inst->getParent()); | ||||||||
| } else { | ||||||||
| Fail = true; | ||||||||
| return; | ||||||||
| } | ||||||||
| } else { | ||||||||
| NewInsts.push_back(Prev); | ||||||||
| } | ||||||||
| } | ||||||||
| if (NewInsts.empty()) { | ||||||||
| Fail = true; | ||||||||
| return; | ||||||||
| } | ||||||||
| Insts = NewInsts; | ||||||||
| } | ||||||||
|
|
||||||||
| void operator++() { | ||||||||
|
||||||||
| void operator++() { | |
| void operator++() { | |
| static_assert(!EarlyFailure, "Unknown method"); |
This method does not maintain the set of active blocks.
Uh oh!
There was an error while loading. Please reload this page.