1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -basic-aa -loop-vectorize < %s | FileCheck %s
3target datalayout = "E-m:e-i64:64-n32:64"
4target triple = "powerpc64-unknown-linux-gnu"
5
6; Function Attrs: nounwind
7define void @foo(double* noalias nocapture %a, double* noalias nocapture readonly %b) #0 {
8; CHECK-LABEL: @foo(
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
11; CHECK:       vector.ph:
12; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
13; CHECK:       vector.body:
14; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
15; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
16; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[INDEX]], 2
17; CHECK-NEXT:    [[TMP2:%.*]] = add i64 [[INDEX]], 4
18; CHECK-NEXT:    [[TMP3:%.*]] = add i64 [[INDEX]], 6
19; CHECK-NEXT:    [[TMP4:%.*]] = add i64 [[INDEX]], 8
20; CHECK-NEXT:    [[TMP5:%.*]] = add i64 [[INDEX]], 10
21; CHECK-NEXT:    [[TMP6:%.*]] = add i64 [[INDEX]], 12
22; CHECK-NEXT:    [[TMP7:%.*]] = add i64 [[INDEX]], 14
23; CHECK-NEXT:    [[TMP8:%.*]] = shl nsw i64 [[TMP0]], 1
24; CHECK-NEXT:    [[TMP9:%.*]] = shl nsw i64 [[TMP1]], 1
25; CHECK-NEXT:    [[TMP10:%.*]] = shl nsw i64 [[TMP2]], 1
26; CHECK-NEXT:    [[TMP11:%.*]] = shl nsw i64 [[TMP3]], 1
27; CHECK-NEXT:    [[TMP12:%.*]] = shl nsw i64 [[TMP4]], 1
28; CHECK-NEXT:    [[TMP13:%.*]] = shl nsw i64 [[TMP5]], 1
29; CHECK-NEXT:    [[TMP14:%.*]] = shl nsw i64 [[TMP6]], 1
30; CHECK-NEXT:    [[TMP15:%.*]] = shl nsw i64 [[TMP7]], 1
31; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds double, double* [[B:%.*]], i64 [[TMP8]]
32; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP9]]
33; CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP10]]
34; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP11]]
35; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP12]]
36; CHECK-NEXT:    [[TMP21:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP13]]
37; CHECK-NEXT:    [[TMP22:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP14]]
38; CHECK-NEXT:    [[TMP23:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP15]]
39; CHECK-NEXT:    [[TMP24:%.*]] = getelementptr inbounds double, double* [[TMP16]], i32 0
40; CHECK-NEXT:    [[TMP25:%.*]] = bitcast double* [[TMP24]] to <4 x double>*
41; CHECK-NEXT:    [[TMP26:%.*]] = getelementptr inbounds double, double* [[TMP17]], i32 0
42; CHECK-NEXT:    [[TMP27:%.*]] = bitcast double* [[TMP26]] to <4 x double>*
43; CHECK-NEXT:    [[TMP28:%.*]] = getelementptr inbounds double, double* [[TMP18]], i32 0
44; CHECK-NEXT:    [[TMP29:%.*]] = bitcast double* [[TMP28]] to <4 x double>*
45; CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds double, double* [[TMP19]], i32 0
46; CHECK-NEXT:    [[TMP31:%.*]] = bitcast double* [[TMP30]] to <4 x double>*
47; CHECK-NEXT:    [[TMP32:%.*]] = getelementptr inbounds double, double* [[TMP20]], i32 0
48; CHECK-NEXT:    [[TMP33:%.*]] = bitcast double* [[TMP32]] to <4 x double>*
49; CHECK-NEXT:    [[TMP34:%.*]] = getelementptr inbounds double, double* [[TMP21]], i32 0
50; CHECK-NEXT:    [[TMP35:%.*]] = bitcast double* [[TMP34]] to <4 x double>*
51; CHECK-NEXT:    [[TMP36:%.*]] = getelementptr inbounds double, double* [[TMP22]], i32 0
52; CHECK-NEXT:    [[TMP37:%.*]] = bitcast double* [[TMP36]] to <4 x double>*
53; CHECK-NEXT:    [[TMP38:%.*]] = getelementptr inbounds double, double* [[TMP23]], i32 0
54; CHECK-NEXT:    [[TMP39:%.*]] = bitcast double* [[TMP38]] to <4 x double>*
55; CHECK-NEXT:    [[WIDE_VEC:%.*]] = load <4 x double>, <4 x double>* [[TMP25]], align 8
56; CHECK-NEXT:    [[WIDE_VEC1:%.*]] = load <4 x double>, <4 x double>* [[TMP27]], align 8
57; CHECK-NEXT:    [[WIDE_VEC2:%.*]] = load <4 x double>, <4 x double>* [[TMP29]], align 8
58; CHECK-NEXT:    [[WIDE_VEC3:%.*]] = load <4 x double>, <4 x double>* [[TMP31]], align 8
59; CHECK-NEXT:    [[WIDE_VEC4:%.*]] = load <4 x double>, <4 x double>* [[TMP33]], align 8
60; CHECK-NEXT:    [[WIDE_VEC5:%.*]] = load <4 x double>, <4 x double>* [[TMP35]], align 8
61; CHECK-NEXT:    [[WIDE_VEC6:%.*]] = load <4 x double>, <4 x double>* [[TMP37]], align 8
62; CHECK-NEXT:    [[WIDE_VEC7:%.*]] = load <4 x double>, <4 x double>* [[TMP39]], align 8
63; CHECK-NEXT:    [[STRIDED_VEC:%.*]] = shufflevector <4 x double> [[WIDE_VEC]], <4 x double> poison, <2 x i32> <i32 0, i32 2>
64; CHECK-NEXT:    [[STRIDED_VEC8:%.*]] = shufflevector <4 x double> [[WIDE_VEC1]], <4 x double> poison, <2 x i32> <i32 0, i32 2>
65; CHECK-NEXT:    [[STRIDED_VEC9:%.*]] = shufflevector <4 x double> [[WIDE_VEC2]], <4 x double> poison, <2 x i32> <i32 0, i32 2>
66; CHECK-NEXT:    [[STRIDED_VEC10:%.*]] = shufflevector <4 x double> [[WIDE_VEC3]], <4 x double> poison, <2 x i32> <i32 0, i32 2>
67; CHECK-NEXT:    [[STRIDED_VEC11:%.*]] = shufflevector <4 x double> [[WIDE_VEC4]], <4 x double> poison, <2 x i32> <i32 0, i32 2>
68; CHECK-NEXT:    [[STRIDED_VEC12:%.*]] = shufflevector <4 x double> [[WIDE_VEC5]], <4 x double> poison, <2 x i32> <i32 0, i32 2>
69; CHECK-NEXT:    [[STRIDED_VEC13:%.*]] = shufflevector <4 x double> [[WIDE_VEC6]], <4 x double> poison, <2 x i32> <i32 0, i32 2>
70; CHECK-NEXT:    [[STRIDED_VEC14:%.*]] = shufflevector <4 x double> [[WIDE_VEC7]], <4 x double> poison, <2 x i32> <i32 0, i32 2>
71; CHECK-NEXT:    [[STRIDED_VEC15:%.*]] = shufflevector <4 x double> [[WIDE_VEC]], <4 x double> poison, <2 x i32> <i32 1, i32 3>
72; CHECK-NEXT:    [[STRIDED_VEC16:%.*]] = shufflevector <4 x double> [[WIDE_VEC1]], <4 x double> poison, <2 x i32> <i32 1, i32 3>
73; CHECK-NEXT:    [[STRIDED_VEC17:%.*]] = shufflevector <4 x double> [[WIDE_VEC2]], <4 x double> poison, <2 x i32> <i32 1, i32 3>
74; CHECK-NEXT:    [[STRIDED_VEC18:%.*]] = shufflevector <4 x double> [[WIDE_VEC3]], <4 x double> poison, <2 x i32> <i32 1, i32 3>
75; CHECK-NEXT:    [[STRIDED_VEC19:%.*]] = shufflevector <4 x double> [[WIDE_VEC4]], <4 x double> poison, <2 x i32> <i32 1, i32 3>
76; CHECK-NEXT:    [[STRIDED_VEC20:%.*]] = shufflevector <4 x double> [[WIDE_VEC5]], <4 x double> poison, <2 x i32> <i32 1, i32 3>
77; CHECK-NEXT:    [[STRIDED_VEC21:%.*]] = shufflevector <4 x double> [[WIDE_VEC6]], <4 x double> poison, <2 x i32> <i32 1, i32 3>
78; CHECK-NEXT:    [[STRIDED_VEC22:%.*]] = shufflevector <4 x double> [[WIDE_VEC7]], <4 x double> poison, <2 x i32> <i32 1, i32 3>
79; CHECK-NEXT:    [[TMP40:%.*]] = fadd <2 x double> [[STRIDED_VEC]], [[STRIDED_VEC15]]
80; CHECK-NEXT:    [[TMP41:%.*]] = fadd <2 x double> [[STRIDED_VEC8]], [[STRIDED_VEC16]]
81; CHECK-NEXT:    [[TMP42:%.*]] = fadd <2 x double> [[STRIDED_VEC9]], [[STRIDED_VEC17]]
82; CHECK-NEXT:    [[TMP43:%.*]] = fadd <2 x double> [[STRIDED_VEC10]], [[STRIDED_VEC18]]
83; CHECK-NEXT:    [[TMP44:%.*]] = fadd <2 x double> [[STRIDED_VEC11]], [[STRIDED_VEC19]]
84; CHECK-NEXT:    [[TMP45:%.*]] = fadd <2 x double> [[STRIDED_VEC12]], [[STRIDED_VEC20]]
85; CHECK-NEXT:    [[TMP46:%.*]] = fadd <2 x double> [[STRIDED_VEC13]], [[STRIDED_VEC21]]
86; CHECK-NEXT:    [[TMP47:%.*]] = fadd <2 x double> [[STRIDED_VEC14]], [[STRIDED_VEC22]]
87; CHECK-NEXT:    [[TMP48:%.*]] = getelementptr inbounds double, double* [[A:%.*]], i64 [[TMP0]]
88; CHECK-NEXT:    [[TMP49:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP1]]
89; CHECK-NEXT:    [[TMP50:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP2]]
90; CHECK-NEXT:    [[TMP51:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP3]]
91; CHECK-NEXT:    [[TMP52:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP4]]
92; CHECK-NEXT:    [[TMP53:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP5]]
93; CHECK-NEXT:    [[TMP54:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP6]]
94; CHECK-NEXT:    [[TMP55:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[TMP7]]
95; CHECK-NEXT:    [[TMP56:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 0
96; CHECK-NEXT:    [[TMP57:%.*]] = bitcast double* [[TMP56]] to <2 x double>*
97; CHECK-NEXT:    store <2 x double> [[TMP40]], <2 x double>* [[TMP57]], align 8
98; CHECK-NEXT:    [[TMP58:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 2
99; CHECK-NEXT:    [[TMP59:%.*]] = bitcast double* [[TMP58]] to <2 x double>*
100; CHECK-NEXT:    store <2 x double> [[TMP41]], <2 x double>* [[TMP59]], align 8
101; CHECK-NEXT:    [[TMP60:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 4
102; CHECK-NEXT:    [[TMP61:%.*]] = bitcast double* [[TMP60]] to <2 x double>*
103; CHECK-NEXT:    store <2 x double> [[TMP42]], <2 x double>* [[TMP61]], align 8
104; CHECK-NEXT:    [[TMP62:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 6
105; CHECK-NEXT:    [[TMP63:%.*]] = bitcast double* [[TMP62]] to <2 x double>*
106; CHECK-NEXT:    store <2 x double> [[TMP43]], <2 x double>* [[TMP63]], align 8
107; CHECK-NEXT:    [[TMP64:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 8
108; CHECK-NEXT:    [[TMP65:%.*]] = bitcast double* [[TMP64]] to <2 x double>*
109; CHECK-NEXT:    store <2 x double> [[TMP44]], <2 x double>* [[TMP65]], align 8
110; CHECK-NEXT:    [[TMP66:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 10
111; CHECK-NEXT:    [[TMP67:%.*]] = bitcast double* [[TMP66]] to <2 x double>*
112; CHECK-NEXT:    store <2 x double> [[TMP45]], <2 x double>* [[TMP67]], align 8
113; CHECK-NEXT:    [[TMP68:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 12
114; CHECK-NEXT:    [[TMP69:%.*]] = bitcast double* [[TMP68]] to <2 x double>*
115; CHECK-NEXT:    store <2 x double> [[TMP46]], <2 x double>* [[TMP69]], align 8
116; CHECK-NEXT:    [[TMP70:%.*]] = getelementptr inbounds double, double* [[TMP48]], i32 14
117; CHECK-NEXT:    [[TMP71:%.*]] = bitcast double* [[TMP70]] to <2 x double>*
118; CHECK-NEXT:    store <2 x double> [[TMP47]], <2 x double>* [[TMP71]], align 8
119; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16
120; CHECK-NEXT:    [[TMP72:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1600
121; CHECK-NEXT:    br i1 [[TMP72]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
122; CHECK:       middle.block:
123; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 1600, 1600
124; CHECK-NEXT:    br i1 [[CMP_N]], label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]]
125; CHECK:       scalar.ph:
126; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 1600, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
127; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
128; CHECK:       for.cond.cleanup:
129; CHECK-NEXT:    ret void
130; CHECK:       for.body:
131; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
132; CHECK-NEXT:    [[TMP73:%.*]] = shl nsw i64 [[INDVARS_IV]], 1
133; CHECK-NEXT:    [[ODD_IDX:%.*]] = add nsw i64 [[TMP73]], 1
134; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[TMP73]]
135; CHECK-NEXT:    [[ARRAYIDX_ODD:%.*]] = getelementptr inbounds double, double* [[B]], i64 [[ODD_IDX]]
136; CHECK-NEXT:    [[TMP74:%.*]] = load double, double* [[ARRAYIDX]], align 8
137; CHECK-NEXT:    [[TMP75:%.*]] = load double, double* [[ARRAYIDX_ODD]], align 8
138; CHECK-NEXT:    [[ADD:%.*]] = fadd double [[TMP74]], [[TMP75]]
139; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[A]], i64 [[INDVARS_IV]]
140; CHECK-NEXT:    store double [[ADD]], double* [[ARRAYIDX2]], align 8
141; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
142; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 1600
143; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]], !llvm.loop [[LOOP2:![0-9]+]]
144;
145entry:
146  br label %for.body
147
148
149for.cond.cleanup:                                 ; preds = %for.body
150  ret void
151
152for.body:                                         ; preds = %for.body, %entry
153  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
154  %0 = shl nsw i64 %indvars.iv, 1
155  %odd.idx = add nsw i64 %0, 1
156
157  %arrayidx = getelementptr inbounds double, double* %b, i64 %0
158  %arrayidx.odd = getelementptr inbounds double, double* %b, i64 %odd.idx
159
160  %1 = load double, double* %arrayidx, align 8
161  %2 = load double, double* %arrayidx.odd, align 8
162
163  %add = fadd double %1, %2
164  %arrayidx2 = getelementptr inbounds double, double* %a, i64 %indvars.iv
165  store double %add, double* %arrayidx2, align 8
166  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
167  %exitcond = icmp eq i64 %indvars.iv.next, 1600
168  br i1 %exitcond, label %for.cond.cleanup, label %for.body
169}
170
171attributes #0 = { nounwind "target-cpu"="pwr8" }
172
173