[PATCH] D63885: [LOOPINFO] Introduce the loop guard API.
Whitney via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 11 07:48:06 PDT 2019
Whitney marked 3 inline comments 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,
----------------
Whitney wrote:
> 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.
> Put two calls on the return paths to different targets and we don't merge them.
@reames Do you have another example which I should pay attention on?
================
Comment at: llvm/lib/Analysis/LoopInfo.cpp:415
+
+ if (!isGuaranteedToTransferExecutionToSuccessor(Succ))
+ return true;
----------------
Meinersbur wrote:
> Whitney wrote:
> > Meinersbur wrote:
> > > If you want to disallow throwing instructions, how did you conclude that `isGuaranteedToTransferExecutionToSuccessor` is what you want and not `->mayThrow`?
> > >
> > > There might be dynamically endless loops as well that isGuaranteedToTransferExecutionToSuccessor does not check (that is, only if the endless loop was inside a call).
> > I chose `isGuaranteedToTransferExecutionToSuccessor` instead of `->mayThrow` is because it consider more cases, for example it checks if memory operation trap. `isGuaranteedToTransferExecutionToSuccessor` is a superset of `->mayThrow`.
> >
> > What is dynamically endless loops?
> > What is dynamically endless loops?
> ```
> header:
> %cmp = icmp ule i32 0, %a ; anything that always returns true but LLVM cannot figure out
> br i1 %cmp, label %header, label %exit
>
> exit:
> ```
I would like to make sure I understand the concern correctly. Is the concern that the guard guards an dynamically endless loops before the loop of interested?
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