xref: /llvm-project/llvm/test/Transforms/LoopVectorize/runtime-checks-difference-simplifications.ll (revision 4ad0fdd1631eeae432714c03ede01a10dc00025d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -o - -S %s | FileCheck %s
3
4; Test case with a large number of pointer groups to check for memory
5; conflicts, but with many redundant checks that can be simplified.
6define void @test_large_number_of_group(ptr %dst, i64 %off, i64 %N) {
7; CHECK-LABEL: @test_large_number_of_group(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[OFF_MUL_2:%.*]] = shl i64 [[OFF:%.*]], 1
10; CHECK-NEXT:    [[OFF_MUL_3:%.*]] = mul i64 [[OFF]], 3
11; CHECK-NEXT:    [[OFF_MUL_4:%.*]] = shl i64 [[OFF]], 2
12; CHECK-NEXT:    [[OFF_MUL_5:%.*]] = mul i64 [[OFF]], 5
13; CHECK-NEXT:    [[OFF_MUL_6:%.*]] = mul i64 [[OFF]], 6
14; CHECK-NEXT:    [[OFF_MUL_7:%.*]] = mul i64 [[OFF]], 7
15; CHECK-NEXT:    [[OFF_MUL_8:%.*]] = shl i64 [[OFF]], 3
16; CHECK-NEXT:    [[OFF_MUL_9:%.*]] = mul i64 [[OFF]], 9
17; CHECK-NEXT:    [[OFF_MUL_10:%.*]] = mul i64 [[OFF]], 10
18; CHECK-NEXT:    [[OFF_MUL_11:%.*]] = mul i64 [[OFF]], 11
19; CHECK-NEXT:    [[OFF_MUL_12:%.*]] = mul i64 [[OFF]], 12
20; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N:%.*]], 4
21; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_MEMCHECK:%.*]]
22; CHECK:       vector.memcheck:
23; CHECK-NEXT:    [[DIFF_CHECK:%.*]] = icmp ult i64 [[OFF_MUL_8]], 32
24; CHECK-NEXT:    [[TMP0:%.*]] = shl i64 [[OFF]], 4
25; CHECK-NEXT:    [[DIFF_CHECK1:%.*]] = icmp ult i64 [[TMP0]], 32
26; CHECK-NEXT:    [[CONFLICT_RDX:%.*]] = or i1 [[DIFF_CHECK]], [[DIFF_CHECK1]]
27; CHECK-NEXT:    [[TMP1:%.*]] = mul i64 [[OFF]], 24
28; CHECK-NEXT:    [[DIFF_CHECK2:%.*]] = icmp ult i64 [[TMP1]], 32
29; CHECK-NEXT:    [[CONFLICT_RDX3:%.*]] = or i1 [[CONFLICT_RDX]], [[DIFF_CHECK2]]
30; CHECK-NEXT:    [[TMP2:%.*]] = shl i64 [[OFF]], 5
31; CHECK-NEXT:    [[DIFF_CHECK4:%.*]] = icmp ult i64 [[TMP2]], 32
32; CHECK-NEXT:    [[CONFLICT_RDX5:%.*]] = or i1 [[CONFLICT_RDX3]], [[DIFF_CHECK4]]
33; CHECK-NEXT:    [[TMP3:%.*]] = mul i64 [[OFF]], 40
34; CHECK-NEXT:    [[DIFF_CHECK6:%.*]] = icmp ult i64 [[TMP3]], 32
35; CHECK-NEXT:    [[CONFLICT_RDX7:%.*]] = or i1 [[CONFLICT_RDX5]], [[DIFF_CHECK6]]
36; CHECK-NEXT:    [[TMP4:%.*]] = mul i64 [[OFF]], 48
37; CHECK-NEXT:    [[DIFF_CHECK8:%.*]] = icmp ult i64 [[TMP4]], 32
38; CHECK-NEXT:    [[CONFLICT_RDX9:%.*]] = or i1 [[CONFLICT_RDX7]], [[DIFF_CHECK8]]
39; CHECK-NEXT:    [[TMP5:%.*]] = mul i64 [[OFF]], 56
40; CHECK-NEXT:    [[DIFF_CHECK10:%.*]] = icmp ult i64 [[TMP5]], 32
41; CHECK-NEXT:    [[CONFLICT_RDX11:%.*]] = or i1 [[CONFLICT_RDX9]], [[DIFF_CHECK10]]
42; CHECK-NEXT:    [[TMP6:%.*]] = shl i64 [[OFF]], 6
43; CHECK-NEXT:    [[DIFF_CHECK12:%.*]] = icmp ult i64 [[TMP6]], 32
44; CHECK-NEXT:    [[CONFLICT_RDX13:%.*]] = or i1 [[CONFLICT_RDX11]], [[DIFF_CHECK12]]
45; CHECK-NEXT:    [[TMP7:%.*]] = mul i64 [[OFF]], 72
46; CHECK-NEXT:    [[DIFF_CHECK14:%.*]] = icmp ult i64 [[TMP7]], 32
47; CHECK-NEXT:    [[CONFLICT_RDX15:%.*]] = or i1 [[CONFLICT_RDX13]], [[DIFF_CHECK14]]
48; CHECK-NEXT:    [[TMP8:%.*]] = mul i64 [[OFF]], 80
49; CHECK-NEXT:    [[DIFF_CHECK16:%.*]] = icmp ult i64 [[TMP8]], 32
50; CHECK-NEXT:    [[CONFLICT_RDX17:%.*]] = or i1 [[CONFLICT_RDX15]], [[DIFF_CHECK16]]
51; CHECK-NEXT:    [[TMP9:%.*]] = mul i64 [[OFF]], 88
52; CHECK-NEXT:    [[DIFF_CHECK18:%.*]] = icmp ult i64 [[TMP9]], 32
53; CHECK-NEXT:    [[CONFLICT_RDX19:%.*]] = or i1 [[CONFLICT_RDX17]], [[DIFF_CHECK18]]
54; CHECK-NEXT:    br i1 [[CONFLICT_RDX19]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]
55; CHECK:       vector.ph:
56; CHECK-NEXT:    [[N_MOD_VF:%.*]] = urem i64 [[N]], 4
57; CHECK-NEXT:    [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]
58; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
59; CHECK:       vector.body:
60; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
61; CHECK-NEXT:    [[TMP10:%.*]] = add i64 [[INDEX]], 0
62; CHECK-NEXT:    [[TMP11:%.*]] = add nsw i64 [[TMP10]], -5
63; CHECK-NEXT:    [[TMP12:%.*]] = add i64 [[TMP11]], [[OFF]]
64; CHECK-NEXT:    [[TMP13:%.*]] = getelementptr i64, ptr [[DST:%.*]], i64 [[TMP12]]
65; CHECK-NEXT:    [[TMP14:%.*]] = getelementptr double, ptr [[TMP13]], i32 0
66; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP14]], align 8
67; CHECK-NEXT:    [[TMP15:%.*]] = add i64 [[TMP11]], [[OFF_MUL_2]]
68; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP15]]
69; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr double, ptr [[TMP16]], i32 0
70; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP17]], align 8
71; CHECK-NEXT:    [[TMP18:%.*]] = add i64 [[TMP11]], [[OFF_MUL_3]]
72; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP18]]
73; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr double, ptr [[TMP19]], i32 0
74; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP20]], align 8
75; CHECK-NEXT:    [[TMP21:%.*]] = add i64 [[TMP11]], [[OFF_MUL_4]]
76; CHECK-NEXT:    [[TMP22:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP21]]
77; CHECK-NEXT:    [[TMP23:%.*]] = getelementptr double, ptr [[TMP22]], i32 0
78; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP23]], align 8
79; CHECK-NEXT:    [[TMP24:%.*]] = add i64 [[TMP11]], [[OFF_MUL_5]]
80; CHECK-NEXT:    [[TMP25:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP24]]
81; CHECK-NEXT:    [[TMP26:%.*]] = getelementptr double, ptr [[TMP25]], i32 0
82; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP26]], align 8
83; CHECK-NEXT:    [[TMP27:%.*]] = add i64 [[TMP11]], [[OFF_MUL_6]]
84; CHECK-NEXT:    [[TMP28:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP27]]
85; CHECK-NEXT:    [[TMP29:%.*]] = getelementptr double, ptr [[TMP28]], i32 0
86; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP29]], align 8
87; CHECK-NEXT:    [[TMP30:%.*]] = add i64 [[TMP11]], [[OFF_MUL_7]]
88; CHECK-NEXT:    [[TMP31:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP30]]
89; CHECK-NEXT:    [[TMP32:%.*]] = getelementptr double, ptr [[TMP31]], i32 0
90; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP32]], align 8
91; CHECK-NEXT:    [[TMP33:%.*]] = add i64 [[TMP11]], [[OFF_MUL_8]]
92; CHECK-NEXT:    [[TMP34:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP33]]
93; CHECK-NEXT:    [[TMP35:%.*]] = getelementptr double, ptr [[TMP34]], i32 0
94; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP35]], align 8
95; CHECK-NEXT:    [[TMP36:%.*]] = add i64 [[TMP11]], [[OFF_MUL_9]]
96; CHECK-NEXT:    [[TMP37:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP36]]
97; CHECK-NEXT:    [[TMP38:%.*]] = getelementptr double, ptr [[TMP37]], i32 0
98; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP38]], align 8
99; CHECK-NEXT:    [[TMP39:%.*]] = add i64 [[TMP11]], [[OFF_MUL_10]]
100; CHECK-NEXT:    [[TMP40:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP39]]
101; CHECK-NEXT:    [[TMP41:%.*]] = getelementptr double, ptr [[TMP40]], i32 0
102; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP41]], align 8
103; CHECK-NEXT:    [[TMP42:%.*]] = add i64 [[TMP11]], [[OFF_MUL_11]]
104; CHECK-NEXT:    [[TMP43:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP42]]
105; CHECK-NEXT:    [[TMP44:%.*]] = getelementptr double, ptr [[TMP43]], i32 0
106; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP44]], align 8
107; CHECK-NEXT:    [[TMP45:%.*]] = add i64 [[TMP11]], [[OFF_MUL_12]]
108; CHECK-NEXT:    [[TMP46:%.*]] = getelementptr i64, ptr [[DST]], i64 [[TMP45]]
109; CHECK-NEXT:    [[TMP47:%.*]] = getelementptr double, ptr [[TMP46]], i32 0
110; CHECK-NEXT:    store <4 x double> zeroinitializer, ptr [[TMP47]], align 8
111; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
112; CHECK-NEXT:    [[TMP48:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
113; CHECK-NEXT:    br i1 [[TMP48]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
114; CHECK:       middle.block:
115; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]
116; CHECK-NEXT:    br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]]
117; CHECK:       scalar.ph:
118; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[VECTOR_MEMCHECK]] ], [ 0, [[ENTRY:%.*]] ]
119; CHECK-NEXT:    br label [[LOOP:%.*]]
120; CHECK:       loop:
121; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
122; CHECK-NEXT:    [[IV_SUB_5:%.*]] = add nsw i64 [[IV]], -5
123; CHECK-NEXT:    [[IDX_1:%.*]] = add i64 [[IV_SUB_5]], [[OFF]]
124; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_1]]
125; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_1]], align 8
126; CHECK-NEXT:    [[IDX_2:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_2]]
127; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_2]]
128; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_2]], align 8
129; CHECK-NEXT:    [[IDX_3:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_3]]
130; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_3]]
131; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_3]], align 8
132; CHECK-NEXT:    [[IDX_4:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_4]]
133; CHECK-NEXT:    [[GEP_4:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_4]]
134; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_4]], align 8
135; CHECK-NEXT:    [[IDX_5:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_5]]
136; CHECK-NEXT:    [[GEP_5:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_5]]
137; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_5]], align 8
138; CHECK-NEXT:    [[IDX_6:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_6]]
139; CHECK-NEXT:    [[GEP_6:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_6]]
140; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_6]], align 8
141; CHECK-NEXT:    [[IDX_7:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_7]]
142; CHECK-NEXT:    [[GEP_7:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_7]]
143; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_7]], align 8
144; CHECK-NEXT:    [[IDX_8:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_8]]
145; CHECK-NEXT:    [[GEP_8:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_8]]
146; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_8]], align 8
147; CHECK-NEXT:    [[IDX_9:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_9]]
148; CHECK-NEXT:    [[GEP_9:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_9]]
149; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_9]], align 8
150; CHECK-NEXT:    [[IDX_10:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_10]]
151; CHECK-NEXT:    [[GEP_10:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_10]]
152; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_10]], align 8
153; CHECK-NEXT:    [[IDX_11:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_11]]
154; CHECK-NEXT:    [[GEP_11:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_11]]
155; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_11]], align 8
156; CHECK-NEXT:    [[IDX_12:%.*]] = add i64 [[IV_SUB_5]], [[OFF_MUL_12]]
157; CHECK-NEXT:    [[GEP_12:%.*]] = getelementptr i64, ptr [[DST]], i64 [[IDX_12]]
158; CHECK-NEXT:    store double 0.000000e+00, ptr [[GEP_12]], align 8
159; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
160; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]
161; CHECK-NEXT:    br i1 [[EC]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP3:![0-9]+]]
162; CHECK:       exit:
163; CHECK-NEXT:    ret void
164;
165entry:
166  %off.mul.2 = shl i64 %off, 1
167  %off.mul.3 = mul i64 %off, 3
168  %off.mul.4 = shl i64 %off, 2
169  %off.mul.5 = mul i64 %off, 5
170  %off.mul.6 = mul i64 %off, 6
171  %off.mul.7 = mul i64 %off, 7
172  %off.mul.8 = shl i64 %off, 3
173  %off.mul.9 = mul i64 %off, 9
174  %off.mul.10 = mul i64 %off, 10
175  %off.mul.11 = mul i64 %off, 11
176  %off.mul.12 = mul i64 %off, 12
177  br label %loop
178
179loop:
180  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
181  %iv.sub.5 = add nsw i64 %iv, -5
182  %idx.1 = add i64 %iv.sub.5, %off
183  %gep.1 = getelementptr i64, ptr %dst, i64 %idx.1
184  store double 0.000000e+00, ptr %gep.1, align 8
185  %idx.2 = add i64 %iv.sub.5, %off.mul.2
186  %gep.2 = getelementptr i64, ptr %dst, i64 %idx.2
187  store double 0.000000e+00, ptr %gep.2, align 8
188  %idx.3 = add i64 %iv.sub.5, %off.mul.3
189  %gep.3 = getelementptr i64, ptr %dst, i64 %idx.3
190  store double 0.000000e+00, ptr %gep.3, align 8
191  %idx.4 = add i64 %iv.sub.5, %off.mul.4
192  %gep.4 = getelementptr i64, ptr %dst, i64 %idx.4
193  store double 0.000000e+00, ptr %gep.4, align 8
194  %idx.5 = add i64 %iv.sub.5, %off.mul.5
195  %gep.5 = getelementptr i64, ptr %dst, i64 %idx.5
196  store double 0.000000e+00, ptr %gep.5, align 8
197  %idx.6 = add i64 %iv.sub.5, %off.mul.6
198  %gep.6 = getelementptr i64, ptr %dst, i64 %idx.6
199  store double 0.000000e+00, ptr %gep.6, align 8
200  %idx.7 = add i64 %iv.sub.5, %off.mul.7
201  %gep.7 = getelementptr i64, ptr %dst, i64 %idx.7
202  store double 0.000000e+00, ptr %gep.7, align 8
203  %idx.8 = add i64 %iv.sub.5, %off.mul.8
204  %gep.8 = getelementptr i64, ptr %dst, i64 %idx.8
205  store double 0.000000e+00, ptr %gep.8, align 8
206  %idx.9 = add i64 %iv.sub.5, %off.mul.9
207  %gep.9 = getelementptr i64, ptr %dst, i64 %idx.9
208  store double 0.000000e+00, ptr %gep.9, align 8
209  %idx.10 = add i64 %iv.sub.5, %off.mul.10
210  %gep.10 = getelementptr i64, ptr %dst, i64 %idx.10
211  store double 0.000000e+00, ptr %gep.10, align 8
212  %idx.11 = add i64 %iv.sub.5, %off.mul.11
213  %gep.11 = getelementptr i64, ptr %dst, i64 %idx.11
214  store double 0.000000e+00, ptr %gep.11, align 8
215  %idx.12 = add i64 %iv.sub.5, %off.mul.12
216  %gep.12 = getelementptr i64, ptr %dst, i64 %idx.12
217  store double 0.000000e+00, ptr %gep.12, align 8
218  %iv.next = add nuw nsw i64 %iv, 1
219  %ec = icmp eq i64 %iv.next, %N
220  br i1 %ec, label %exit, label %loop
221
222exit:
223  ret void
224}
225
226define void @check_creation_order(ptr %a, ptr %b, i32 %m) {
227; CHECK-LABEL: @check_creation_order(
228; CHECK-NEXT:  entry:
229; CHECK-NEXT:    [[B2:%.*]] = ptrtoint ptr [[B:%.*]] to i64
230; CHECK-NEXT:    [[A1:%.*]] = ptrtoint ptr [[A:%.*]] to i64
231; CHECK-NEXT:    [[M_EXT:%.*]] = sext i32 [[M:%.*]] to i64
232; CHECK-NEXT:    [[INVARIANT_GEP:%.*]] = getelementptr double, ptr [[A]], i64 [[M_EXT]]
233; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_MEMCHECK:%.*]]
234; CHECK:       vector.memcheck:
235; CHECK-NEXT:    [[TMP0:%.*]] = mul nsw i64 [[M_EXT]], -8
236; CHECK-NEXT:    [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP0]], 32
237; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 [[A1]], [[B2]]
238; CHECK-NEXT:    [[DIFF_CHECK3:%.*]] = icmp ult i64 [[TMP1]], 32
239; CHECK-NEXT:    [[CONFLICT_RDX:%.*]] = or i1 [[DIFF_CHECK]], [[DIFF_CHECK3]]
240; CHECK-NEXT:    br i1 [[CONFLICT_RDX]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]
241; CHECK:       vector.ph:
242; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
243; CHECK:       vector.body:
244; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
245; CHECK-NEXT:    [[TMP2:%.*]] = add i64 [[INDEX]], 0
246; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr double, ptr [[INVARIANT_GEP]], i64 [[TMP2]]
247; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr double, ptr [[TMP3]], i32 0
248; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <4 x double>, ptr [[TMP4]], align 8
249; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds double, ptr [[B]], i64 [[TMP2]]
250; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds double, ptr [[TMP5]], i32 0
251; CHECK-NEXT:    [[WIDE_LOAD4:%.*]] = load <4 x double>, ptr [[TMP6]], align 8
252; CHECK-NEXT:    [[TMP7:%.*]] = fadd <4 x double> [[WIDE_LOAD]], [[WIDE_LOAD4]]
253; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds double, ptr [[A]], i64 [[TMP2]]
254; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds double, ptr [[TMP8]], i32 0
255; CHECK-NEXT:    store <4 x double> [[TMP7]], ptr [[TMP9]], align 8
256; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
257; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 31996
258; CHECK-NEXT:    br i1 [[TMP10]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
259; CHECK:       middle.block:
260; CHECK-NEXT:    br i1 false, label [[EXIT:%.*]], label [[SCALAR_PH]]
261; CHECK:       scalar.ph:
262; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 31996, [[MIDDLE_BLOCK]] ], [ 0, [[VECTOR_MEMCHECK]] ], [ 0, [[ENTRY:%.*]] ]
263; CHECK-NEXT:    br label [[LOOP:%.*]]
264; CHECK:       loop:
265; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
266; CHECK-NEXT:    [[GEP:%.*]] = getelementptr double, ptr [[INVARIANT_GEP]], i64 [[IV]]
267; CHECK-NEXT:    [[L_0:%.*]] = load double, ptr [[GEP]], align 8
268; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds double, ptr [[B]], i64 [[IV]]
269; CHECK-NEXT:    [[L_1:%.*]] = load double, ptr [[GEP_B]], align 8
270; CHECK-NEXT:    [[ADD3:%.*]] = fadd double [[L_0]], [[L_1]]
271; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds double, ptr [[A]], i64 [[IV]]
272; CHECK-NEXT:    store double [[ADD3]], ptr [[GEP_A]], align 8
273; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
274; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 31999
275; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP5:![0-9]+]]
276; CHECK:       exit:
277; CHECK-NEXT:    ret void
278;
279entry:
280  %m.ext = sext i32 %m to i64
281  %invariant.gep = getelementptr double, ptr %a, i64 %m.ext
282  br label %loop
283
284loop:
285  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
286  %gep = getelementptr double, ptr %invariant.gep, i64 %iv
287  %l.0 = load double, ptr %gep, align 8
288  %gep.b = getelementptr inbounds double, ptr %b, i64 %iv
289  %l.1 = load double, ptr %gep.b, align 8
290  %add3 = fadd double %l.0, %l.1
291  %gep.a = getelementptr inbounds double, ptr %a, i64 %iv
292  store double %add3, ptr %gep.a, align 8
293  %iv.next = add nuw nsw i64 %iv, 1
294  %exitcond.not = icmp eq i64 %iv.next, 31999
295  br i1 %exitcond.not, label %exit, label %loop
296
297exit:
298  ret void
299}
300