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

omar ahmed via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 26 03:01:01 PST 2020


omarahmed added a comment.

In D74691#1892769 <https://reviews.llvm.org/D74691#1892769>, @jdoerfert wrote:

> In D74691#1892447 <https://reviews.llvm.org/D74691#1892447>, @omarahmed wrote:
>
> > I am sorry but I can't get what the test that the approach of moving on the SCCs fails in as I have tried to test it a bit with tests like that and printed the SCCs that it gets
> >
> > https://i.imgur.com/fpZhpST.png
> >  1 - entry
> >  2- condition - body
> >  3- return
> >  4 - l4
> >
> > https://i.imgur.com/UJJ3aH0.png
> >  1- entry
> >  2- l1 - l2 - l3 - l4 - l5
> >  3- return
> >  4- l6 - l7 - l8
> >
> > https://i.imgur.com/92NS6rp.png
> >  1- entry
> >  2- l1 - l2 - l3 - l4 - l5 - l6 - l7
> >  3- return
> >
> > and in all of them it reached the cycle and outputs that the loop does not have a max trip count
>
>
> Can u share the IR (with the appropriate RUN lines, thus tests) not the images please?


okay , sorry for this anonymous comment

the first IR :

  define i32* @test1(i32* %n0, i32* %r0, i32* %w0) {
  entry:
  	%tmp = add i32 0, 0
  	br label %condition
  
  condition:
  	%tobool2 = icmp ne i32* %n0, null
      br i1 %tobool2, label %body, label %return
  
  body:
  	%tobool3 = icmp ne i32* %n0, null
      br i1 %tobool3, label %l4, label %condition	
  
  l4:
  	br label %l4
  
  return:                                           
    ret i32* %w0
  }

the second IR :

  define i32* @test2(i32* %n0, i32* %r0, i32* %w0) {
  entry:
  	br label %l1
  l1:
  	br label %l2
  l2:
  	br label %l3
  l3:
  	%tobool = icmp ne i32* %n0, null
      br i1 %tobool, label %return, label %l4
  l4:
  	%tobool2 = icmp ne i32* %n0, null
      br i1 %tobool2, label %l6, label %l5
  l5:
  	br label %l1
  l6:
  	br label %l7
  l7:
  	br label %l8
  l8:
  	br label %l6
  
  return:                                           
    ret i32* %w0
  }

the third IR :

  define i32* @test3(i32* %n0, i32* %r0, i32* %w0) {
  entry:
  	br label %l1
  l1:
  	br label %l2
  l2:
  	br label %l3
  l3:
  	%tobool = icmp ne i32* %n0, null
      br i1 %tobool, label %return, label %l4
  l4:
  	%tobool2 = icmp ne i32* %n0, null
      br i1 %tobool2, label %l6, label %l5
  l5:
  	br label %l1
  l6:
  	br label %l7
  l7:
  	br label %l4
  
  return:                                           
    ret i32* %w0
  }

the run command :

  ./bin/opt -passes=attributor --attributor-disable=false /home/omar/mytest.ll -S

the code I tested it on :

  static bool containsUnboundedCycle(Function &F, Attributor &A) {
    bool NoAnalysis = false;
  
    ScalarEvolution *SE =
        A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(F);
    LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F);
    if (!LI || !SE){
      NoAnalysis = true;
      dbgs() << "no analysis in function\n";
    }
  
    for (scc_iterator<Function *> It = scc_begin(&F), IE = scc_end(&F); It != IE;
         ++It) {
      dbgs()<<"SCC start\n\n\n";
      for(auto SCCBB : *It){
        dbgs()<< *SCCBB <<"\n";
      }
      bool SCCHasLoop = It.hasLoop();
      if (!SCCHasLoop){
        dbgs()<<"SCC does not have loop\n";
        continue;
      }
      // When NoAnalysis available then check only if the SCC has loop or not.
      if (NoAnalysis && SCCHasLoop){
        dbgs() << "no analysis and does have loop\n";
        return true;
      }
  
      const std::vector<BasicBlock *> &SCCBBs = *It;
      // If any random block in this SCC does not belong to a loop, then this SCC
      // is definitely not a loop.
      Loop *L = LI->getLoopFor(SCCBBs.front());
      if (!L){
        dbgs() << "loop is null so current SCC does not have loop\n";
        return true;
      }
  
      // L is the innermost loop that has a common block with the SCC. Since a
      // loop is always an SCC, if their number of blocks are equal, the SCC is a
      // loop so we check if it is bounded or Unbounded loop by checking the
      // maxTripCount. Otherwise, there are 2 cases:
      // - If the SCC has less blocks, then it is definitely not a loop.
      // - If it has more, then we can't decide since the SCC can be a parent loop
      //   of L. So, we perform the same test for the parent of L.
      do {
        if (L->getNumBlocks() > SCCBBs.size()){
          dbgs() << "SCC is less so not loop\n";
          return true;
        }
  
        if (L->getNumBlocks() == SCCBBs.size())
          if (!SE->getSmallConstantMaxTripCount(L)){
            dbgs() << "there is no max trip count for the current SCC\n";
            return true;
          }
          dbgs() << "loop with max trip count\n";
          break;
  
      } while ((L = L->getParentLoop()));
  
      // Check if L is null, we found no loop that matches exactly the number of
      // blocks of the SCC and so the SCC is not a loop.
       if (!L)
        return true;
    }
    return false;
  }

and in the three tests it gets me "there is no max trip count for the current SCC\n" and return true 
so I what I was asking is that I can't figure out what test fails in this code ?


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