[PATCH] D74691: [Attributor] Detect possibly unbounded cycles in functions

Stefanos Baziotis via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 25 10:09:40 PST 2020


baziotis added a comment.

> Edit: I'll come back with how we can make maxTripCount fit into this.

So, I'm back. Before continuing, please tell me if everything in this algorithm was clear.
If there are any questions, please ask. So, this algorithm should be strictly better
than the original but still we haven't used LoopInfo and SCEV.

Here's another quick version that I think does that. Btw, please don't code anything //yet//
because especially after my last mistake I want to be extra sure that what I propose
is totally correct. Here we go:

Ok, in the version I posted above, in the `else if`, where we check if the successor is
already visited, if it is true, we just found a cycle. But, how do we check
whether this cycle is a loop or not? One way is to `getLoopFor()` for a node of
the cycle and if we //do get// a `Loop` back, check if the size of the loop with the size
of the cycle is the same. If yes, it is a loop, specifically the one we got. This is a little
subtle, so to understand this, think that a loop is always a SCC (same for the cycle). Now,
2 SCCs are either completely disjoint (no common node) or they make one big SCC.
Since the loop and the cycle do have one common node (the one we used in `getLoopFor()`),
they are in the same SCC. So, if the cycle and the loop have the same number of nodes,
then they're the same thing.
But, how do we get the number of nodes?
Well, in the `else if`, where we find a cycle, one start of the cycle is
`SuccBB`. The thing is, going up the recursion, we have already seen this
node (that's why it's visited). So, going down the recursion (i.e. returning)
we're going to see it again. If we save what is this starting node and count
how many nodes we go down until we find it again, this is the size of the cycle.
The code looks something like this:

  static SmallPtrSet<BasicBlock *, 32> *Visited;
  static SmallPtrSet<BasicBlock *, 32> *Processed;
  static BasicBlock *StartBB;
  static unsigned BBCount;
  bool containsCycleUtil(BasicBlock *BB) {
    if (Processed->count(BB)) {
      Visited->erase(BB);
      return false;
    }
    Processed->insert(BB);
    Visited->insert(BB);
    for (auto *SuccBB : successors(BB)) {
      if (!Processed->count(SuccBB) && containsCycleUtil(SuccBB)) {
        ++BBCount;
        // Continue going down, we haven't found
        // the start yet.
        if (StartBB != BB) {
          return true;
        }
      } else if (Visited->count(SuccBB)) {
        // Found cycle, save the start.
        StartBB = SuccBB;
        ++BBCount;
        return true;
      }
    }
    Visited->erase(BB);
    return false;
  }

(I just moved the invariants to globals so that they're not passed
back and forth in the recursion).

What remains is to utilize the `LoopInfo`. I have
an algorithm but before doing that we have to solve an important problem. I don't seem to be able
to get `LoopInfo`, it's always `null`. I found that I probably
need to add `-loops -analyze` in the command-line but still
it doesn't work. @jdoerfert any idea?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D74691/new/

https://reviews.llvm.org/D74691





More information about the llvm-commits mailing list