xref: /llvm-project/llvm/test/Transforms/GuardWidening/profile-based-profitability-intrinsics.ll (revision 0b5bb6923f09ebc257ebed4ace1d8b6b113b2bf5)
1a7dcf39fSMax Kazantsev; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2a7dcf39fSMax Kazantsev; RUN: opt -S -passes=guard-widening < %s | FileCheck %s
3a7dcf39fSMax Kazantsev
4a7dcf39fSMax Kazantsev; Function Attrs: nocallback nofree nosync willreturn
5a7dcf39fSMax Kazantsevdeclare void @llvm.experimental.guard(i1, ...) #0
6a7dcf39fSMax Kazantsev
7a7dcf39fSMax Kazantsev; Hot loop, frequently entered, should widen.
8a7dcf39fSMax Kazantsevdefine i32 @test_intrinsic_very_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {
9a7dcf39fSMax Kazantsev; CHECK-LABEL: define i32 @test_intrinsic_very_profitable
10a7dcf39fSMax Kazantsev; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
11a7dcf39fSMax Kazantsev; CHECK-NEXT:  entry:
12*0b5bb692SSerguei Katkov; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
13*0b5bb692SSerguei Katkov; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
14a7dcf39fSMax Kazantsev; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
15a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
16a7dcf39fSMax Kazantsev; CHECK-NEXT:    br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF0:![0-9]+]]
17a7dcf39fSMax Kazantsev; CHECK:       loop:
18a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
19a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
20a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100
21a7dcf39fSMax Kazantsev; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1:![0-9]+]]
22a7dcf39fSMax Kazantsev; CHECK:       exit:
23a7dcf39fSMax Kazantsev; CHECK-NEXT:    ret i32 0
24a7dcf39fSMax Kazantsev; CHECK:       failed:
25a7dcf39fSMax Kazantsev; CHECK-NEXT:    ret i32 -1
26a7dcf39fSMax Kazantsev;
27a7dcf39fSMax Kazantseventry:
28a7dcf39fSMax Kazantsev  call void (i1, ...) @llvm.experimental.guard(i1 %cond.1) [ "deopt"() ]
29a7dcf39fSMax Kazantsev  %loop.precondition = icmp uge i32 %n, 100
30a7dcf39fSMax Kazantsev  br i1 %loop.precondition, label %loop, label %failed, !prof !0
31a7dcf39fSMax Kazantsev
32a7dcf39fSMax Kazantsevloop:                                             ; preds = %loop, %entry
33a7dcf39fSMax Kazantsev  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
34a7dcf39fSMax Kazantsev  call void (i1, ...) @llvm.experimental.guard(i1 %cond.2) [ "deopt"() ]
35a7dcf39fSMax Kazantsev  %iv.next = add nuw nsw i32 %iv, 1
36a7dcf39fSMax Kazantsev  %loop.cond = icmp ult i32 %iv.next, 100
37a7dcf39fSMax Kazantsev  br i1 %loop.cond, label %loop, label %exit, !prof !1
38a7dcf39fSMax Kazantsev
39a7dcf39fSMax Kazantsevexit:                                             ; preds = %loop
40a7dcf39fSMax Kazantsev  ret i32 0
41a7dcf39fSMax Kazantsev
42a7dcf39fSMax Kazantsevfailed:                                           ; preds = %entry
43a7dcf39fSMax Kazantsev  ret i32 -1
44a7dcf39fSMax Kazantsev}
45a7dcf39fSMax Kazantsev
46a7dcf39fSMax Kazantsev; Even though the loop is rarely entered, it has so many iterations that the widening
47a7dcf39fSMax Kazantsev; is still profitable.
48a7dcf39fSMax Kazantsevdefine i32 @test_intrinsic_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {
49a7dcf39fSMax Kazantsev; CHECK-LABEL: define i32 @test_intrinsic_profitable
50a7dcf39fSMax Kazantsev; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
51a7dcf39fSMax Kazantsev; CHECK-NEXT:  entry:
52*0b5bb692SSerguei Katkov; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
53*0b5bb692SSerguei Katkov; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
54a7dcf39fSMax Kazantsev; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
55a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
56a7dcf39fSMax Kazantsev; CHECK-NEXT:    br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF2:![0-9]+]]
57a7dcf39fSMax Kazantsev; CHECK:       loop:
58a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
59a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
60a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100
61a7dcf39fSMax Kazantsev; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]
62a7dcf39fSMax Kazantsev; CHECK:       exit:
63a7dcf39fSMax Kazantsev; CHECK-NEXT:    ret i32 0
64a7dcf39fSMax Kazantsev; CHECK:       failed:
65a7dcf39fSMax Kazantsev; CHECK-NEXT:    ret i32 -1
66a7dcf39fSMax Kazantsev;
67a7dcf39fSMax Kazantseventry:
68a7dcf39fSMax Kazantsev  call void (i1, ...) @llvm.experimental.guard(i1 %cond.1) [ "deopt"() ]
69a7dcf39fSMax Kazantsev  %loop.precondition = icmp uge i32 %n, 100
70a7dcf39fSMax Kazantsev  br i1 %loop.precondition, label %loop, label %failed, !prof !2
71a7dcf39fSMax Kazantsev
72a7dcf39fSMax Kazantsevloop:                                             ; preds = %loop, %entry
73a7dcf39fSMax Kazantsev  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
74a7dcf39fSMax Kazantsev  call void (i1, ...) @llvm.experimental.guard(i1 %cond.2) [ "deopt"() ]
75a7dcf39fSMax Kazantsev  %iv.next = add nuw nsw i32 %iv, 1
76a7dcf39fSMax Kazantsev  %loop.cond = icmp ult i32 %iv.next, 100
77a7dcf39fSMax Kazantsev  br i1 %loop.cond, label %loop, label %exit, !prof !1
78a7dcf39fSMax Kazantsev
79a7dcf39fSMax Kazantsevexit:                                             ; preds = %loop
80a7dcf39fSMax Kazantsev  ret i32 0
81a7dcf39fSMax Kazantsev
82a7dcf39fSMax Kazantsevfailed:                                           ; preds = %entry
83a7dcf39fSMax Kazantsev  ret i32 -1
84a7dcf39fSMax Kazantsev}
85a7dcf39fSMax Kazantsev
86a7dcf39fSMax Kazantsev; Loop's hotness compensates rareness of its entrance. We still want to widen, because
87a7dcf39fSMax Kazantsev; it may open up some optimization opportunities.
88a7dcf39fSMax Kazantsevdefine i32 @test_intrinsic_neutral(i32 %n, i1 %cond.1, i1 %cond.2) {
89a7dcf39fSMax Kazantsev; CHECK-LABEL: define i32 @test_intrinsic_neutral
90a7dcf39fSMax Kazantsev; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
91a7dcf39fSMax Kazantsev; CHECK-NEXT:  entry:
92*0b5bb692SSerguei Katkov; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
93*0b5bb692SSerguei Katkov; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
94a7dcf39fSMax Kazantsev; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
95a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
96a7dcf39fSMax Kazantsev; CHECK-NEXT:    br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF3:![0-9]+]]
97a7dcf39fSMax Kazantsev; CHECK:       loop:
98a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
99a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
100a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100
101a7dcf39fSMax Kazantsev; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]
102a7dcf39fSMax Kazantsev; CHECK:       exit:
103a7dcf39fSMax Kazantsev; CHECK-NEXT:    ret i32 0
104a7dcf39fSMax Kazantsev; CHECK:       failed:
105a7dcf39fSMax Kazantsev; CHECK-NEXT:    ret i32 -1
106a7dcf39fSMax Kazantsev;
107a7dcf39fSMax Kazantseventry:
108a7dcf39fSMax Kazantsev  call void (i1, ...) @llvm.experimental.guard(i1 %cond.1) [ "deopt"() ]
109a7dcf39fSMax Kazantsev  %loop.precondition = icmp uge i32 %n, 100
110a7dcf39fSMax Kazantsev  br i1 %loop.precondition, label %loop, label %failed, !prof !3
111a7dcf39fSMax Kazantsev
112a7dcf39fSMax Kazantsevloop:                                             ; preds = %loop, %entry
113a7dcf39fSMax Kazantsev  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
114a7dcf39fSMax Kazantsev  call void (i1, ...) @llvm.experimental.guard(i1 %cond.2) [ "deopt"() ]
115a7dcf39fSMax Kazantsev  %iv.next = add nuw nsw i32 %iv, 1
116a7dcf39fSMax Kazantsev  %loop.cond = icmp ult i32 %iv.next, 100
117a7dcf39fSMax Kazantsev  br i1 %loop.cond, label %loop, label %exit, !prof !1
118a7dcf39fSMax Kazantsev
119a7dcf39fSMax Kazantsevexit:                                             ; preds = %loop
120a7dcf39fSMax Kazantsev  ret i32 0
121a7dcf39fSMax Kazantsev
122a7dcf39fSMax Kazantsevfailed:                                           ; preds = %entry
123a7dcf39fSMax Kazantsev  ret i32 -1
124a7dcf39fSMax Kazantsev}
125a7dcf39fSMax Kazantsev
126a7dcf39fSMax Kazantsev; FIXME: This loop is so rarely entered, that we don't want to widen here.
127a7dcf39fSMax Kazantsevdefine i32 @test_intrinsic_very_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {
128a7dcf39fSMax Kazantsev; CHECK-LABEL: define i32 @test_intrinsic_very_unprofitable
129a7dcf39fSMax Kazantsev; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
130a7dcf39fSMax Kazantsev; CHECK-NEXT:  entry:
131*0b5bb692SSerguei Katkov; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
132*0b5bb692SSerguei Katkov; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
133a7dcf39fSMax Kazantsev; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
134a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
135a7dcf39fSMax Kazantsev; CHECK-NEXT:    br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF4:![0-9]+]]
136a7dcf39fSMax Kazantsev; CHECK:       loop:
137a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
138a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
139a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100
140a7dcf39fSMax Kazantsev; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]
141a7dcf39fSMax Kazantsev; CHECK:       exit:
142a7dcf39fSMax Kazantsev; CHECK-NEXT:    ret i32 0
143a7dcf39fSMax Kazantsev; CHECK:       failed:
144a7dcf39fSMax Kazantsev; CHECK-NEXT:    ret i32 -1
145a7dcf39fSMax Kazantsev;
146a7dcf39fSMax Kazantseventry:
147a7dcf39fSMax Kazantsev  call void (i1, ...) @llvm.experimental.guard(i1 %cond.1) [ "deopt"() ]
148a7dcf39fSMax Kazantsev  %loop.precondition = icmp uge i32 %n, 100
149a7dcf39fSMax Kazantsev  br i1 %loop.precondition, label %loop, label %failed, !prof !4
150a7dcf39fSMax Kazantsev
151a7dcf39fSMax Kazantsevloop:                                             ; preds = %loop, %entry
152a7dcf39fSMax Kazantsev  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
153a7dcf39fSMax Kazantsev  call void (i1, ...) @llvm.experimental.guard(i1 %cond.2) [ "deopt"() ]
154a7dcf39fSMax Kazantsev  %iv.next = add nuw nsw i32 %iv, 1
155a7dcf39fSMax Kazantsev  %loop.cond = icmp ult i32 %iv.next, 100
156a7dcf39fSMax Kazantsev  br i1 %loop.cond, label %loop, label %exit, !prof !1
157a7dcf39fSMax Kazantsev
158a7dcf39fSMax Kazantsevexit:                                             ; preds = %loop
159a7dcf39fSMax Kazantsev  ret i32 0
160a7dcf39fSMax Kazantsev
161a7dcf39fSMax Kazantsevfailed:                                           ; preds = %entry
162a7dcf39fSMax Kazantsev  ret i32 -1
163a7dcf39fSMax Kazantsev}
164a7dcf39fSMax Kazantsev
165a7dcf39fSMax Kazantsev; FIXME: This loop is so rarely entered, that we don't want to widen here.
166a7dcf39fSMax Kazantsevdefine i32 @test_intrinsic_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {
167a7dcf39fSMax Kazantsev; CHECK-LABEL: define i32 @test_intrinsic_unprofitable
168a7dcf39fSMax Kazantsev; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
169a7dcf39fSMax Kazantsev; CHECK-NEXT:  entry:
170*0b5bb692SSerguei Katkov; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
171*0b5bb692SSerguei Katkov; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
172a7dcf39fSMax Kazantsev; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
173a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
174a7dcf39fSMax Kazantsev; CHECK-NEXT:    br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF5:![0-9]+]]
175a7dcf39fSMax Kazantsev; CHECK:       loop:
176a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
177a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
178a7dcf39fSMax Kazantsev; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100
179a7dcf39fSMax Kazantsev; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]], !prof [[PROF1]]
180a7dcf39fSMax Kazantsev; CHECK:       exit:
181a7dcf39fSMax Kazantsev; CHECK-NEXT:    ret i32 0
182a7dcf39fSMax Kazantsev; CHECK:       failed:
183a7dcf39fSMax Kazantsev; CHECK-NEXT:    ret i32 -1
184a7dcf39fSMax Kazantsev;
185a7dcf39fSMax Kazantseventry:
186a7dcf39fSMax Kazantsev  call void (i1, ...) @llvm.experimental.guard(i1 %cond.1) [ "deopt"() ]
187a7dcf39fSMax Kazantsev  %loop.precondition = icmp uge i32 %n, 100
188a7dcf39fSMax Kazantsev  br i1 %loop.precondition, label %loop, label %failed, !prof !5
189a7dcf39fSMax Kazantsev
190a7dcf39fSMax Kazantsevloop:                                             ; preds = %loop, %entry
191a7dcf39fSMax Kazantsev  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
192a7dcf39fSMax Kazantsev  call void (i1, ...) @llvm.experimental.guard(i1 %cond.2) [ "deopt"() ]
193a7dcf39fSMax Kazantsev  %iv.next = add nuw nsw i32 %iv, 1
194a7dcf39fSMax Kazantsev  %loop.cond = icmp ult i32 %iv.next, 100
195a7dcf39fSMax Kazantsev  br i1 %loop.cond, label %loop, label %exit, !prof !1
196a7dcf39fSMax Kazantsev
197a7dcf39fSMax Kazantsevexit:                                             ; preds = %loop
198a7dcf39fSMax Kazantsev  ret i32 0
199a7dcf39fSMax Kazantsev
200a7dcf39fSMax Kazantsevfailed:                                           ; preds = %entry
201a7dcf39fSMax Kazantsev  ret i32 -1
202a7dcf39fSMax Kazantsev}
203a7dcf39fSMax Kazantsev
204a7dcf39fSMax Kazantsevattributes #0 = { nocallback nofree nosync willreturn }
205a7dcf39fSMax Kazantsev
206a7dcf39fSMax Kazantsev!0 = !{!"branch_weights", i32 1048576, i32 1}
207a7dcf39fSMax Kazantsev!1 = !{!"branch_weights", i32 99, i32 1}
208a7dcf39fSMax Kazantsev!2 = !{!"branch_weights", i32 1, i32 10}
209a7dcf39fSMax Kazantsev!3 = !{!"branch_weights", i32 1, i32 99}
210a7dcf39fSMax Kazantsev!4 = !{!"branch_weights", i32 1, i32 1048576}
211a7dcf39fSMax Kazantsev!5 = !{!"branch_weights", i32 1, i32 1000}
212