Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[LoopDeletion] Allows deletion of possibly infinite side-effect free …
…loops From C11 and C++11 onwards, a forward-progress requirement has been introduced for both languages. In the case of C, loops with non-constant conditionals that do not have any observable side-effects (as defined by 6.8.5p6) can be assumed by the implementation to terminate, and in the case of C++, this assumption extends to all functions. The clang frontend will emit the `mustprogress` function attribute for C++ functions (D86233, D85393, D86841) and emit the loop metadata `llvm.loop.mustprogress` for every loop in C11 or later that has a non-constant conditional. This patch modifies LoopDeletion so that only loops with the `llvm.loop.mustprogress` metadata or loops contained in functions that are required to make progress (`mustprogress` or `willreturn`) are checked for observable side-effects. If these loops do not have an observable side-effect, then we delete them. Loops without observable side-effects that do not satisfy the above conditions will not be deleted. Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D86844
- Loading branch information
Showing
19 changed files
with
274 additions
and
30 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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,237 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes | ||
; RUN: opt < %s -loop-deletion -S | FileCheck %s | ||
|
||
;; Original C Code: | ||
;; void unknown_tripcount_mustprogress_attr_mustprogress_loopmd(int a, int b) { | ||
;; for (; a < b;) ; | ||
;; for (;;) ; | ||
;; } | ||
|
||
define void @unknown_tripcount_mustprogress_attr_mustprogress_loopmd(i32 %a, i32 %b) #0 { | ||
; CHECK: Function Attrs: mustprogress | ||
; CHECK-LABEL: define {{[^@]+}}@unknown_tripcount_mustprogress_attr_mustprogress_loopmd | ||
; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) [[ATTR0:#.*]] { | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: br label [[FOR_END:%.*]] | ||
; CHECK: for.end: | ||
; CHECK-NEXT: unreachable | ||
; | ||
entry: | ||
br label %for.cond | ||
for.cond: | ||
%cmp = icmp slt i32 %a, %b | ||
br i1 %cmp, label %for.body, label %for.end | ||
for.body: | ||
br label %for.cond, !llvm.loop !2 | ||
for.end: | ||
br label %for.cond1 | ||
for.cond1: | ||
br label %for.cond1 | ||
} | ||
|
||
;; Original C Code: | ||
;; void unknown_tripcount_mustprogress_attr_no_mustprogress_loopmd(int a, int b) { | ||
;; for (; a < b;) ; | ||
;; for (;;) ; | ||
;; } | ||
;; => Removed mustprogress loop attribute | ||
|
||
define void @unknown_tripcount_mustprogress_attr_no_mustprogess_loopmd(i32 %a, i32 %b) #0 { | ||
; CHECK: Function Attrs: mustprogress | ||
; CHECK-LABEL: define {{[^@]+}}@unknown_tripcount_mustprogress_attr_no_mustprogess_loopmd | ||
; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) [[ATTR0]] { | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: br label [[FOR_END:%.*]] | ||
; CHECK: for.end: | ||
; CHECK-NEXT: unreachable | ||
; | ||
entry: | ||
br label %for.cond | ||
for.cond: | ||
%cmp = icmp slt i32 %a, %b | ||
br i1 %cmp, label %for.body, label %for.end | ||
for.body: | ||
br label %for.cond | ||
for.end: | ||
br label %for.cond1 | ||
for.cond1: | ||
br label %for.cond1 | ||
} | ||
|
||
;; Original C Code: | ||
;; void known_tripcount_no_mustprogress_attr_no_mustprogress_loopmd() { | ||
;; for (int i = 0; i < 5; i++) ; | ||
;; } | ||
|
||
define void @known_tripcount_no_mustprogress_attr_no_mustprogress_loopmd() { | ||
; CHECK-LABEL: define {{[^@]+}}@known_tripcount_no_mustprogress_attr_no_mustprogress_loopmd() { | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: br label [[FOR_END:%.*]] | ||
; CHECK: for.end: | ||
; CHECK-NEXT: ret void | ||
; | ||
entry: | ||
br label %for.cond | ||
for.cond: | ||
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] | ||
%cmp = icmp slt i32 %i.0, 5 | ||
br i1 %cmp, label %for.body, label %for.end | ||
for.body: | ||
br label %for.inc | ||
for.inc: | ||
%inc = add nsw i32 %i.0, 1 | ||
br label %for.cond | ||
for.end: | ||
ret void | ||
} | ||
|
||
;; Original C Code: | ||
;; void known_tripcount_no_mustprogress_attr_mustprogress_loopmd() { | ||
;; for (int i = 0; i < 5; i++) ; | ||
;; } | ||
;; => Added mustprogress loop attribute | ||
|
||
define void @known_tripcount_no_mustprogress_attr_mustprogress_loopmd() { | ||
; CHECK-LABEL: define {{[^@]+}}@known_tripcount_no_mustprogress_attr_mustprogress_loopmd() { | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: br label [[FOR_END:%.*]] | ||
; CHECK: for.end: | ||
; CHECK-NEXT: ret void | ||
; | ||
entry: | ||
br label %for.cond | ||
for.cond: | ||
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] | ||
%cmp = icmp slt i32 %i.0, 5 | ||
br i1 %cmp, label %for.body, label %for.end | ||
for.body: | ||
br label %for.inc | ||
for.inc: | ||
%inc = add nsw i32 %i.0, 1 | ||
br label %for.cond, !llvm.loop !4 | ||
for.end: | ||
ret void | ||
} | ||
|
||
;; Original C Code: | ||
;; void known_tripcount_mustprogress_attr_no_mustprogress_loopmd() { | ||
;; for (int i = 0; i < 5; i++) ; | ||
;; } | ||
;; => Added mustprogress function attribute | ||
|
||
define void @known_tripcount_mustprogress_attr_no_mustprogress_loopmd() #0 { | ||
; CHECK: Function Attrs: mustprogress | ||
; CHECK-LABEL: define {{[^@]+}}@known_tripcount_mustprogress_attr_no_mustprogress_loopmd | ||
; CHECK-SAME: () [[ATTR0]] { | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: br label [[FOR_END:%.*]] | ||
; CHECK: for.end: | ||
; CHECK-NEXT: ret void | ||
; | ||
entry: | ||
br label %for.cond | ||
for.cond: | ||
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] | ||
%cmp = icmp slt i32 %i.0, 5 | ||
br i1 %cmp, label %for.body, label %for.end | ||
for.body: | ||
br label %for.inc | ||
for.inc: | ||
%inc = add nsw i32 %i.0, 1 | ||
br label %for.cond | ||
for.end: | ||
ret void | ||
} | ||
|
||
;; Original C Code: | ||
;; void known_tripcount_mustprogress_attr_mustprogress_loopmd() { | ||
;; for (int i = 0; i < 5; i++) ; | ||
;; } | ||
;; => Added mustprogress function and mustprogress loop attribute | ||
|
||
define void @known_tripcount_mustprogress_attr_mustprogress_loopmd() #0 { | ||
; CHECK: Function Attrs: mustprogress | ||
; CHECK-LABEL: define {{[^@]+}}@known_tripcount_mustprogress_attr_mustprogress_loopmd | ||
; CHECK-SAME: () [[ATTR0]] { | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: br label [[FOR_END:%.*]] | ||
; CHECK: for.end: | ||
; CHECK-NEXT: ret void | ||
; | ||
entry: | ||
br label %for.cond | ||
for.cond: | ||
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] | ||
%cmp = icmp slt i32 %i.0, 5 | ||
br i1 %cmp, label %for.body, label %for.end | ||
for.body: | ||
br label %for.inc | ||
for.inc: | ||
%inc = add nsw i32 %i.0, 1 | ||
br label %for.cond, !llvm.loop !5 | ||
for.end: | ||
ret void | ||
} | ||
|
||
;; Original C Code: | ||
;; void unknown_tripcount_no_mustprogress_attr_mustprogress_loopmd(int a, int b) { | ||
;; for (; a < b;) ; | ||
;; } | ||
;; => Added mustprogress loop attribute | ||
|
||
define void @unknown_tripcount_no_mustprogress_attr_mustprogress_loopmd(i32 %a, i32 %b) { | ||
; CHECK-LABEL: define {{[^@]+}}@unknown_tripcount_no_mustprogress_attr_mustprogress_loopmd | ||
; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: br label [[FOR_END:%.*]] | ||
; CHECK: for.end: | ||
; CHECK-NEXT: ret void | ||
; | ||
entry: | ||
br label %for.cond | ||
for.cond: | ||
%cmp = icmp slt i32 %a, %b | ||
br i1 %cmp, label %for.body, label %for.end | ||
for.body: | ||
br label %for.cond, !llvm.loop !6 | ||
for.end: | ||
ret void | ||
} | ||
|
||
;; Original C Code: | ||
;; void unknown_tripcount_no_mustprogress_attr_no_mustprogress_loopmd(int a, int b) { | ||
;; for (; a < b;) ; | ||
;; } | ||
|
||
define void @unknown_tripcount_no_mustprogress_attr_no_mustprogress_loopmd(i32 %a, i32 %b) { | ||
; CHECK-LABEL: define {{[^@]+}}@unknown_tripcount_no_mustprogress_attr_no_mustprogress_loopmd | ||
; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: br label [[FOR_COND:%.*]] | ||
; CHECK: for.cond: | ||
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], [[B]] | ||
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] | ||
; CHECK: for.body: | ||
; CHECK-NEXT: br label [[FOR_COND]] | ||
; CHECK: for.end: | ||
; CHECK-NEXT: ret void | ||
; | ||
entry: | ||
br label %for.cond | ||
for.cond: | ||
%cmp = icmp slt i32 %a, %b | ||
br i1 %cmp, label %for.body, label %for.end | ||
for.body: | ||
br label %for.cond | ||
for.end: | ||
ret void | ||
} | ||
|
||
; CHECK: attributes [[ATTR0]] = { mustprogress } | ||
|
||
attributes #0 = { mustprogress } | ||
!2 = distinct !{!2, !3} | ||
!3 = !{!"llvm.loop.mustprogress"} | ||
!4 = distinct !{!4, !3} | ||
!5 = distinct !{!5, !3} | ||
!6 = distinct !{!6, !3} |
Oops, something went wrong.