[PATCH] D63885: [LOOPINFO] Introduce the loop guard API.

Whitney via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 3 11:02:46 PDT 2019


Whitney marked an inline comment as done.
Whitney added inline comments.


================
Comment at: llvm/include/llvm/Analysis/LoopInfo.h:737
+  /// dominates the loop header, and the other successor postdominates the loop
+  /// header, i.e. the branch instruction \p BI is a loop guard.
+  bool isLoopGuardBranch(const BranchInst &BI, const DominatorTree &DT,
----------------
reames wrote:
> Whitney wrote:
> > reames wrote:
> > > Whitney wrote:
> > > > reames wrote:
> > > > > Your definition would seem to disallow:
> > > > > if (C) return;
> > > > > for (...) {}
> > > > > 
> > > > > That is C wouldn't be considered a guard condition.  Intentional?  
> > > > I think this is fine, in most cases, LLVM tries to common the return blocks, so `if (C)` will jump to the common exit block, and this algorithm will work. Although we can intensionally write LLVMIR with multiple return blocks, I don't think it will be the common case. 
> > > Put two calls on the return paths to different targets and we don't merge them.
> > Do you mind giving me an example? I tried the code below, and that doesn't work. 
> > ```
> > void bar1();
> > void bar2();
> > int foo(bool cond, int *A) {
> >   if (cond) return 1;
> >   for (long i = 0; i < 100; ++i) {
> >     A[i] = 0;
> >   }
> >   bar1();
> >   bar2();
> >   return 0;
> > }
> > ```
> void bar1();
> void bar2();
> int foo(bool cond, int *A) {
>   if (cond) { bar1(); return 1; }
>   for (long i = 0; i < 100; ++i) {
>     A[i] = 0;
>   }
>   bar2();
>   return 0;
> }
With the code above, I ran it through clang (noopt), and got:
```
  br i1 %tobool, label %if.then, label %if.end

if.then:                                          ; preds = %entry
  call void @_Z4bar1v()
  store i32 1, i32* %retval, align 4
  br label %return

if.end:                                           ; preds = %entry
  store i64 0, i64* %i, align 8
  br label %for.cond

for.cond:                                         ; preds = %for.inc, %if.end
  %1 = load i64, i64* %i, align 8
  %cmp = icmp slt i64 %1, 100
  br i1 %cmp, label %for.body, label %for.end

for.body:                                         ; preds = %for.cond
  %2 = load i32*, i32** %A.addr, align 8
  %3 = load i64, i64* %i, align 8
  %arrayidx = getelementptr inbounds i32, i32* %2, i64 %3
  store i32 0, i32* %arrayidx, align 4
  br label %for.inc

for.inc:                                          ; preds = %for.body
  %4 = load i64, i64* %i, align 8
  %inc = add nsw i64 %4, 1
  store i64 %inc, i64* %i, align 8
  br label %for.cond

for.end:                                          ; preds = %for.cond
  call void @_Z4bar2v()
  store i32 0, i32* %retval, align 4
  br label %return

return:                                           ; preds = %for.end, %if.then
  %5 = load i32, i32* %retval, align 4
  ret i32 %5
```

Looks like the two returns are common into one return block.


Repository:
  rL LLVM

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

https://reviews.llvm.org/D63885





More information about the llvm-commits mailing list