Skip to content

Commit

Permalink
[FixIrreducible] Use CycleInfo instead of a custom SCC traversal (llv…
Browse files Browse the repository at this point in the history
…m#101386)

[FixIrreducible] Use CycleInfo instead of a custom SCC traversal

1. CycleInfo efficiently locates all cycles in a single pass, while the
SCC is
   repeated inside every natural loop.

2. CycleInfo provides a hierarchy of irreducible cycles, and the new
implementation transforms each cycle in this hierarchy separately
instead of
reducing an entire irreducible SCC in a single step. This reduces the
number
of control-flow paths that pass through the header of each newly created
loop. This is evidenced by the reduced number of predecessors on the
"guard"
blocks in the lit tests, and fewer operands on the corresponding PHI
nodes.

3. When an entry of an irreducible cycle is the header of a child
natural loop,
the original implementation destroyed that loop. This is now preserved,
   since the incoming edges on non-header entries are not touched.

4. In the new implementation, if an irreducible cycle is a superset of a
natural
loop with the same header, then that natural loop is destroyed and
replaced
   by the newly created loop.
  • Loading branch information
ssahasra committed Aug 26, 2024
1 parent 4549a8d commit fa4cc9d
Show file tree
Hide file tree
Showing 10 changed files with 545 additions and 394 deletions.
28 changes: 20 additions & 8 deletions llvm/include/llvm/ADT/GenericCycleInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ template <typename ContextT> class GenericCycle {
return is_contained(Entries, Block);
}

/// \brief Replace all entries with \p Block as single entry.
void setSingleEntry(BlockT *Block) {
assert(contains(Block));
Entries.clear();
Entries.push_back(Block);
}

/// \brief Return whether \p Block is contained in the cycle.
bool contains(const BlockT *Block) const { return Blocks.contains(Block); }

Expand Down Expand Up @@ -192,11 +199,16 @@ template <typename ContextT> class GenericCycle {
//@{
using const_entry_iterator =
typename SmallVectorImpl<BlockT *>::const_iterator;

const_entry_iterator entry_begin() const { return Entries.begin(); }
const_entry_iterator entry_end() const { return Entries.end(); }
size_t getNumEntries() const { return Entries.size(); }
iterator_range<const_entry_iterator> entries() const {
return llvm::make_range(Entries.begin(), Entries.end());
return llvm::make_range(entry_begin(), entry_end());
}
using const_reverse_entry_iterator =
typename SmallVectorImpl<BlockT *>::const_reverse_iterator;
const_reverse_entry_iterator entry_rbegin() const { return Entries.rbegin(); }
const_reverse_entry_iterator entry_rend() const { return Entries.rend(); }
//@}

Printable printEntries(const ContextT &Ctx) const {
Expand Down Expand Up @@ -255,12 +267,6 @@ template <typename ContextT> class GenericCycleInfo {
/// the subtree.
void moveTopLevelCycleToNewParent(CycleT *NewParent, CycleT *Child);

/// Assumes that \p Cycle is the innermost cycle containing \p Block.
/// \p Block will be appended to \p Cycle and all of its parent cycles.
/// \p Block will be added to BlockMap with \p Cycle and
/// BlockMapTopLevel with \p Cycle's top level parent cycle.
void addBlockToCycle(BlockT *Block, CycleT *Cycle);

public:
GenericCycleInfo() = default;
GenericCycleInfo(GenericCycleInfo &&) = default;
Expand All @@ -278,6 +284,12 @@ template <typename ContextT> class GenericCycleInfo {
unsigned getCycleDepth(const BlockT *Block) const;
CycleT *getTopLevelParentCycle(BlockT *Block);

/// Assumes that \p Cycle is the innermost cycle containing \p Block.
/// \p Block will be appended to \p Cycle and all of its parent cycles.
/// \p Block will be added to BlockMap with \p Cycle and
/// BlockMapTopLevel with \p Cycle's top level parent cycle.
void addBlockToCycle(BlockT *Block, CycleT *Cycle);

/// Methods for debug and self-test.
//@{
void verifyCycleNest(bool VerifyFull = false) const;
Expand Down
Loading

0 comments on commit fa4cc9d

Please sign in to comment.