xref: /llvm-project/llvm/test/Analysis/LoopAccessAnalysis/forked-pointers.ll (revision 1aee1e1f4c4b504becc06521546de992a662694b)
1; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 3
2; RUN: opt -disable-output -passes='print<access-info>' %s 2>&1 | FileCheck %s
3; RUN: opt -disable-output -passes='print<access-info>' -max-forked-scev-depth=2 %s 2>&1 | FileCheck -check-prefix=RECURSE %s
4
5target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
6
7define void @forked_ptrs_simple(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr %Dest) {
8; CHECK-LABEL: 'forked_ptrs_simple'
9; CHECK-NEXT:    loop:
10; CHECK-NEXT:      Memory dependences are safe with run-time checks
11; CHECK-NEXT:      Dependences:
12; CHECK-NEXT:      Run-time memory checks:
13; CHECK-NEXT:      Check 0:
14; CHECK-NEXT:        Comparing group ([[GRP1:0x[0-9a-f]+]]):
15; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
16; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
17; CHECK-NEXT:        Against group ([[GRP2:0x[0-9a-f]+]]):
18; CHECK-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
19; CHECK-NEXT:      Check 1:
20; CHECK-NEXT:        Comparing group ([[GRP1]]):
21; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
22; CHECK-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
23; CHECK-NEXT:        Against group ([[GRP3:0x[0-9a-f]+]]):
24; CHECK-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
25; CHECK-NEXT:      Grouped accesses:
26; CHECK-NEXT:        Group [[GRP1]]:
27; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
28; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
29; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
30; CHECK-NEXT:        Group [[GRP2]]:
31; CHECK-NEXT:          (Low: %Base1 High: (400 + %Base1))
32; CHECK-NEXT:            Member: {%Base1,+,4}<nw><%loop>
33; CHECK-NEXT:        Group [[GRP3]]:
34; CHECK-NEXT:          (Low: %Base2 High: (400 + %Base2))
35; CHECK-NEXT:            Member: {%Base2,+,4}<nw><%loop>
36; CHECK-EMPTY:
37; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
38; CHECK-NEXT:      SCEV assumptions:
39; CHECK-EMPTY:
40; CHECK-NEXT:      Expressions re-written:
41;
42; RECURSE-LABEL: 'forked_ptrs_simple'
43; RECURSE-NEXT:    loop:
44; RECURSE-NEXT:      Memory dependences are safe with run-time checks
45; RECURSE-NEXT:      Dependences:
46; RECURSE-NEXT:      Run-time memory checks:
47; RECURSE-NEXT:      Check 0:
48; RECURSE-NEXT:        Comparing group ([[GRP4:0x[0-9a-f]+]]):
49; RECURSE-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
50; RECURSE-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
51; RECURSE-NEXT:        Against group ([[GRP5:0x[0-9a-f]+]]):
52; RECURSE-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
53; RECURSE-NEXT:      Check 1:
54; RECURSE-NEXT:        Comparing group ([[GRP4]]):
55; RECURSE-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
56; RECURSE-NEXT:          %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
57; RECURSE-NEXT:        Against group ([[GRP6:0x[0-9a-f]+]]):
58; RECURSE-NEXT:          %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
59; RECURSE-NEXT:      Grouped accesses:
60; RECURSE-NEXT:        Group [[GRP4]]:
61; RECURSE-NEXT:          (Low: %Dest High: (400 + %Dest))
62; RECURSE-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
63; RECURSE-NEXT:            Member: {%Dest,+,4}<nuw><%loop>
64; RECURSE-NEXT:        Group [[GRP5]]:
65; RECURSE-NEXT:          (Low: %Base1 High: (400 + %Base1))
66; RECURSE-NEXT:            Member: {%Base1,+,4}<nw><%loop>
67; RECURSE-NEXT:        Group [[GRP6]]:
68; RECURSE-NEXT:          (Low: %Base2 High: (400 + %Base2))
69; RECURSE-NEXT:            Member: {%Base2,+,4}<nw><%loop>
70; RECURSE-EMPTY:
71; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
72; RECURSE-NEXT:      SCEV assumptions:
73; RECURSE-EMPTY:
74; RECURSE-NEXT:      Expressions re-written:
75;
76entry:
77  br label %loop
78
79loop:
80  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
81  %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
82  %l.Dest = load float, ptr %gep.Dest
83  %cmp = fcmp une float %l.Dest, 0.0
84  %gep.1 = getelementptr inbounds float, ptr %Base1, i64 %iv
85  %gep.2 = getelementptr inbounds float, ptr %Base2, i64 %iv
86  %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
87  %sink = load float, ptr %select, align 4
88  store float %sink, ptr %gep.Dest, align 4
89  %iv.next = add nuw nsw i64 %iv, 1
90  %exitcond.not = icmp eq i64 %iv.next, 100
91  br i1 %exitcond.not, label %exit, label %loop
92
93exit:
94  ret void
95}
96
97;; We have a limit on the recursion depth for finding a loop invariant or
98;; addrec term; confirm we won't exceed that depth by forcing a lower
99;; limit via -max-forked-scev-depth=2
100
101;;;; Derived from the following C code
102;; void forked_ptrs_different_base_same_offset(float *A, float *B, float *C, int *D) {
103;;   for (int i=0; i<100; i++) {
104;;     if (D[i] != 0) {
105;;       C[i] = A[i];
106;;     } else {
107;;       C[i] = B[i];
108;;     }
109;;   }
110;; }
111
112define dso_local void @forked_ptrs_different_base_same_offset(ptr nocapture readonly nonnull %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
113; CHECK-LABEL: 'forked_ptrs_different_base_same_offset'
114; CHECK-NEXT:    for.body:
115; CHECK-NEXT:      Memory dependences are safe with run-time checks
116; CHECK-NEXT:      Dependences:
117; CHECK-NEXT:      Run-time memory checks:
118; CHECK-NEXT:      Check 0:
119; CHECK-NEXT:        Comparing group ([[GRP7:0x[0-9a-f]+]]):
120; CHECK-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
121; CHECK-NEXT:        Against group ([[GRP8:0x[0-9a-f]+]]):
122; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
123; CHECK-NEXT:      Check 1:
124; CHECK-NEXT:        Comparing group ([[GRP7]]):
125; CHECK-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
126; CHECK-NEXT:        Against group ([[GRP9:0x[0-9a-f]+]]):
127; CHECK-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
128; CHECK-NEXT:      Check 2:
129; CHECK-NEXT:        Comparing group ([[GRP7]]):
130; CHECK-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
131; CHECK-NEXT:        Against group ([[GRP10:0x[0-9a-f]+]]):
132; CHECK-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
133; CHECK-NEXT:      Grouped accesses:
134; CHECK-NEXT:        Group [[GRP7]]:
135; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
136; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%for.body>
137; CHECK-NEXT:        Group [[GRP8]]:
138; CHECK-NEXT:          (Low: %Preds High: (400 + %Preds))
139; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
140; CHECK-NEXT:        Group [[GRP9]]:
141; CHECK-NEXT:          (Low: %Base2 High: (400 + %Base2))
142; CHECK-NEXT:            Member: {%Base2,+,4}<nw><%for.body>
143; CHECK-NEXT:        Group [[GRP10]]:
144; CHECK-NEXT:          (Low: %Base1 High: (400 + %Base1))
145; CHECK-NEXT:            Member: {%Base1,+,4}<nw><%for.body>
146; CHECK-EMPTY:
147; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
148; CHECK-NEXT:      SCEV assumptions:
149; CHECK-EMPTY:
150; CHECK-NEXT:      Expressions re-written:
151;
152; RECURSE-LABEL: 'forked_ptrs_different_base_same_offset'
153; RECURSE-NEXT:    for.body:
154; RECURSE-NEXT:      Memory dependences are safe with run-time checks
155; RECURSE-NEXT:      Dependences:
156; RECURSE-NEXT:      Run-time memory checks:
157; RECURSE-NEXT:      Check 0:
158; RECURSE-NEXT:        Comparing group ([[GRP11:0x[0-9a-f]+]]):
159; RECURSE-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
160; RECURSE-NEXT:        Against group ([[GRP12:0x[0-9a-f]+]]):
161; RECURSE-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
162; RECURSE-NEXT:      Check 1:
163; RECURSE-NEXT:        Comparing group ([[GRP11]]):
164; RECURSE-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
165; RECURSE-NEXT:        Against group ([[GRP13:0x[0-9a-f]+]]):
166; RECURSE-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
167; RECURSE-NEXT:      Check 2:
168; RECURSE-NEXT:        Comparing group ([[GRP11]]):
169; RECURSE-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
170; RECURSE-NEXT:        Against group ([[GRP14:0x[0-9a-f]+]]):
171; RECURSE-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
172; RECURSE-NEXT:      Grouped accesses:
173; RECURSE-NEXT:        Group [[GRP11]]:
174; RECURSE-NEXT:          (Low: %Dest High: (400 + %Dest))
175; RECURSE-NEXT:            Member: {%Dest,+,4}<nuw><%for.body>
176; RECURSE-NEXT:        Group [[GRP12]]:
177; RECURSE-NEXT:          (Low: %Preds High: (400 + %Preds))
178; RECURSE-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
179; RECURSE-NEXT:        Group [[GRP13]]:
180; RECURSE-NEXT:          (Low: %Base2 High: (400 + %Base2))
181; RECURSE-NEXT:            Member: {%Base2,+,4}<nw><%for.body>
182; RECURSE-NEXT:        Group [[GRP14]]:
183; RECURSE-NEXT:          (Low: %Base1 High: (400 + %Base1))
184; RECURSE-NEXT:            Member: {%Base1,+,4}<nw><%for.body>
185; RECURSE-EMPTY:
186; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
187; RECURSE-NEXT:      SCEV assumptions:
188; RECURSE-EMPTY:
189; RECURSE-NEXT:      Expressions re-written:
190;
191entry:
192  br label %for.body
193
194for.cond.cleanup:
195  ret void
196
197for.body:
198  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
199  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
200  %0 = load i32, ptr %arrayidx, align 4
201  %cmp1.not = icmp eq i32 %0, 0
202  %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1
203  %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
204  %.sink = load float, ptr %.sink.in, align 4
205  %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
206  store float %.sink, ptr %1, align 4
207  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
208  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
209  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
210}
211
212define dso_local void @forked_ptrs_different_base_same_offset_64b(ptr nocapture readonly nonnull %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
213; CHECK-LABEL: 'forked_ptrs_different_base_same_offset_64b'
214; CHECK-NEXT:    for.body:
215; CHECK-NEXT:      Memory dependences are safe with run-time checks
216; CHECK-NEXT:      Dependences:
217; CHECK-NEXT:      Run-time memory checks:
218; CHECK-NEXT:      Check 0:
219; CHECK-NEXT:        Comparing group ([[GRP15:0x[0-9a-f]+]]):
220; CHECK-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
221; CHECK-NEXT:        Against group ([[GRP16:0x[0-9a-f]+]]):
222; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
223; CHECK-NEXT:      Check 1:
224; CHECK-NEXT:        Comparing group ([[GRP15]]):
225; CHECK-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
226; CHECK-NEXT:        Against group ([[GRP17:0x[0-9a-f]+]]):
227; CHECK-NEXT:          %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
228; CHECK-NEXT:      Check 2:
229; CHECK-NEXT:        Comparing group ([[GRP15]]):
230; CHECK-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
231; CHECK-NEXT:        Against group ([[GRP18:0x[0-9a-f]+]]):
232; CHECK-NEXT:          %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
233; CHECK-NEXT:      Grouped accesses:
234; CHECK-NEXT:        Group [[GRP15]]:
235; CHECK-NEXT:          (Low: %Dest High: (800 + %Dest))
236; CHECK-NEXT:            Member: {%Dest,+,8}<nuw><%for.body>
237; CHECK-NEXT:        Group [[GRP16]]:
238; CHECK-NEXT:          (Low: %Preds High: (400 + %Preds))
239; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
240; CHECK-NEXT:        Group [[GRP17]]:
241; CHECK-NEXT:          (Low: %Base2 High: (800 + %Base2))
242; CHECK-NEXT:            Member: {%Base2,+,8}<nw><%for.body>
243; CHECK-NEXT:        Group [[GRP18]]:
244; CHECK-NEXT:          (Low: %Base1 High: (800 + %Base1))
245; CHECK-NEXT:            Member: {%Base1,+,8}<nw><%for.body>
246; CHECK-EMPTY:
247; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
248; CHECK-NEXT:      SCEV assumptions:
249; CHECK-EMPTY:
250; CHECK-NEXT:      Expressions re-written:
251;
252; RECURSE-LABEL: 'forked_ptrs_different_base_same_offset_64b'
253; RECURSE-NEXT:    for.body:
254; RECURSE-NEXT:      Memory dependences are safe with run-time checks
255; RECURSE-NEXT:      Dependences:
256; RECURSE-NEXT:      Run-time memory checks:
257; RECURSE-NEXT:      Check 0:
258; RECURSE-NEXT:        Comparing group ([[GRP19:0x[0-9a-f]+]]):
259; RECURSE-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
260; RECURSE-NEXT:        Against group ([[GRP20:0x[0-9a-f]+]]):
261; RECURSE-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
262; RECURSE-NEXT:      Check 1:
263; RECURSE-NEXT:        Comparing group ([[GRP19]]):
264; RECURSE-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
265; RECURSE-NEXT:        Against group ([[GRP21:0x[0-9a-f]+]]):
266; RECURSE-NEXT:          %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
267; RECURSE-NEXT:      Check 2:
268; RECURSE-NEXT:        Comparing group ([[GRP19]]):
269; RECURSE-NEXT:          %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
270; RECURSE-NEXT:        Against group ([[GRP22:0x[0-9a-f]+]]):
271; RECURSE-NEXT:          %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
272; RECURSE-NEXT:      Grouped accesses:
273; RECURSE-NEXT:        Group [[GRP19]]:
274; RECURSE-NEXT:          (Low: %Dest High: (800 + %Dest))
275; RECURSE-NEXT:            Member: {%Dest,+,8}<nuw><%for.body>
276; RECURSE-NEXT:        Group [[GRP20]]:
277; RECURSE-NEXT:          (Low: %Preds High: (400 + %Preds))
278; RECURSE-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
279; RECURSE-NEXT:        Group [[GRP21]]:
280; RECURSE-NEXT:          (Low: %Base2 High: (800 + %Base2))
281; RECURSE-NEXT:            Member: {%Base2,+,8}<nw><%for.body>
282; RECURSE-NEXT:        Group [[GRP22]]:
283; RECURSE-NEXT:          (Low: %Base1 High: (800 + %Base1))
284; RECURSE-NEXT:            Member: {%Base1,+,8}<nw><%for.body>
285; RECURSE-EMPTY:
286; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
287; RECURSE-NEXT:      SCEV assumptions:
288; RECURSE-EMPTY:
289; RECURSE-NEXT:      Expressions re-written:
290;
291entry:
292  br label %for.body
293
294for.cond.cleanup:
295  ret void
296
297for.body:
298  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
299  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
300  %0 = load i32, ptr %arrayidx, align 4
301  %cmp1.not = icmp eq i32 %0, 0
302  %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1
303  %.sink.in = getelementptr inbounds double, ptr %spec.select, i64 %indvars.iv
304  %.sink = load double, ptr %.sink.in, align 8
305  %1 = getelementptr inbounds double, ptr %Dest, i64 %indvars.iv
306  store double %.sink, ptr %1, align 8
307  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
308  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
309  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
310}
311
312define dso_local void @forked_ptrs_different_base_same_offset_23b(ptr nocapture readonly nonnull %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
313; CHECK-LABEL: 'forked_ptrs_different_base_same_offset_23b'
314; CHECK-NEXT:    for.body:
315; CHECK-NEXT:      Memory dependences are safe with run-time checks
316; CHECK-NEXT:      Dependences:
317; CHECK-NEXT:      Run-time memory checks:
318; CHECK-NEXT:      Check 0:
319; CHECK-NEXT:        Comparing group ([[GRP23:0x[0-9a-f]+]]):
320; CHECK-NEXT:          %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv
321; CHECK-NEXT:        Against group ([[GRP24:0x[0-9a-f]+]]):
322; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
323; CHECK-NEXT:      Check 1:
324; CHECK-NEXT:        Comparing group ([[GRP23]]):
325; CHECK-NEXT:          %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv
326; CHECK-NEXT:        Against group ([[GRP25:0x[0-9a-f]+]]):
327; CHECK-NEXT:          %.sink.in = getelementptr inbounds i23, ptr %spec.select, i64 %indvars.iv
328; CHECK-NEXT:      Check 2:
329; CHECK-NEXT:        Comparing group ([[GRP23]]):
330; CHECK-NEXT:          %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv
331; CHECK-NEXT:        Against group ([[GRP26:0x[0-9a-f]+]]):
332; CHECK-NEXT:          %.sink.in = getelementptr inbounds i23, ptr %spec.select, i64 %indvars.iv
333; CHECK-NEXT:      Grouped accesses:
334; CHECK-NEXT:        Group [[GRP23]]:
335; CHECK-NEXT:          (Low: %Dest High: (399 + %Dest))
336; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%for.body>
337; CHECK-NEXT:        Group [[GRP24]]:
338; CHECK-NEXT:          (Low: %Preds High: (400 + %Preds))
339; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
340; CHECK-NEXT:        Group [[GRP25]]:
341; CHECK-NEXT:          (Low: %Base2 High: (399 + %Base2))
342; CHECK-NEXT:            Member: {%Base2,+,4}<nw><%for.body>
343; CHECK-NEXT:        Group [[GRP26]]:
344; CHECK-NEXT:          (Low: %Base1 High: (399 + %Base1))
345; CHECK-NEXT:            Member: {%Base1,+,4}<nw><%for.body>
346; CHECK-EMPTY:
347; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
348; CHECK-NEXT:      SCEV assumptions:
349; CHECK-EMPTY:
350; CHECK-NEXT:      Expressions re-written:
351;
352; RECURSE-LABEL: 'forked_ptrs_different_base_same_offset_23b'
353; RECURSE-NEXT:    for.body:
354; RECURSE-NEXT:      Memory dependences are safe with run-time checks
355; RECURSE-NEXT:      Dependences:
356; RECURSE-NEXT:      Run-time memory checks:
357; RECURSE-NEXT:      Check 0:
358; RECURSE-NEXT:        Comparing group ([[GRP27:0x[0-9a-f]+]]):
359; RECURSE-NEXT:          %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv
360; RECURSE-NEXT:        Against group ([[GRP28:0x[0-9a-f]+]]):
361; RECURSE-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
362; RECURSE-NEXT:      Check 1:
363; RECURSE-NEXT:        Comparing group ([[GRP27]]):
364; RECURSE-NEXT:          %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv
365; RECURSE-NEXT:        Against group ([[GRP29:0x[0-9a-f]+]]):
366; RECURSE-NEXT:          %.sink.in = getelementptr inbounds i23, ptr %spec.select, i64 %indvars.iv
367; RECURSE-NEXT:      Check 2:
368; RECURSE-NEXT:        Comparing group ([[GRP27]]):
369; RECURSE-NEXT:          %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv
370; RECURSE-NEXT:        Against group ([[GRP30:0x[0-9a-f]+]]):
371; RECURSE-NEXT:          %.sink.in = getelementptr inbounds i23, ptr %spec.select, i64 %indvars.iv
372; RECURSE-NEXT:      Grouped accesses:
373; RECURSE-NEXT:        Group [[GRP27]]:
374; RECURSE-NEXT:          (Low: %Dest High: (399 + %Dest))
375; RECURSE-NEXT:            Member: {%Dest,+,4}<nuw><%for.body>
376; RECURSE-NEXT:        Group [[GRP28]]:
377; RECURSE-NEXT:          (Low: %Preds High: (400 + %Preds))
378; RECURSE-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
379; RECURSE-NEXT:        Group [[GRP29]]:
380; RECURSE-NEXT:          (Low: %Base2 High: (399 + %Base2))
381; RECURSE-NEXT:            Member: {%Base2,+,4}<nw><%for.body>
382; RECURSE-NEXT:        Group [[GRP30]]:
383; RECURSE-NEXT:          (Low: %Base1 High: (399 + %Base1))
384; RECURSE-NEXT:            Member: {%Base1,+,4}<nw><%for.body>
385; RECURSE-EMPTY:
386; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
387; RECURSE-NEXT:      SCEV assumptions:
388; RECURSE-EMPTY:
389; RECURSE-NEXT:      Expressions re-written:
390;
391entry:
392  br label %for.body
393
394for.cond.cleanup:
395  ret void
396
397for.body:
398  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
399  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
400  %0 = load i32, ptr %arrayidx, align 4
401  %cmp1.not = icmp eq i32 %0, 0
402  %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1
403  %.sink.in = getelementptr inbounds i23, ptr %spec.select, i64 %indvars.iv
404  %.sink = load i23, ptr %.sink.in
405  %1 = getelementptr inbounds i23, ptr %Dest, i64 %indvars.iv
406  store i23 %.sink, ptr %1
407  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
408  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
409  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
410}
411
412define dso_local void @forked_ptrs_different_base_same_offset_6b(ptr nocapture readonly nonnull %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
413; CHECK-LABEL: 'forked_ptrs_different_base_same_offset_6b'
414; CHECK-NEXT:    for.body:
415; CHECK-NEXT:      Memory dependences are safe with run-time checks
416; CHECK-NEXT:      Dependences:
417; CHECK-NEXT:      Run-time memory checks:
418; CHECK-NEXT:      Check 0:
419; CHECK-NEXT:        Comparing group ([[GRP31:0x[0-9a-f]+]]):
420; CHECK-NEXT:          %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv
421; CHECK-NEXT:        Against group ([[GRP32:0x[0-9a-f]+]]):
422; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
423; CHECK-NEXT:      Check 1:
424; CHECK-NEXT:        Comparing group ([[GRP31]]):
425; CHECK-NEXT:          %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv
426; CHECK-NEXT:        Against group ([[GRP33:0x[0-9a-f]+]]):
427; CHECK-NEXT:          %.sink.in = getelementptr inbounds i6, ptr %spec.select, i64 %indvars.iv
428; CHECK-NEXT:      Check 2:
429; CHECK-NEXT:        Comparing group ([[GRP31]]):
430; CHECK-NEXT:          %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv
431; CHECK-NEXT:        Against group ([[GRP34:0x[0-9a-f]+]]):
432; CHECK-NEXT:          %.sink.in = getelementptr inbounds i6, ptr %spec.select, i64 %indvars.iv
433; CHECK-NEXT:      Grouped accesses:
434; CHECK-NEXT:        Group [[GRP31]]:
435; CHECK-NEXT:          (Low: %Dest High: (100 + %Dest))
436; CHECK-NEXT:            Member: {%Dest,+,1}<nuw><%for.body>
437; CHECK-NEXT:        Group [[GRP32]]:
438; CHECK-NEXT:          (Low: %Preds High: (400 + %Preds))
439; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
440; CHECK-NEXT:        Group [[GRP33]]:
441; CHECK-NEXT:          (Low: %Base2 High: (100 + %Base2))
442; CHECK-NEXT:            Member: {%Base2,+,1}<nw><%for.body>
443; CHECK-NEXT:        Group [[GRP34]]:
444; CHECK-NEXT:          (Low: %Base1 High: (100 + %Base1))
445; CHECK-NEXT:            Member: {%Base1,+,1}<nw><%for.body>
446; CHECK-EMPTY:
447; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
448; CHECK-NEXT:      SCEV assumptions:
449; CHECK-EMPTY:
450; CHECK-NEXT:      Expressions re-written:
451;
452; RECURSE-LABEL: 'forked_ptrs_different_base_same_offset_6b'
453; RECURSE-NEXT:    for.body:
454; RECURSE-NEXT:      Memory dependences are safe with run-time checks
455; RECURSE-NEXT:      Dependences:
456; RECURSE-NEXT:      Run-time memory checks:
457; RECURSE-NEXT:      Check 0:
458; RECURSE-NEXT:        Comparing group ([[GRP35:0x[0-9a-f]+]]):
459; RECURSE-NEXT:          %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv
460; RECURSE-NEXT:        Against group ([[GRP36:0x[0-9a-f]+]]):
461; RECURSE-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
462; RECURSE-NEXT:      Check 1:
463; RECURSE-NEXT:        Comparing group ([[GRP35]]):
464; RECURSE-NEXT:          %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv
465; RECURSE-NEXT:        Against group ([[GRP37:0x[0-9a-f]+]]):
466; RECURSE-NEXT:          %.sink.in = getelementptr inbounds i6, ptr %spec.select, i64 %indvars.iv
467; RECURSE-NEXT:      Check 2:
468; RECURSE-NEXT:        Comparing group ([[GRP35]]):
469; RECURSE-NEXT:          %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv
470; RECURSE-NEXT:        Against group ([[GRP38:0x[0-9a-f]+]]):
471; RECURSE-NEXT:          %.sink.in = getelementptr inbounds i6, ptr %spec.select, i64 %indvars.iv
472; RECURSE-NEXT:      Grouped accesses:
473; RECURSE-NEXT:        Group [[GRP35]]:
474; RECURSE-NEXT:          (Low: %Dest High: (100 + %Dest))
475; RECURSE-NEXT:            Member: {%Dest,+,1}<nuw><%for.body>
476; RECURSE-NEXT:        Group [[GRP36]]:
477; RECURSE-NEXT:          (Low: %Preds High: (400 + %Preds))
478; RECURSE-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
479; RECURSE-NEXT:        Group [[GRP37]]:
480; RECURSE-NEXT:          (Low: %Base2 High: (100 + %Base2))
481; RECURSE-NEXT:            Member: {%Base2,+,1}<nw><%for.body>
482; RECURSE-NEXT:        Group [[GRP38]]:
483; RECURSE-NEXT:          (Low: %Base1 High: (100 + %Base1))
484; RECURSE-NEXT:            Member: {%Base1,+,1}<nw><%for.body>
485; RECURSE-EMPTY:
486; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
487; RECURSE-NEXT:      SCEV assumptions:
488; RECURSE-EMPTY:
489; RECURSE-NEXT:      Expressions re-written:
490;
491entry:
492  br label %for.body
493
494for.cond.cleanup:
495  ret void
496
497for.body:
498  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
499  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
500  %0 = load i32, ptr %arrayidx, align 4
501  %cmp1.not = icmp eq i32 %0, 0
502  %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1
503  %.sink.in = getelementptr inbounds i6, ptr %spec.select, i64 %indvars.iv
504  %.sink = load i6, ptr %.sink.in
505  %1 = getelementptr inbounds i6, ptr %Dest, i64 %indvars.iv
506  store i6 %.sink, ptr %1
507  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
508  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
509  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
510}
511
512define dso_local void @forked_ptrs_different_base_same_offset_possible_poison(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds, i1 %c) {
513; CHECK-LABEL: 'forked_ptrs_different_base_same_offset_possible_poison'
514; CHECK-NEXT:    for.body:
515; CHECK-NEXT:      Memory dependences are safe with run-time checks
516; CHECK-NEXT:      Dependences:
517; CHECK-NEXT:      Run-time memory checks:
518; CHECK-NEXT:      Check 0:
519; CHECK-NEXT:        Comparing group ([[GRP39:0x[0-9a-f]+]]):
520; CHECK-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
521; CHECK-NEXT:        Against group ([[GRP40:0x[0-9a-f]+]]):
522; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
523; CHECK-NEXT:      Check 1:
524; CHECK-NEXT:        Comparing group ([[GRP39]]):
525; CHECK-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
526; CHECK-NEXT:        Against group ([[GRP41:0x[0-9a-f]+]]):
527; CHECK-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
528; CHECK-NEXT:      Check 2:
529; CHECK-NEXT:        Comparing group ([[GRP39]]):
530; CHECK-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
531; CHECK-NEXT:        Against group ([[GRP42:0x[0-9a-f]+]]):
532; CHECK-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
533; CHECK-NEXT:      Grouped accesses:
534; CHECK-NEXT:        Group [[GRP39]]:
535; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
536; CHECK-NEXT:            Member: {%Dest,+,4}<nw><%for.body>
537; CHECK-NEXT:        Group [[GRP40]]:
538; CHECK-NEXT:          (Low: %Preds High: (400 + %Preds))
539; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
540; CHECK-NEXT:        Group [[GRP41]]:
541; CHECK-NEXT:          (Low: %Base2 High: (400 + %Base2))
542; CHECK-NEXT:            Member: {%Base2,+,4}<nw><%for.body>
543; CHECK-NEXT:        Group [[GRP42]]:
544; CHECK-NEXT:          (Low: %Base1 High: (400 + %Base1))
545; CHECK-NEXT:            Member: {%Base1,+,4}<nw><%for.body>
546; CHECK-EMPTY:
547; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
548; CHECK-NEXT:      SCEV assumptions:
549; CHECK-EMPTY:
550; CHECK-NEXT:      Expressions re-written:
551;
552; RECURSE-LABEL: 'forked_ptrs_different_base_same_offset_possible_poison'
553; RECURSE-NEXT:    for.body:
554; RECURSE-NEXT:      Memory dependences are safe with run-time checks
555; RECURSE-NEXT:      Dependences:
556; RECURSE-NEXT:      Run-time memory checks:
557; RECURSE-NEXT:      Check 0:
558; RECURSE-NEXT:        Comparing group ([[GRP43:0x[0-9a-f]+]]):
559; RECURSE-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
560; RECURSE-NEXT:        Against group ([[GRP44:0x[0-9a-f]+]]):
561; RECURSE-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
562; RECURSE-NEXT:      Check 1:
563; RECURSE-NEXT:        Comparing group ([[GRP43]]):
564; RECURSE-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
565; RECURSE-NEXT:        Against group ([[GRP45:0x[0-9a-f]+]]):
566; RECURSE-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
567; RECURSE-NEXT:      Check 2:
568; RECURSE-NEXT:        Comparing group ([[GRP43]]):
569; RECURSE-NEXT:          %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
570; RECURSE-NEXT:        Against group ([[GRP46:0x[0-9a-f]+]]):
571; RECURSE-NEXT:          %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
572; RECURSE-NEXT:      Grouped accesses:
573; RECURSE-NEXT:        Group [[GRP43]]:
574; RECURSE-NEXT:          (Low: %Dest High: (400 + %Dest))
575; RECURSE-NEXT:            Member: {%Dest,+,4}<nw><%for.body>
576; RECURSE-NEXT:        Group [[GRP44]]:
577; RECURSE-NEXT:          (Low: %Preds High: (400 + %Preds))
578; RECURSE-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
579; RECURSE-NEXT:        Group [[GRP45]]:
580; RECURSE-NEXT:          (Low: %Base2 High: (400 + %Base2))
581; RECURSE-NEXT:            Member: {%Base2,+,4}<nw><%for.body>
582; RECURSE-NEXT:        Group [[GRP46]]:
583; RECURSE-NEXT:          (Low: %Base1 High: (400 + %Base1))
584; RECURSE-NEXT:            Member: {%Base1,+,4}<nw><%for.body>
585; RECURSE-EMPTY:
586; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
587; RECURSE-NEXT:      SCEV assumptions:
588; RECURSE-EMPTY:
589; RECURSE-NEXT:      Expressions re-written:
590;
591entry:
592  br label %for.body
593
594for.cond.cleanup:
595  ret void
596
597for.body:
598  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %latch ]
599  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
600  %0 = load i32, ptr %arrayidx, align 4
601  %cmp1.not = icmp eq i32 %0, 0
602  %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1
603  %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %indvars.iv
604  %.sink = load float, ptr %.sink.in, align 4
605  %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
606  br i1 %c, label %then, label %latch
607
608then:
609  store float %.sink, ptr %1, align 4
610  br label %latch
611
612latch:
613  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
614  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
615  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
616}
617
618;;;; Derived from the following C code
619;; void forked_ptrs_same_base_different_offset(float *A, float *B, int *C) {
620;;   int offset;
621;;   for (int i = 0; i < 100; i++) {
622;;     if (C[i] != 0)
623;;       offset = i;
624;;     else
625;;       offset = i+1;
626;;     B[i] = A[offset];
627;;   }
628;; }
629
630define dso_local void @forked_ptrs_same_base_different_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
631; CHECK-LABEL: 'forked_ptrs_same_base_different_offset'
632; CHECK-NEXT:    for.body:
633; CHECK-NEXT:      Report: cannot identify array bounds
634; CHECK-NEXT:      Dependences:
635; CHECK-NEXT:      Run-time memory checks:
636; CHECK-NEXT:      Grouped accesses:
637; CHECK-EMPTY:
638; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
639; CHECK-NEXT:      SCEV assumptions:
640; CHECK-EMPTY:
641; CHECK-NEXT:      Expressions re-written:
642;
643; RECURSE-LABEL: 'forked_ptrs_same_base_different_offset'
644; RECURSE-NEXT:    for.body:
645; RECURSE-NEXT:      Report: cannot identify array bounds
646; RECURSE-NEXT:      Dependences:
647; RECURSE-NEXT:      Run-time memory checks:
648; RECURSE-NEXT:      Grouped accesses:
649; RECURSE-EMPTY:
650; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
651; RECURSE-NEXT:      SCEV assumptions:
652; RECURSE-EMPTY:
653; RECURSE-NEXT:      Expressions re-written:
654;
655entry:
656  br label %for.body
657
658for.cond.cleanup:                                 ; preds = %for.body
659  ret void
660
661for.body:                                         ; preds = %entry, %for.body
662  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
663  %i.014 = phi i32 [ 0, %entry ], [ %add, %for.body ]
664  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
665  %0 = load i32, ptr %arrayidx, align 4
666  %cmp1.not = icmp eq i32 %0, 0
667  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
668  %add = add nuw nsw i32 %i.014, 1
669  %1 = trunc i64 %indvars.iv to i32
670  %offset.0 = select i1 %cmp1.not, i32 %add, i32 %1
671  %idxprom213 = zext i32 %offset.0 to i64
672  %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %idxprom213
673  %2 = load float, ptr %arrayidx3, align 4
674  %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
675  store float %2, ptr %arrayidx5, align 4
676  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
677  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
678}
679
680define dso_local void @forked_ptrs_add_to_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds, i64 %extra_offset) {
681; CHECK-LABEL: 'forked_ptrs_add_to_offset'
682; CHECK-NEXT:    for.body:
683; CHECK-NEXT:      Memory dependences are safe with run-time checks
684; CHECK-NEXT:      Dependences:
685; CHECK-NEXT:      Run-time memory checks:
686; CHECK-NEXT:      Check 0:
687; CHECK-NEXT:        Comparing group ([[GRP47:0x[0-9a-f]+]]):
688; CHECK-NEXT:          %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
689; CHECK-NEXT:        Against group ([[GRP48:0x[0-9a-f]+]]):
690; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
691; CHECK-NEXT:      Check 1:
692; CHECK-NEXT:        Comparing group ([[GRP47]]):
693; CHECK-NEXT:          %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
694; CHECK-NEXT:        Against group ([[GRP49:0x[0-9a-f]+]]):
695; CHECK-NEXT:          %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset
696; CHECK-NEXT:          %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset
697; CHECK-NEXT:      Grouped accesses:
698; CHECK-NEXT:        Group [[GRP47]]:
699; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
700; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%for.body>
701; CHECK-NEXT:        Group [[GRP48]]:
702; CHECK-NEXT:          (Low: %Preds High: (400 + %Preds))
703; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
704; CHECK-NEXT:        Group [[GRP49]]:
705; CHECK-NEXT:          (Low: ((4 * %extra_offset) + %Base) High: (404 + (4 * %extra_offset) + %Base))
706; CHECK-NEXT:            Member: {(4 + (4 * %extra_offset) + %Base),+,4}<%for.body>
707; CHECK-NEXT:            Member: {((4 * %extra_offset) + %Base),+,4}<%for.body>
708; CHECK-EMPTY:
709; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
710; CHECK-NEXT:      SCEV assumptions:
711; CHECK-EMPTY:
712; CHECK-NEXT:      Expressions re-written:
713;
714; RECURSE-LABEL: 'forked_ptrs_add_to_offset'
715; RECURSE-NEXT:    for.body:
716; RECURSE-NEXT:      Report: cannot identify array bounds
717; RECURSE-NEXT:      Dependences:
718; RECURSE-NEXT:      Run-time memory checks:
719; RECURSE-NEXT:      Grouped accesses:
720; RECURSE-EMPTY:
721; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
722; RECURSE-NEXT:      SCEV assumptions:
723; RECURSE-EMPTY:
724; RECURSE-NEXT:      Expressions re-written:
725;
726entry:
727  br label %for.body
728
729for.cond.cleanup:                                 ; preds = %for.body
730  ret void
731
732for.body:                                         ; preds = %entry, %for.body
733  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
734  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
735  %0 = load i32, ptr %arrayidx, align 4
736  %cmp.not = icmp eq i32 %0, 0
737  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
738  %sel = select i1 %cmp.not, i64 %indvars.iv.next, i64 %indvars.iv
739  %offset = add nuw nsw i64 %sel, %extra_offset
740  %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset
741  %1 = load float, ptr %arrayidx3, align 4
742  %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
743  store float %1, ptr %arrayidx5, align 4
744  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
745  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
746}
747
748define dso_local void @forked_ptrs_sub_from_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds, i64 %extra_offset) {
749; CHECK-LABEL: 'forked_ptrs_sub_from_offset'
750; CHECK-NEXT:    for.body:
751; CHECK-NEXT:      Memory dependences are safe with run-time checks
752; CHECK-NEXT:      Dependences:
753; CHECK-NEXT:      Run-time memory checks:
754; CHECK-NEXT:      Check 0:
755; CHECK-NEXT:        Comparing group ([[GRP50:0x[0-9a-f]+]]):
756; CHECK-NEXT:          %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
757; CHECK-NEXT:        Against group ([[GRP51:0x[0-9a-f]+]]):
758; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
759; CHECK-NEXT:      Check 1:
760; CHECK-NEXT:        Comparing group ([[GRP50]]):
761; CHECK-NEXT:          %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
762; CHECK-NEXT:        Against group ([[GRP52:0x[0-9a-f]+]]):
763; CHECK-NEXT:          %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset
764; CHECK-NEXT:          %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset
765; CHECK-NEXT:      Grouped accesses:
766; CHECK-NEXT:        Group [[GRP50]]:
767; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
768; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%for.body>
769; CHECK-NEXT:        Group [[GRP51]]:
770; CHECK-NEXT:          (Low: %Preds High: (400 + %Preds))
771; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
772; CHECK-NEXT:        Group [[GRP52]]:
773; CHECK-NEXT:          (Low: ((-4 * %extra_offset) + %Base) High: (404 + (-4 * %extra_offset) + %Base))
774; CHECK-NEXT:            Member: {(4 + (-4 * %extra_offset) + %Base),+,4}<%for.body>
775; CHECK-NEXT:            Member: {((-4 * %extra_offset) + %Base),+,4}<%for.body>
776; CHECK-EMPTY:
777; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
778; CHECK-NEXT:      SCEV assumptions:
779; CHECK-EMPTY:
780; CHECK-NEXT:      Expressions re-written:
781;
782; RECURSE-LABEL: 'forked_ptrs_sub_from_offset'
783; RECURSE-NEXT:    for.body:
784; RECURSE-NEXT:      Report: cannot identify array bounds
785; RECURSE-NEXT:      Dependences:
786; RECURSE-NEXT:      Run-time memory checks:
787; RECURSE-NEXT:      Grouped accesses:
788; RECURSE-EMPTY:
789; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
790; RECURSE-NEXT:      SCEV assumptions:
791; RECURSE-EMPTY:
792; RECURSE-NEXT:      Expressions re-written:
793;
794entry:
795  br label %for.body
796
797for.cond.cleanup:                                 ; preds = %for.body
798  ret void
799
800for.body:                                         ; preds = %entry, %for.body
801  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
802  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
803  %0 = load i32, ptr %arrayidx, align 4
804  %cmp.not = icmp eq i32 %0, 0
805  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
806  %sel = select i1 %cmp.not, i64 %indvars.iv.next, i64 %indvars.iv
807  %offset = sub nuw nsw i64 %sel, %extra_offset
808  %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset
809  %1 = load float, ptr %arrayidx3, align 4
810  %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
811  store float %1, ptr %arrayidx5, align 4
812  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
813  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
814}
815
816define dso_local void @forked_ptrs_add_sub_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds, i64 %to_add, i64 %to_sub) {
817; CHECK-LABEL: 'forked_ptrs_add_sub_offset'
818; CHECK-NEXT:    for.body:
819; CHECK-NEXT:      Memory dependences are safe with run-time checks
820; CHECK-NEXT:      Dependences:
821; CHECK-NEXT:      Run-time memory checks:
822; CHECK-NEXT:      Check 0:
823; CHECK-NEXT:        Comparing group ([[GRP53:0x[0-9a-f]+]]):
824; CHECK-NEXT:          %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
825; CHECK-NEXT:        Against group ([[GRP54:0x[0-9a-f]+]]):
826; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
827; CHECK-NEXT:      Check 1:
828; CHECK-NEXT:        Comparing group ([[GRP53]]):
829; CHECK-NEXT:          %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
830; CHECK-NEXT:        Against group ([[GRP55:0x[0-9a-f]+]]):
831; CHECK-NEXT:          %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset
832; CHECK-NEXT:          %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset
833; CHECK-NEXT:      Grouped accesses:
834; CHECK-NEXT:        Group [[GRP53]]:
835; CHECK-NEXT:          (Low: %Dest High: (400 + %Dest))
836; CHECK-NEXT:            Member: {%Dest,+,4}<nuw><%for.body>
837; CHECK-NEXT:        Group [[GRP54]]:
838; CHECK-NEXT:          (Low: %Preds High: (400 + %Preds))
839; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
840; CHECK-NEXT:        Group [[GRP55]]:
841; CHECK-NEXT:          (Low: ((4 * %to_add) + (-4 * %to_sub) + %Base) High: (404 + (4 * %to_add) + (-4 * %to_sub) + %Base))
842; CHECK-NEXT:            Member: {(4 + (4 * %to_add) + (-4 * %to_sub) + %Base),+,4}<%for.body>
843; CHECK-NEXT:            Member: {((4 * %to_add) + (-4 * %to_sub) + %Base),+,4}<%for.body>
844; CHECK-EMPTY:
845; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
846; CHECK-NEXT:      SCEV assumptions:
847; CHECK-EMPTY:
848; CHECK-NEXT:      Expressions re-written:
849;
850; RECURSE-LABEL: 'forked_ptrs_add_sub_offset'
851; RECURSE-NEXT:    for.body:
852; RECURSE-NEXT:      Report: cannot identify array bounds
853; RECURSE-NEXT:      Dependences:
854; RECURSE-NEXT:      Run-time memory checks:
855; RECURSE-NEXT:      Grouped accesses:
856; RECURSE-EMPTY:
857; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
858; RECURSE-NEXT:      SCEV assumptions:
859; RECURSE-EMPTY:
860; RECURSE-NEXT:      Expressions re-written:
861;
862entry:
863  br label %for.body
864
865for.cond.cleanup:                                 ; preds = %for.body
866  ret void
867
868for.body:                                         ; preds = %entry, %for.body
869  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
870  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
871  %0 = load i32, ptr %arrayidx, align 4
872  %cmp.not = icmp eq i32 %0, 0
873  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
874  %sel = select i1 %cmp.not, i64 %indvars.iv.next, i64 %indvars.iv
875  %add = add nuw nsw i64 %sel, %to_add
876  %offset = sub nuw nsw i64 %add, %to_sub
877  %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset
878  %1 = load float, ptr %arrayidx3, align 4
879  %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
880  store float %1, ptr %arrayidx5, align 4
881  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
882  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
883}
884
885;;;; Cases that can be handled by a forked pointer but are not currently allowed.
886
887define dso_local void @forked_ptrs_mul_by_offset(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds, i64 %extra_offset) {
888; CHECK-LABEL: 'forked_ptrs_mul_by_offset'
889; CHECK-NEXT:    for.body:
890; CHECK-NEXT:      Report: cannot identify array bounds
891; CHECK-NEXT:      Dependences:
892; CHECK-NEXT:      Run-time memory checks:
893; CHECK-NEXT:      Grouped accesses:
894; CHECK-EMPTY:
895; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
896; CHECK-NEXT:      SCEV assumptions:
897; CHECK-EMPTY:
898; CHECK-NEXT:      Expressions re-written:
899;
900; RECURSE-LABEL: 'forked_ptrs_mul_by_offset'
901; RECURSE-NEXT:    for.body:
902; RECURSE-NEXT:      Report: cannot identify array bounds
903; RECURSE-NEXT:      Dependences:
904; RECURSE-NEXT:      Run-time memory checks:
905; RECURSE-NEXT:      Grouped accesses:
906; RECURSE-EMPTY:
907; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
908; RECURSE-NEXT:      SCEV assumptions:
909; RECURSE-EMPTY:
910; RECURSE-NEXT:      Expressions re-written:
911;
912entry:
913  br label %for.body
914
915for.cond.cleanup:                                 ; preds = %for.body
916  ret void
917
918for.body:                                         ; preds = %entry, %for.body
919  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
920  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
921  %0 = load i32, ptr %arrayidx, align 4
922  %cmp.not = icmp eq i32 %0, 0
923  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
924  %sel = select i1 %cmp.not, i64 %indvars.iv.next, i64 %indvars.iv
925  %offset = mul nuw nsw i64 %sel, %extra_offset
926  %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %offset
927  %1 = load float, ptr %arrayidx3, align 4
928  %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
929  store float %1, ptr %arrayidx5, align 4
930  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
931  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
932}
933
934;;;; Derived from forked_ptrs_same_base_different_offset with a manually
935;;;; added uniform offset and a mul to provide a stride
936
937define dso_local void @forked_ptrs_uniform_and_strided_forks(ptr nocapture readonly %Base, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
938; CHECK-LABEL: 'forked_ptrs_uniform_and_strided_forks'
939; CHECK-NEXT:    for.body:
940; CHECK-NEXT:      Report: cannot identify array bounds
941; CHECK-NEXT:      Dependences:
942; CHECK-NEXT:      Run-time memory checks:
943; CHECK-NEXT:      Grouped accesses:
944; CHECK-EMPTY:
945; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
946; CHECK-NEXT:      SCEV assumptions:
947; CHECK-EMPTY:
948; CHECK-NEXT:      Expressions re-written:
949;
950; RECURSE-LABEL: 'forked_ptrs_uniform_and_strided_forks'
951; RECURSE-NEXT:    for.body:
952; RECURSE-NEXT:      Report: cannot identify array bounds
953; RECURSE-NEXT:      Dependences:
954; RECURSE-NEXT:      Run-time memory checks:
955; RECURSE-NEXT:      Grouped accesses:
956; RECURSE-EMPTY:
957; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
958; RECURSE-NEXT:      SCEV assumptions:
959; RECURSE-EMPTY:
960; RECURSE-NEXT:      Expressions re-written:
961;
962entry:
963  br label %for.body
964
965for.cond.cleanup:                                 ; preds = %for.body
966  ret void
967
968for.body:                                         ; preds = %entry, %for.body
969  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
970  %i.014 = phi i32 [ 0, %entry ], [ %add, %for.body ]
971  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
972  %0 = load i32, ptr %arrayidx, align 4
973  %cmp1.not = icmp eq i32 %0, 0
974  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
975  %add = add nuw nsw i32 %i.014, 1
976  %1 = trunc i64 %indvars.iv to i32
977  %mul = mul i32 %1, 3
978  %offset.0 = select i1 %cmp1.not, i32 4, i32 %mul
979  %idxprom213 = sext i32 %offset.0 to i64
980  %arrayidx3 = getelementptr inbounds float, ptr %Base, i64 %idxprom213
981  %2 = load float, ptr %arrayidx3, align 4
982  %arrayidx5 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
983  store float %2, ptr %arrayidx5, align 4
984  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
985  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
986}
987
988;;;; Derived from forked_ptrs_same_base_different_offset with a gather
989;;;; added using Preds as an index array in addition to the per-iteration
990;;;; condition.
991
992define dso_local void @forked_ptrs_gather_and_contiguous_forks(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
993; CHECK-LABEL: 'forked_ptrs_gather_and_contiguous_forks'
994; CHECK-NEXT:    for.body:
995; CHECK-NEXT:      Report: cannot identify array bounds
996; CHECK-NEXT:      Dependences:
997; CHECK-NEXT:      Run-time memory checks:
998; CHECK-NEXT:      Grouped accesses:
999; CHECK-EMPTY:
1000; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1001; CHECK-NEXT:      SCEV assumptions:
1002; CHECK-EMPTY:
1003; CHECK-NEXT:      Expressions re-written:
1004;
1005; RECURSE-LABEL: 'forked_ptrs_gather_and_contiguous_forks'
1006; RECURSE-NEXT:    for.body:
1007; RECURSE-NEXT:      Report: cannot identify array bounds
1008; RECURSE-NEXT:      Dependences:
1009; RECURSE-NEXT:      Run-time memory checks:
1010; RECURSE-NEXT:      Grouped accesses:
1011; RECURSE-EMPTY:
1012; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1013; RECURSE-NEXT:      SCEV assumptions:
1014; RECURSE-EMPTY:
1015; RECURSE-NEXT:      Expressions re-written:
1016;
1017entry:
1018  br label %for.body
1019
1020for.cond.cleanup:                                 ; preds = %for.body
1021  ret void
1022
1023for.body:                                         ; preds = %entry, %for.body
1024  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
1025  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
1026  %0 = load i32, ptr %arrayidx, align 4
1027  %cmp1.not = icmp eq i32 %0, 0
1028  %arrayidx9 = getelementptr inbounds float, ptr %Base2, i64 %indvars.iv
1029  %idxprom4 = sext i32 %0 to i64
1030  %arrayidx5 = getelementptr inbounds float, ptr %Base1, i64 %idxprom4
1031  %.sink.in = select i1 %cmp1.not, ptr %arrayidx9, ptr %arrayidx5
1032  %.sink = load float, ptr %.sink.in, align 4
1033  %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
1034  store float %.sink, ptr %1, align 4
1035  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
1036  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
1037  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1038}
1039
1040;; We don't currently handle a fork in both the base and the offset of a
1041;; GEP instruction.
1042
1043define dso_local void @forked_ptrs_two_forks_gep(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
1044; CHECK-LABEL: 'forked_ptrs_two_forks_gep'
1045; CHECK-NEXT:    for.body:
1046; CHECK-NEXT:      Report: cannot identify array bounds
1047; CHECK-NEXT:      Dependences:
1048; CHECK-NEXT:      Run-time memory checks:
1049; CHECK-NEXT:      Grouped accesses:
1050; CHECK-EMPTY:
1051; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1052; CHECK-NEXT:      SCEV assumptions:
1053; CHECK-EMPTY:
1054; CHECK-NEXT:      Expressions re-written:
1055;
1056; RECURSE-LABEL: 'forked_ptrs_two_forks_gep'
1057; RECURSE-NEXT:    for.body:
1058; RECURSE-NEXT:      Report: cannot identify array bounds
1059; RECURSE-NEXT:      Dependences:
1060; RECURSE-NEXT:      Run-time memory checks:
1061; RECURSE-NEXT:      Grouped accesses:
1062; RECURSE-EMPTY:
1063; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1064; RECURSE-NEXT:      SCEV assumptions:
1065; RECURSE-EMPTY:
1066; RECURSE-NEXT:      Expressions re-written:
1067;
1068entry:
1069  br label %for.body
1070
1071for.cond.cleanup:
1072  ret void
1073
1074for.body:
1075  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
1076  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
1077  %0 = load i32, ptr %arrayidx, align 4
1078  %cmp1.not = icmp eq i32 %0, 0
1079  %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1
1080  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
1081  %offset = select i1 %cmp1.not, i64 %indvars.iv.next, i64 %indvars.iv
1082  %.sink.in = getelementptr inbounds float, ptr %spec.select, i64 %offset
1083  %.sink = load float, ptr %.sink.in, align 4
1084  %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
1085  store float %.sink, ptr %1, align 4
1086  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
1087  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1088}
1089
1090;; We don't handle forks as children of a select
1091
1092define void @forked_ptrs_two_select(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture readonly %Base3, ptr %Dest) {
1093; CHECK-LABEL: 'forked_ptrs_two_select'
1094; CHECK-NEXT:    loop:
1095; CHECK-NEXT:      Report: cannot identify array bounds
1096; CHECK-NEXT:      Dependences:
1097; CHECK-NEXT:      Run-time memory checks:
1098; CHECK-NEXT:      Grouped accesses:
1099; CHECK-EMPTY:
1100; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1101; CHECK-NEXT:      SCEV assumptions:
1102; CHECK-EMPTY:
1103; CHECK-NEXT:      Expressions re-written:
1104;
1105; RECURSE-LABEL: 'forked_ptrs_two_select'
1106; RECURSE-NEXT:    loop:
1107; RECURSE-NEXT:      Report: cannot identify array bounds
1108; RECURSE-NEXT:      Dependences:
1109; RECURSE-NEXT:      Run-time memory checks:
1110; RECURSE-NEXT:      Grouped accesses:
1111; RECURSE-EMPTY:
1112; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1113; RECURSE-NEXT:      SCEV assumptions:
1114; RECURSE-EMPTY:
1115; RECURSE-NEXT:      Expressions re-written:
1116;
1117entry:
1118  br label %loop
1119
1120loop:
1121  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
1122  %gep.Dest = getelementptr inbounds float, ptr %Dest, i64 %iv
1123  %l.Dest = load float, ptr %gep.Dest
1124  %cmp = fcmp une float %l.Dest, 0.0
1125  %cmp1 = fcmp une float %l.Dest, 1.0
1126  %gep.1 = getelementptr inbounds float, ptr %Base1, i64 %iv
1127  %gep.2 = getelementptr inbounds float, ptr %Base2, i64 %iv
1128  %gep.3 = getelementptr inbounds float, ptr %Base3, i64 %iv
1129  %select = select i1 %cmp, ptr %gep.1, ptr %gep.2
1130  %select1 = select i1 %cmp1, ptr %select, ptr %gep.3
1131  %sink = load float, ptr %select1, align 4
1132  store float %sink, ptr %gep.Dest, align 4
1133  %iv.next = add nuw nsw i64 %iv, 1
1134  %exitcond.not = icmp eq i64 %iv.next, 100
1135  br i1 %exitcond.not, label %exit, label %loop
1136
1137exit:
1138  ret void
1139}
1140
1141;; We don't yet handle geps with more than 2 operands
1142
1143define void @forked_ptrs_too_many_gep_ops(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
1144; CHECK-LABEL: 'forked_ptrs_too_many_gep_ops'
1145; CHECK-NEXT:    for.body:
1146; CHECK-NEXT:      Report: cannot identify array bounds
1147; CHECK-NEXT:      Dependences:
1148; CHECK-NEXT:      Run-time memory checks:
1149; CHECK-NEXT:      Grouped accesses:
1150; CHECK-EMPTY:
1151; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1152; CHECK-NEXT:      SCEV assumptions:
1153; CHECK-EMPTY:
1154; CHECK-NEXT:      Expressions re-written:
1155;
1156; RECURSE-LABEL: 'forked_ptrs_too_many_gep_ops'
1157; RECURSE-NEXT:    for.body:
1158; RECURSE-NEXT:      Report: cannot identify array bounds
1159; RECURSE-NEXT:      Dependences:
1160; RECURSE-NEXT:      Run-time memory checks:
1161; RECURSE-NEXT:      Grouped accesses:
1162; RECURSE-EMPTY:
1163; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1164; RECURSE-NEXT:      SCEV assumptions:
1165; RECURSE-EMPTY:
1166; RECURSE-NEXT:      Expressions re-written:
1167;
1168entry:
1169  br label %for.body
1170
1171for.body:
1172  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
1173  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
1174  %0 = load i32, ptr %arrayidx, align 4
1175  %cmp1.not = icmp eq i32 %0, 0
1176  %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1
1177  %.sink.in = getelementptr inbounds [1000 x float], ptr %spec.select, i64 0, i64 %indvars.iv
1178  %.sink = load float, ptr %.sink.in, align 4
1179  %1 = getelementptr inbounds float, ptr %Dest, i64 %indvars.iv
1180  store float %.sink, ptr %1, align 4
1181  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
1182  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
1183  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1184
1185for.cond.cleanup:
1186  ret void
1187}
1188
1189;; We don't currently handle vector GEPs
1190
1191define void @forked_ptrs_vector_gep(ptr nocapture readonly %Base1, ptr nocapture readonly %Base2, ptr nocapture %Dest, ptr nocapture readonly %Preds) {
1192; CHECK-LABEL: 'forked_ptrs_vector_gep'
1193; CHECK-NEXT:    for.body:
1194; CHECK-NEXT:      Report: cannot identify array bounds
1195; CHECK-NEXT:      Dependences:
1196; CHECK-NEXT:      Run-time memory checks:
1197; CHECK-NEXT:      Grouped accesses:
1198; CHECK-EMPTY:
1199; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1200; CHECK-NEXT:      SCEV assumptions:
1201; CHECK-EMPTY:
1202; CHECK-NEXT:      Expressions re-written:
1203;
1204; RECURSE-LABEL: 'forked_ptrs_vector_gep'
1205; RECURSE-NEXT:    for.body:
1206; RECURSE-NEXT:      Report: cannot identify array bounds
1207; RECURSE-NEXT:      Dependences:
1208; RECURSE-NEXT:      Run-time memory checks:
1209; RECURSE-NEXT:      Grouped accesses:
1210; RECURSE-EMPTY:
1211; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1212; RECURSE-NEXT:      SCEV assumptions:
1213; RECURSE-EMPTY:
1214; RECURSE-NEXT:      Expressions re-written:
1215;
1216entry:
1217  br label %for.body
1218
1219for.body:
1220  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
1221  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
1222  %0 = load i32, ptr %arrayidx, align 4
1223  %cmp1.not = icmp eq i32 %0, 0
1224  %spec.select = select i1 %cmp1.not, ptr %Base2, ptr %Base1
1225  %.sink.in = getelementptr inbounds <4 x float>, ptr %spec.select, i64 %indvars.iv
1226  %.sink = load <4 x float>, ptr %.sink.in, align 4
1227  %1 = getelementptr inbounds <4 x float>, ptr %Dest, i64 %indvars.iv
1228  store <4 x float> %.sink, ptr %1, align 4
1229  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 4
1230  %exitcond.not = icmp eq i64 %indvars.iv.next, 100
1231  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1232
1233for.cond.cleanup:
1234  ret void
1235}
1236
1237;;; The following test caused an ICE with the initial forked pointers work.
1238;;; One fork is loop invariant (%Base2 + 0), the other is an scAddExpr that
1239;;; contains an scAddRecExpr inside it:
1240;;;   ((8 * (zext i32 {0,+,1}<%for.body> to i64))<nuw><nsw> + %Base2)<nuw>
1241;;;
1242;;; RtCheck::insert was expecting either loop invariant or SAR, so asserted
1243;;; on a plain scAddExpr. For now we restrict to loop invariant or SAR
1244;;; forks only, but we should be able to do better.
1245
1246define void @sc_add_expr_ice(ptr %Base1, ptr %Base2, i64 %N) {
1247; CHECK-LABEL: 'sc_add_expr_ice'
1248; CHECK-NEXT:    for.body:
1249; CHECK-NEXT:      Memory dependences are safe with run-time checks
1250; CHECK-NEXT:      Dependences:
1251; CHECK-NEXT:      Run-time memory checks:
1252; CHECK-NEXT:      Check 0:
1253; CHECK-NEXT:        Comparing group ([[GRP56:0x[0-9a-f]+]]):
1254; CHECK-NEXT:        ptr %Base1
1255; CHECK-NEXT:        Against group ([[GRP57:0x[0-9a-f]+]]):
1256; CHECK-NEXT:          %fptr = getelementptr inbounds double, ptr %Base2, i64 %sel
1257; CHECK-NEXT:      Grouped accesses:
1258; CHECK-NEXT:        Group [[GRP56]]:
1259; CHECK-NEXT:          (Low: %Base1 High: (8 + %Base1))
1260; CHECK-NEXT:            Member: %Base1
1261; CHECK-NEXT:        Group [[GRP57]]:
1262; CHECK-NEXT:          (Low: %Base2 High: ((8 * %N) + %Base2))
1263; CHECK-NEXT:            Member: {%Base2,+,8}<%for.body>
1264; CHECK-EMPTY:
1265; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1266; CHECK-NEXT:      SCEV assumptions:
1267; CHECK-NEXT:      {0,+,1}<%for.body> Added Flags: <nusw>
1268; CHECK-EMPTY:
1269; CHECK-NEXT:      Expressions re-written:
1270; CHECK-NEXT:      [PSE] %fptr = getelementptr inbounds double, ptr %Base2, i64 %sel:
1271; CHECK-NEXT:        ((8 * (zext i32 {0,+,1}<%for.body> to i64))<nuw><nsw> + %Base2)<nuw>
1272; CHECK-NEXT:        --> {%Base2,+,8}<%for.body>
1273;
1274; RECURSE-LABEL: 'sc_add_expr_ice'
1275; RECURSE-NEXT:    for.body:
1276; RECURSE-NEXT:      Memory dependences are safe with run-time checks
1277; RECURSE-NEXT:      Dependences:
1278; RECURSE-NEXT:      Run-time memory checks:
1279; RECURSE-NEXT:      Check 0:
1280; RECURSE-NEXT:        Comparing group ([[GRP58:0x[0-9a-f]+]]):
1281; RECURSE-NEXT:        ptr %Base1
1282; RECURSE-NEXT:        Against group ([[GRP59:0x[0-9a-f]+]]):
1283; RECURSE-NEXT:          %fptr = getelementptr inbounds double, ptr %Base2, i64 %sel
1284; RECURSE-NEXT:      Grouped accesses:
1285; RECURSE-NEXT:        Group [[GRP58]]:
1286; RECURSE-NEXT:          (Low: %Base1 High: (8 + %Base1))
1287; RECURSE-NEXT:            Member: %Base1
1288; RECURSE-NEXT:        Group [[GRP59]]:
1289; RECURSE-NEXT:          (Low: %Base2 High: ((8 * %N) + %Base2))
1290; RECURSE-NEXT:            Member: {%Base2,+,8}<%for.body>
1291; RECURSE-EMPTY:
1292; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1293; RECURSE-NEXT:      SCEV assumptions:
1294; RECURSE-NEXT:      {0,+,1}<%for.body> Added Flags: <nusw>
1295; RECURSE-EMPTY:
1296; RECURSE-NEXT:      Expressions re-written:
1297; RECURSE-NEXT:      [PSE] %fptr = getelementptr inbounds double, ptr %Base2, i64 %sel:
1298; RECURSE-NEXT:        ((8 * (zext i32 {0,+,1}<%for.body> to i64))<nuw><nsw> + %Base2)<nuw>
1299; RECURSE-NEXT:        --> {%Base2,+,8}<%for.body>
1300;
1301entry:
1302  br label %for.body
1303
1304for.body:
1305  %iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]
1306  %iv.trunc = trunc i64 %iv to i32
1307  store double 0.000000e+00, ptr %Base1, align 8
1308  %iv.zext = zext i32 %iv.trunc to i64
1309  %sel = select i1 true, i64 %iv.zext, i64 0
1310  %fptr = getelementptr inbounds double, ptr %Base2, i64 %sel
1311  %dummy.load = load double, ptr %fptr, align 8
1312  %iv.next = add nuw nsw i64 %iv, 1
1313  %exitcond = icmp eq i64 %iv.next, %N
1314  br i1 %exitcond, label %exit, label %for.body
1315
1316exit:
1317  ret void
1318}
1319
1320define void @forked_ptrs_with_different_base(ptr nocapture readonly %Preds, ptr nocapture %a, ptr nocapture %b, ptr nocapture readonly %c)  {
1321; CHECK-LABEL: 'forked_ptrs_with_different_base'
1322; CHECK-NEXT:    for.body:
1323; CHECK-NEXT:      Memory dependences are safe with run-time checks
1324; CHECK-NEXT:      Dependences:
1325; CHECK-NEXT:      Run-time memory checks:
1326; CHECK-NEXT:      Check 0:
1327; CHECK-NEXT:        Comparing group ([[GRP60:0x[0-9a-f]+]]):
1328; CHECK-NEXT:          %arrayidx7 = getelementptr inbounds double, ptr %.sink, i64 %indvars.iv
1329; CHECK-NEXT:        Against group ([[GRP61:0x[0-9a-f]+]]):
1330; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
1331; CHECK-NEXT:      Check 1:
1332; CHECK-NEXT:        Comparing group ([[GRP60]]):
1333; CHECK-NEXT:          %arrayidx7 = getelementptr inbounds double, ptr %.sink, i64 %indvars.iv
1334; CHECK-NEXT:        Against group ([[GRP62:0x[0-9a-f]+]]):
1335; CHECK-NEXT:          %arrayidx5 = getelementptr inbounds double, ptr %0, i64 %indvars.iv
1336; CHECK-NEXT:      Check 2:
1337; CHECK-NEXT:        Comparing group ([[GRP63:0x[0-9a-f]+]]):
1338; CHECK-NEXT:          %arrayidx7 = getelementptr inbounds double, ptr %.sink, i64 %indvars.iv
1339; CHECK-NEXT:        Against group ([[GRP61]]):
1340; CHECK-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
1341; CHECK-NEXT:      Check 3:
1342; CHECK-NEXT:        Comparing group ([[GRP63]]):
1343; CHECK-NEXT:          %arrayidx7 = getelementptr inbounds double, ptr %.sink, i64 %indvars.iv
1344; CHECK-NEXT:        Against group ([[GRP62]]):
1345; CHECK-NEXT:          %arrayidx5 = getelementptr inbounds double, ptr %0, i64 %indvars.iv
1346; CHECK-NEXT:      Grouped accesses:
1347; CHECK-NEXT:        Group [[GRP60]]:
1348; CHECK-NEXT:          (Low: %1 High: (63992 + %1))
1349; CHECK-NEXT:            Member: {%1,+,8}<nw><%for.body>
1350; CHECK-NEXT:        Group [[GRP63]]:
1351; CHECK-NEXT:          (Low: %2 High: (63992 + %2))
1352; CHECK-NEXT:            Member: {%2,+,8}<nw><%for.body>
1353; CHECK-NEXT:        Group [[GRP61]]:
1354; CHECK-NEXT:          (Low: %Preds High: (31996 + %Preds))
1355; CHECK-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
1356; CHECK-NEXT:        Group [[GRP62]]:
1357; CHECK-NEXT:          (Low: %0 High: (63992 + %0))
1358; CHECK-NEXT:            Member: {%0,+,8}<nw><%for.body>
1359; CHECK-EMPTY:
1360; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1361; CHECK-NEXT:      SCEV assumptions:
1362; CHECK-EMPTY:
1363; CHECK-NEXT:      Expressions re-written:
1364;
1365; RECURSE-LABEL: 'forked_ptrs_with_different_base'
1366; RECURSE-NEXT:    for.body:
1367; RECURSE-NEXT:      Memory dependences are safe with run-time checks
1368; RECURSE-NEXT:      Dependences:
1369; RECURSE-NEXT:      Run-time memory checks:
1370; RECURSE-NEXT:      Check 0:
1371; RECURSE-NEXT:        Comparing group ([[GRP64:0x[0-9a-f]+]]):
1372; RECURSE-NEXT:          %arrayidx7 = getelementptr inbounds double, ptr %.sink, i64 %indvars.iv
1373; RECURSE-NEXT:        Against group ([[GRP65:0x[0-9a-f]+]]):
1374; RECURSE-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
1375; RECURSE-NEXT:      Check 1:
1376; RECURSE-NEXT:        Comparing group ([[GRP64]]):
1377; RECURSE-NEXT:          %arrayidx7 = getelementptr inbounds double, ptr %.sink, i64 %indvars.iv
1378; RECURSE-NEXT:        Against group ([[GRP66:0x[0-9a-f]+]]):
1379; RECURSE-NEXT:          %arrayidx5 = getelementptr inbounds double, ptr %0, i64 %indvars.iv
1380; RECURSE-NEXT:      Check 2:
1381; RECURSE-NEXT:        Comparing group ([[GRP67:0x[0-9a-f]+]]):
1382; RECURSE-NEXT:          %arrayidx7 = getelementptr inbounds double, ptr %.sink, i64 %indvars.iv
1383; RECURSE-NEXT:        Against group ([[GRP65]]):
1384; RECURSE-NEXT:          %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
1385; RECURSE-NEXT:      Check 3:
1386; RECURSE-NEXT:        Comparing group ([[GRP67]]):
1387; RECURSE-NEXT:          %arrayidx7 = getelementptr inbounds double, ptr %.sink, i64 %indvars.iv
1388; RECURSE-NEXT:        Against group ([[GRP66]]):
1389; RECURSE-NEXT:          %arrayidx5 = getelementptr inbounds double, ptr %0, i64 %indvars.iv
1390; RECURSE-NEXT:      Grouped accesses:
1391; RECURSE-NEXT:        Group [[GRP64]]:
1392; RECURSE-NEXT:          (Low: %1 High: (63992 + %1))
1393; RECURSE-NEXT:            Member: {%1,+,8}<nw><%for.body>
1394; RECURSE-NEXT:        Group [[GRP67]]:
1395; RECURSE-NEXT:          (Low: %2 High: (63992 + %2))
1396; RECURSE-NEXT:            Member: {%2,+,8}<nw><%for.body>
1397; RECURSE-NEXT:        Group [[GRP65]]:
1398; RECURSE-NEXT:          (Low: %Preds High: (31996 + %Preds))
1399; RECURSE-NEXT:            Member: {%Preds,+,4}<nuw><%for.body>
1400; RECURSE-NEXT:        Group [[GRP66]]:
1401; RECURSE-NEXT:          (Low: %0 High: (63992 + %0))
1402; RECURSE-NEXT:            Member: {%0,+,8}<nw><%for.body>
1403; RECURSE-EMPTY:
1404; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1405; RECURSE-NEXT:      SCEV assumptions:
1406; RECURSE-EMPTY:
1407; RECURSE-NEXT:      Expressions re-written:
1408;
1409entry:
1410  %0 = load ptr, ptr %c, align 64
1411  %1 = load ptr, ptr %a, align 64
1412  %2 = load ptr, ptr %b, align 64
1413  br label %for.body
1414
1415for.cond.cleanup:                                 ; preds = %for.inc
1416  ret void
1417
1418for.body:                                         ; preds = %entry, %for.inc
1419  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ]
1420  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
1421  %3 = load i32, ptr %arrayidx, align 4
1422  %cmp2.not = icmp eq i32 %3, 0
1423  br i1 %cmp2.not, label %if.else, label %if.then
1424
1425if.then:                                          ; preds = %for.body
1426  %arrayidx5 = getelementptr inbounds double, ptr %0, i64 %indvars.iv
1427  %4 = load double, ptr %arrayidx5, align 8
1428  %add = fadd fast double %4, 1.000000e+00
1429  br label %for.inc
1430
1431if.else:                                          ; preds = %for.body
1432  %5 = mul nuw nsw i64 %indvars.iv, %indvars.iv
1433  %6 = trunc i64 %5 to i32
1434  %conv8 = sitofp i32 %6 to double
1435  br label %for.inc
1436
1437for.inc:                                          ; preds = %if.then, %if.else
1438  %.sink = phi ptr [ %1, %if.then ], [ %2, %if.else ]
1439  %add.sink = phi double [ %add, %if.then ], [ %conv8, %if.else ]
1440  %arrayidx7 = getelementptr inbounds double, ptr %.sink, i64 %indvars.iv
1441  store double %add.sink, ptr %arrayidx7, align 8
1442  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
1443  %exitcond.not = icmp eq i64 %indvars.iv.next, 7999
1444  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1445}
1446
1447; Negative test: the operator number of PhiNode is not 2.
1448define void @forked_ptrs_with_different_base3(ptr nocapture readonly %Preds, ptr nocapture %a, ptr nocapture %b, ptr nocapture readonly %c)  {
1449; CHECK-LABEL: 'forked_ptrs_with_different_base3'
1450; CHECK-NEXT:    for.body:
1451; CHECK-NEXT:      Report: cannot identify array bounds
1452; CHECK-NEXT:      Dependences:
1453; CHECK-NEXT:      Run-time memory checks:
1454; CHECK-NEXT:      Grouped accesses:
1455; CHECK-EMPTY:
1456; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1457; CHECK-NEXT:      SCEV assumptions:
1458; CHECK-EMPTY:
1459; CHECK-NEXT:      Expressions re-written:
1460;
1461; RECURSE-LABEL: 'forked_ptrs_with_different_base3'
1462; RECURSE-NEXT:    for.body:
1463; RECURSE-NEXT:      Report: cannot identify array bounds
1464; RECURSE-NEXT:      Dependences:
1465; RECURSE-NEXT:      Run-time memory checks:
1466; RECURSE-NEXT:      Grouped accesses:
1467; RECURSE-EMPTY:
1468; RECURSE-NEXT:      Non vectorizable stores to invariant address were not found in loop.
1469; RECURSE-NEXT:      SCEV assumptions:
1470; RECURSE-EMPTY:
1471; RECURSE-NEXT:      Expressions re-written:
1472;
1473entry:
1474  %ld.c = load ptr, ptr %c, align 64
1475  %ld.a = load ptr, ptr %a, align 64
1476  %ld.b = load ptr, ptr %b, align 64
1477  br label %for.body
1478
1479for.body:                                         ; preds = %entry, %for.inc
1480  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ]
1481  %arrayidx = getelementptr inbounds i32, ptr %Preds, i64 %indvars.iv
1482  %ld.preds = load i32, ptr %arrayidx, align 4
1483  switch i32 %ld.preds, label %if.else [
1484    i32 0, label %if.br0
1485	i32 1, label %if.br1
1486  ]
1487
1488if.br0:                                          ; preds = %for.body
1489  br label %for.inc
1490
1491if.br1:                                          ; preds = %for.body
1492  br label %for.inc
1493
1494if.else:                                         ; preds = %for.body
1495  br label %for.inc
1496
1497for.inc:                                          ; preds = %if.br1, %if.br0
1498  %.sink = phi ptr [ %ld.a, %if.br0 ], [ %ld.b, %if.br1 ], [ %ld.c, %if.else ]
1499  %arrayidx7 = getelementptr inbounds double, ptr %.sink, i64 %indvars.iv
1500  store double 1.000000e+00, ptr %arrayidx7, align 8
1501  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
1502  %exitcond.not = icmp eq i64 %indvars.iv.next, 7999
1503  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1504
1505for.cond.cleanup:                                 ; preds = %for.inc
1506  ret void
1507}
1508