1cee313d2SEric Christopher; This test verifies that the loop vectorizer will not vectorizes low trip count
2cee313d2SEric Christopher; loops that require runtime checks (Trip count is computed with profile info).
3cee313d2SEric Christopher; REQUIRES: asserts
4cee313d2SEric Christopher; RUN: opt < %s -loop-vectorize -loop-vectorize-with-block-frequency -S | FileCheck %s
5cee313d2SEric Christopher
6cee313d2SEric Christophertarget datalayout = "E-m:e-p:32:32-i64:32-f64:32:64-a:0:32-n32-S128"
7cee313d2SEric Christopher
8cee313d2SEric Christopher@tab = common global [32 x i8] zeroinitializer, align 1
9cee313d2SEric Christopher
10cee313d2SEric Christopherdefine i32 @foo_low_trip_count1(i32 %bound) {
11cee313d2SEric Christopher; Simple loop with low tripcount. Should not be vectorized.
12cee313d2SEric Christopher
13cee313d2SEric Christopher; CHECK-LABEL: @foo_low_trip_count1(
14cee313d2SEric Christopher; CHECK-NOT: <{{[0-9]+}} x i8>
15cee313d2SEric Christopher
16cee313d2SEric Christopherentry:
17cee313d2SEric Christopher  br label %for.body
18cee313d2SEric Christopher
19cee313d2SEric Christopherfor.body:                                         ; preds = %for.body, %entry
20cee313d2SEric Christopher  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
21cee313d2SEric Christopher  %arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 %i.08
22cee313d2SEric Christopher  %0 = load i8, i8* %arrayidx, align 1
23cee313d2SEric Christopher  %cmp1 = icmp eq i8 %0, 0
24cee313d2SEric Christopher  %. = select i1 %cmp1, i8 2, i8 1
25cee313d2SEric Christopher  store i8 %., i8* %arrayidx, align 1
26cee313d2SEric Christopher  %inc = add nsw i32 %i.08, 1
27cee313d2SEric Christopher  %exitcond = icmp eq i32 %i.08, %bound
28cee313d2SEric Christopher  br i1 %exitcond, label %for.end, label %for.body, !prof !1
29cee313d2SEric Christopher
30cee313d2SEric Christopherfor.end:                                          ; preds = %for.body
31cee313d2SEric Christopher  ret i32 0
32cee313d2SEric Christopher}
33cee313d2SEric Christopher
34cee313d2SEric Christopherdefine i32 @foo_low_trip_count2(i32 %bound) !prof !0 {
35cee313d2SEric Christopher; The loop has a same invocation count with the function, but has a low
36cee313d2SEric Christopher; trip_count per invocation and not worth to vectorize.
37cee313d2SEric Christopher
38cee313d2SEric Christopher; CHECK-LABEL: @foo_low_trip_count2(
39cee313d2SEric Christopher; CHECK-NOT: <{{[0-9]+}} x i8>
40cee313d2SEric Christopher
41cee313d2SEric Christopherentry:
42cee313d2SEric Christopher  br label %for.body
43cee313d2SEric Christopher
44cee313d2SEric Christopherfor.body:                                         ; preds = %for.body, %entry
45cee313d2SEric Christopher  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
46cee313d2SEric Christopher  %arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 %i.08
47cee313d2SEric Christopher  %0 = load i8, i8* %arrayidx, align 1
48cee313d2SEric Christopher  %cmp1 = icmp eq i8 %0, 0
49cee313d2SEric Christopher  %. = select i1 %cmp1, i8 2, i8 1
50cee313d2SEric Christopher  store i8 %., i8* %arrayidx, align 1
51cee313d2SEric Christopher  %inc = add nsw i32 %i.08, 1
52cee313d2SEric Christopher  %exitcond = icmp eq i32 %i.08, %bound
53cee313d2SEric Christopher  br i1 %exitcond, label %for.end, label %for.body, !prof !1
54cee313d2SEric Christopher
55cee313d2SEric Christopherfor.end:                                          ; preds = %for.body
56cee313d2SEric Christopher  ret i32 0
57cee313d2SEric Christopher}
58cee313d2SEric Christopher
59cee313d2SEric Christopherdefine i32 @foo_low_trip_count3(i1 %cond, i32 %bound) !prof !0 {
60cee313d2SEric Christopher; The loop has low invocation count compare to the function invocation count,
61cee313d2SEric Christopher; but has a high trip count per invocation. Vectorize it.
62cee313d2SEric Christopher
63cee313d2SEric Christopher; CHECK-LABEL: @foo_low_trip_count3(
64af7e1588SEvgeniy Brevnov; CHECK:  [[VECTOR_BODY:vector\.body]]:
65af7e1588SEvgeniy Brevnov; CHECK:    br i1 [[TMP9:%.*]], label [[MIDDLE_BLOCK:%.*]], label %[[VECTOR_BODY]], !prof [[LP3:\!.*]],
66af7e1588SEvgeniy Brevnov; CHECK:  [[FOR_BODY:for\.body]]:
67af7e1588SEvgeniy Brevnov; CHECK:    br i1 [[EXITCOND:%.*]], label [[FOR_END_LOOPEXIT:%.*]], label %[[FOR_BODY]], !prof [[LP6:\!.*]],
68cee313d2SEric Christopherentry:
69cee313d2SEric Christopher  br i1 %cond, label %for.preheader, label %for.end, !prof !2
70cee313d2SEric Christopher
71cee313d2SEric Christopherfor.preheader:
72cee313d2SEric Christopher  br label %for.body
73cee313d2SEric Christopher
74cee313d2SEric Christopherfor.body:                                         ; preds = %for.body, %entry
75cee313d2SEric Christopher  %i.08 = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]
76cee313d2SEric Christopher  %arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 %i.08
77cee313d2SEric Christopher  %0 = load i8, i8* %arrayidx, align 1
78cee313d2SEric Christopher  %cmp1 = icmp eq i8 %0, 0
79cee313d2SEric Christopher  %. = select i1 %cmp1, i8 2, i8 1
80cee313d2SEric Christopher  store i8 %., i8* %arrayidx, align 1
81cee313d2SEric Christopher  %inc = add nsw i32 %i.08, 1
82cee313d2SEric Christopher  %exitcond = icmp eq i32 %i.08, %bound
83cee313d2SEric Christopher  br i1 %exitcond, label %for.end, label %for.body, !prof !3
84cee313d2SEric Christopher
85cee313d2SEric Christopherfor.end:                                          ; preds = %for.body
86cee313d2SEric Christopher  ret i32 0
87cee313d2SEric Christopher}
88cee313d2SEric Christopher
89cee313d2SEric Christopherdefine i32 @foo_low_trip_count_icmp_sgt(i32 %bound) {
90cee313d2SEric Christopher; Simple loop with low tripcount and inequality test for exit.
91cee313d2SEric Christopher; Should not be vectorized.
92cee313d2SEric Christopher
93cee313d2SEric Christopher; CHECK-LABEL: @foo_low_trip_count_icmp_sgt(
94cee313d2SEric Christopher; CHECK-NOT: <{{[0-9]+}} x i8>
95cee313d2SEric Christopher
96cee313d2SEric Christopherentry:
97cee313d2SEric Christopher  br label %for.body
98cee313d2SEric Christopher
99cee313d2SEric Christopherfor.body:                                         ; preds = %for.body, %entry
100cee313d2SEric Christopher  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
101cee313d2SEric Christopher  %arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 %i.08
102cee313d2SEric Christopher  %0 = load i8, i8* %arrayidx, align 1
103cee313d2SEric Christopher  %cmp1 = icmp eq i8 %0, 0
104cee313d2SEric Christopher  %. = select i1 %cmp1, i8 2, i8 1
105cee313d2SEric Christopher  store i8 %., i8* %arrayidx, align 1
106cee313d2SEric Christopher  %inc = add nsw i32 %i.08, 1
107cee313d2SEric Christopher  %exitcond = icmp sgt i32 %i.08, %bound
108cee313d2SEric Christopher  br i1 %exitcond, label %for.end, label %for.body, !prof !1
109cee313d2SEric Christopher
110cee313d2SEric Christopherfor.end:                                          ; preds = %for.body
111cee313d2SEric Christopher  ret i32 0
112cee313d2SEric Christopher}
113cee313d2SEric Christopher
114cee313d2SEric Christopherdefine i32 @const_low_trip_count() {
115cee313d2SEric Christopher; Simple loop with constant, small trip count and no profiling info.
116cee313d2SEric Christopher
117cee313d2SEric Christopher; CHECK-LABEL: @const_low_trip_count
118cee313d2SEric Christopher; CHECK-NOT: <{{[0-9]+}} x i8>
119cee313d2SEric Christopher
120cee313d2SEric Christopherentry:
121cee313d2SEric Christopher  br label %for.body
122cee313d2SEric Christopher
123cee313d2SEric Christopherfor.body:                                         ; preds = %for.body, %entry
124cee313d2SEric Christopher  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
125cee313d2SEric Christopher  %arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 %i.08
126cee313d2SEric Christopher  %0 = load i8, i8* %arrayidx, align 1
127cee313d2SEric Christopher  %cmp1 = icmp eq i8 %0, 0
128cee313d2SEric Christopher  %. = select i1 %cmp1, i8 2, i8 1
129cee313d2SEric Christopher  store i8 %., i8* %arrayidx, align 1
130cee313d2SEric Christopher  %inc = add nsw i32 %i.08, 1
131cee313d2SEric Christopher  %exitcond = icmp slt i32 %i.08, 2
132cee313d2SEric Christopher  br i1 %exitcond, label %for.body, label %for.end
133cee313d2SEric Christopher
134cee313d2SEric Christopherfor.end:                                          ; preds = %for.body
135cee313d2SEric Christopher  ret i32 0
136cee313d2SEric Christopher}
137cee313d2SEric Christopher
138cee313d2SEric Christopherdefine i32 @const_large_trip_count() {
139cee313d2SEric Christopher; Simple loop with constant large trip count and no profiling info.
140cee313d2SEric Christopher
141cee313d2SEric Christopher; CHECK-LABEL: @const_large_trip_count
142cee313d2SEric Christopher; CHECK: <{{[0-9]+}} x i8>
143cee313d2SEric Christopher
144cee313d2SEric Christopherentry:
145cee313d2SEric Christopher  br label %for.body
146cee313d2SEric Christopher
147cee313d2SEric Christopherfor.body:                                         ; preds = %for.body, %entry
148cee313d2SEric Christopher  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
149cee313d2SEric Christopher  %arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 %i.08
150cee313d2SEric Christopher  %0 = load i8, i8* %arrayidx, align 1
151cee313d2SEric Christopher  %cmp1 = icmp eq i8 %0, 0
152cee313d2SEric Christopher  %. = select i1 %cmp1, i8 2, i8 1
153cee313d2SEric Christopher  store i8 %., i8* %arrayidx, align 1
154cee313d2SEric Christopher  %inc = add nsw i32 %i.08, 1
155cee313d2SEric Christopher  %exitcond = icmp slt i32 %i.08, 1000
156cee313d2SEric Christopher  br i1 %exitcond, label %for.body, label %for.end
157cee313d2SEric Christopher
158cee313d2SEric Christopherfor.end:                                          ; preds = %for.body
159cee313d2SEric Christopher  ret i32 0
160cee313d2SEric Christopher}
161cee313d2SEric Christopher
162cee313d2SEric Christopherdefine i32 @const_small_trip_count_step() {
163cee313d2SEric Christopher; Simple loop with static, small trip count and no profiling info.
164cee313d2SEric Christopher
165cee313d2SEric Christopher; CHECK-LABEL: @const_small_trip_count_step
166cee313d2SEric Christopher; CHECK-NOT: <{{[0-9]+}} x i8>
167cee313d2SEric Christopher
168cee313d2SEric Christopherentry:
169cee313d2SEric Christopher  br label %for.body
170cee313d2SEric Christopher
171cee313d2SEric Christopherfor.body:                                         ; preds = %for.body, %entry
172cee313d2SEric Christopher  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
173cee313d2SEric Christopher  %arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 %i.08
174cee313d2SEric Christopher  %0 = load i8, i8* %arrayidx, align 1
175cee313d2SEric Christopher  %cmp1 = icmp eq i8 %0, 0
176cee313d2SEric Christopher  %. = select i1 %cmp1, i8 2, i8 1
177cee313d2SEric Christopher  store i8 %., i8* %arrayidx, align 1
178cee313d2SEric Christopher  %inc = add nsw i32 %i.08, 5
179cee313d2SEric Christopher  %exitcond = icmp slt i32 %i.08, 10
180cee313d2SEric Christopher  br i1 %exitcond, label %for.body, label %for.end
181cee313d2SEric Christopher
182cee313d2SEric Christopherfor.end:                                          ; preds = %for.body
183cee313d2SEric Christopher  ret i32 0
184cee313d2SEric Christopher}
185cee313d2SEric Christopher
186cee313d2SEric Christopherdefine i32 @const_trip_over_profile() {
187cee313d2SEric Christopher; constant trip count takes precedence over profile data
188cee313d2SEric Christopher
189cee313d2SEric Christopher; CHECK-LABEL: @const_trip_over_profile
190cee313d2SEric Christopher; CHECK: <{{[0-9]+}} x i8>
191cee313d2SEric Christopher
192cee313d2SEric Christopherentry:
193cee313d2SEric Christopher  br label %for.body
194cee313d2SEric Christopher
195cee313d2SEric Christopherfor.body:                                         ; preds = %for.body, %entry
196cee313d2SEric Christopher  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
197cee313d2SEric Christopher  %arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 %i.08
198cee313d2SEric Christopher  %0 = load i8, i8* %arrayidx, align 1
199cee313d2SEric Christopher  %cmp1 = icmp eq i8 %0, 0
200cee313d2SEric Christopher  %. = select i1 %cmp1, i8 2, i8 1
201cee313d2SEric Christopher  store i8 %., i8* %arrayidx, align 1
202cee313d2SEric Christopher  %inc = add nsw i32 %i.08, 1
203cee313d2SEric Christopher  %exitcond = icmp slt i32 %i.08, 1000
204cee313d2SEric Christopher  br i1 %exitcond, label %for.body, label %for.end, !prof !1
205cee313d2SEric Christopher
206cee313d2SEric Christopherfor.end:                                          ; preds = %for.body
207cee313d2SEric Christopher  ret i32 0
208cee313d2SEric Christopher}
209cee313d2SEric Christopher
210*5c31b8b9SArthur Eubanks; CHECK: [[LP3]] = !{!"branch_weights", i32 10, i32 2490}
211*5c31b8b9SArthur Eubanks; CHECK: [[LP6]] = !{!"branch_weights", i32 10, i32 0}
212af7e1588SEvgeniy Brevnov; original loop has latchExitWeight=10 and backedgeTakenWeight=10,000,
213af7e1588SEvgeniy Brevnov; therefore estimatedBackedgeTakenCount=1,000 and estimatedTripCount=1,001.
214af7e1588SEvgeniy Brevnov; Vectorizing by 4 produces estimatedTripCounts of 1,001/4=250 and 1,001%4=1
215af7e1588SEvgeniy Brevnov; for vectorized and remainder loops, respectively, therefore their
216af7e1588SEvgeniy Brevnov; estimatedBackedgeTakenCounts are 249 and 0, and so the weights recorded with
217af7e1588SEvgeniy Brevnov; loop invocation weights of 10 are the above {10, 2490} and {10, 0}.
218af7e1588SEvgeniy Brevnov
219cee313d2SEric Christopher!0 = !{!"function_entry_count", i64 100}
220*5c31b8b9SArthur Eubanks!1 = !{!"branch_weights", i32 100, i32 0}
221*5c31b8b9SArthur Eubanks!2 = !{!"branch_weights", i32 10, i32 90}
222*5c31b8b9SArthur Eubanks!3 = !{!"branch_weights", i32 10, i32 10000}
223