-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[LoopUnroll] Fix division by zero #166258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
llvm/test/Transforms/LoopUnroll/loop-probability-one.ll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| ; Check that a loop probability of one (indicating an always infinite loop) does | ||
| ; not crash or otherwise break LoopUnroll behavior when it tries to compute new | ||
| ; probabilities from it. | ||
| ; | ||
| ; Runtime loop unrolling should be impossible for that case. What is infinity % | ||
| ; UnrollCount? But we can have bad profile data. In that case, the | ||
| ; implementation arbitrarily chooses to keep the probability at 1 throughout the | ||
| ; remainder loop. | ||
|
|
||
| ; DEFINE: %{unroll} = opt < %s -unroll-count=3 -passes=loop-unroll -S | ||
| ; DEFINE: %{rt} = %{unroll} -unroll-runtime | ||
|
|
||
| ; RUN: %{unroll} | FileCheck %s -check-prefix UNROLL | ||
| ; RUN: %{rt} -unroll-runtime-epilog=true | FileCheck %s -check-prefix EPILOG | ||
| ; RUN: %{rt} -unroll-runtime-epilog=false | FileCheck %s -check-prefix PROLOG | ||
|
|
||
| define void @test(i32 %n) { | ||
| entry: | ||
| br label %loop | ||
|
|
||
| loop: | ||
| %i = phi i32 [ 0, %entry ], [ %inc, %loop ] | ||
| %inc = add i32 %i, 1 | ||
| %c = icmp slt i32 %inc, %n | ||
| br i1 %c, label %loop, label %end, !prof !0 | ||
|
|
||
| end: | ||
| ret void | ||
| } | ||
|
|
||
|
|
||
| !0 = !{!"branch_weights", i32 1, i32 0} | ||
|
|
||
| ; UNROLL: define void @test(i32 %n) { | ||
| ; UNROLL: entry: | ||
| ; UNROLL: br label %loop | ||
| ; UNROLL: loop: | ||
| ; UNROLL: br i1 %c, label %loop.1, label %end, !prof !0 | ||
| ; UNROLL: loop.1: | ||
| ; UNROLL: br i1 %c.1, label %loop.2, label %end, !prof !0 | ||
| ; UNROLL: loop.2: | ||
| ; UNROLL: br i1 %c.2, label %loop, label %end, !prof !0, !llvm.loop !1 | ||
| ; UNROLL-NOT: loop.3 | ||
| ; UNROLL: end: | ||
| ; UNROLL: ret void | ||
| ; UNROLL: } | ||
| ; | ||
| ; Infinite unrolled loop. | ||
| ; UNROLL: !0 = !{!"branch_weights", i32 1, i32 0} | ||
|
|
||
| ; EPILOG: define void @test(i32 %n) { | ||
| ; EPILOG: entry: | ||
| ; EPILOG: br i1 %{{.*}}, label %loop.epil.preheader, label %entry.new, !prof !0 | ||
| ; EPILOG: entry.new: | ||
| ; EPILOG: br label %loop | ||
| ; EPILOG: loop: | ||
| ; EPILOG: br i1 %{{.*}}, label %loop, label %end.unr-lcssa, !prof !1 | ||
| ; EPILOG: end.unr-lcssa: | ||
| ; EPILOG: br i1 %{{.*}}, label %loop.epil.preheader, label %end, !prof !1 | ||
| ; EPILOG: loop.epil.preheader: | ||
| ; EPILOG: br label %loop.epil | ||
| ; EPILOG: loop.epil: | ||
| ; EPILOG: br i1 %{{.*}}, label %loop.epil, label %end.epilog-lcssa, !prof !4 | ||
| ; EPILOG: end.epilog-lcssa: | ||
| ; EPILOG: br label %end | ||
| ; EPILOG: end: | ||
| ; EPILOG: ret void | ||
| ; EPILOG: } | ||
| ; | ||
| ; Unrolled loop guard: Unrolled loop is always entered. | ||
| ; EPILOG: !0 = !{!"branch_weights", i32 0, i32 -2147483648} | ||
| ; | ||
| ; Unrolled loop latch: Unrolled loop is infinite. | ||
| ; Epilogue loop guard: Epilogue loop is always entered if unrolled loop exits. | ||
| ; EPILOG: !1 = !{!"branch_weights", i32 -2147483648, i32 0} | ||
| ; | ||
| ; Epilogue loop latch: Epilogue loop executes both of its 2 iterations. | ||
| ; EPILOG: !4 = !{!"branch_weights", i32 1073741824, i32 1073741824} | ||
|
|
||
| ; PROLOG: define void @test(i32 %n) { | ||
| ; PROLOG: entry: | ||
| ; PROLOG: br i1 %{{.*}}, label %loop.prol.preheader, label %loop.prol.loopexit, !prof !0 | ||
| ; PROLOG: loop.prol.preheader: | ||
| ; PROLOG: br label %loop.prol | ||
| ; PROLOG: loop.prol: | ||
| ; PROLOG: br i1 %{{.*}}, label %loop.prol, label %loop.prol.loopexit.unr-lcssa, !prof !1 | ||
| ; PROLOG: loop.prol.loopexit.unr-lcssa: | ||
| ; PROLOG: br label %loop.prol.loopexit | ||
| ; PROLOG: loop.prol.loopexit: | ||
| ; PROLOG: br i1 %{{.*}}, label %end, label %entry.new, !prof !0 | ||
| ; PROLOG: entry.new: | ||
| ; PROLOG: br label %loop | ||
| ; PROLOG: loop: | ||
| ; PROLOG: br i1 %{{.*}}, label %loop, label %end.unr-lcssa, !prof !4 | ||
| ; PROLOG: end.unr-lcssa: | ||
| ; PROLOG: br label %end | ||
| ; PROLOG: end: | ||
| ; PROLOG: ret void | ||
| ; PROLOG: } | ||
| ; | ||
| ; FIXME: Branch weights still need to be fixed in the case of prologues (issue | ||
| ; #135812), so !0 and !1 do not yet match their comments below. When we do | ||
| ; fix it, this test will hopefully catch any bug like issue #165998, which | ||
| ; impacted the case of epilogues. | ||
| ; | ||
| ; Prologue loop guard: Prologue loop is always entered. | ||
| ; Unrolled loop guard: Unrolled loop is always entered. | ||
| ; PROLOG: !0 = !{!"branch_weights", i32 1, i32 127} | ||
| ; | ||
| ; Prologue loop latch: Prologue loop executes both of its 2 iterations. | ||
| ; PROLOG: !1 = !{!"branch_weights", i32 0, i32 1} | ||
| ; | ||
| ; Unrolled loop latch: Unrolled loop is infinite. | ||
| ; PROLOG: !4 = !{!"branch_weights", i32 1, i32 0} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a strong opinion here, but for my taste I'd rather have the talk about special cases within the function (rather than in the "API" documentation in front of the function) and even then rather discuss in reviews, discourse etc. what the values could mean rather than particularily here.
(But I realize this is a bit of a subjective thing; so do whatever you think is right)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I replied to your other comment, I feel like the code comment should stay somewhere in the code. I thought of it as an API-level issue as it explains that/how the function is robust to a case that a caller might be concerned about. I can live with it being an internal comment though if you decide you do feel strongly about it.
But I now realize we should have something saying division by zero is being avoided. I'll add that.