[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