1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; This test verifies that the loop vectorizer will NOT vectorize loops that
3; will produce a tail loop with the optimize for size or the minimize size
4; attributes. This is a target-dependent version of the test.
5; RUN: opt < %s -loop-vectorize -force-vector-width=64 -S -mtriple=x86_64-unknown-linux -mcpu=skx | FileCheck %s
6; RUN: opt < %s -loop-vectorize -S -mtriple=x86_64-unknown-linux -mcpu=skx | FileCheck %s --check-prefix AUTOVF
7
8target datalayout = "E-m:e-p:32:32-i64:32-f64:32:64-a:0:32-n32-S128"
9
10@tab = common global [32 x i8] zeroinitializer, align 1
11
12define i32 @foo_optsize() #0 {
13; CHECK-LABEL: @foo_optsize(
14; CHECK-NEXT:  entry:
15; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
16; CHECK:       vector.ph:
17; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
18; CHECK:       vector.body:
19; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
20; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[INDEX]], 0
21; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <64 x i32> undef, i32 [[TMP0]], i32 0
22; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <64 x i32> [[BROADCAST_SPLATINSERT]], <64 x i32> undef, <64 x i32> zeroinitializer
23; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 [[TMP0]]
24; CHECK-NEXT:    [[TMP2:%.*]] = icmp ule <64 x i32> [[BROADCAST_SPLAT]], <i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202>
25; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i32 0
26; CHECK-NEXT:    [[TMP4:%.*]] = bitcast i8* [[TMP3]] to <64 x i8>*
27; CHECK-NEXT:    [[WIDE_MASKED_LOAD:%.*]] = call <64 x i8> @llvm.masked.load.v64i8.p0v64i8(<64 x i8>* [[TMP4]], i32 1, <64 x i1> [[TMP2]], <64 x i8> undef)
28; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq <64 x i8> [[WIDE_MASKED_LOAD]], zeroinitializer
29; CHECK-NEXT:    [[TMP6:%.*]] = extractelement <64 x i1> [[TMP5]], i32 0
30; CHECK-NEXT:    [[TMP7:%.*]] = select <64 x i1> [[TMP5]], <64 x i8> <i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2>, <64 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
31; CHECK-NEXT:    [[TMP8:%.*]] = bitcast i8* [[TMP3]] to <64 x i8>*
32; CHECK-NEXT:    call void @llvm.masked.store.v64i8.p0v64i8(<64 x i8> [[TMP7]], <64 x i8>* [[TMP8]], i32 1, <64 x i1> [[TMP2]])
33; CHECK-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 64
34; CHECK-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[INDEX_NEXT]], 256
35; CHECK-NEXT:    br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !0
36; CHECK:       middle.block:
37; CHECK-NEXT:    br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]]
38; CHECK:       scalar.ph:
39; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ 256, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
40; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
41; CHECK:       for.body:
42; CHECK-NEXT:    [[I_08:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
43; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 [[I_08]]
44; CHECK-NEXT:    [[TMP10:%.*]] = load i8, i8* [[ARRAYIDX]], align 1
45; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[TMP10]], 0
46; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[CMP1]], i8 2, i8 1
47; CHECK-NEXT:    store i8 [[DOT]], i8* [[ARRAYIDX]], align 1
48; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_08]], 1
49; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[I_08]], 202
50; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !2
51; CHECK:       for.end:
52; CHECK-NEXT:    ret i32 0
53;
54; AUTOVF-LABEL: @foo_optsize(
55; AUTOVF-NEXT:  entry:
56; AUTOVF-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
57; AUTOVF:       vector.ph:
58; AUTOVF-NEXT:    br label [[VECTOR_BODY:%.*]]
59; AUTOVF:       vector.body:
60; AUTOVF-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
61; AUTOVF-NEXT:    [[TMP0:%.*]] = add i32 [[INDEX]], 0
62; AUTOVF-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <32 x i32> undef, i32 [[TMP0]], i32 0
63; AUTOVF-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <32 x i32> [[BROADCAST_SPLATINSERT]], <32 x i32> undef, <32 x i32> zeroinitializer
64; AUTOVF-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 [[TMP0]]
65; AUTOVF-NEXT:    [[TMP2:%.*]] = icmp ule <32 x i32> [[BROADCAST_SPLAT]], <i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202>
66; AUTOVF-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i32 0
67; AUTOVF-NEXT:    [[TMP4:%.*]] = bitcast i8* [[TMP3]] to <32 x i8>*
68; AUTOVF-NEXT:    [[WIDE_MASKED_LOAD:%.*]] = call <32 x i8> @llvm.masked.load.v32i8.p0v32i8(<32 x i8>* [[TMP4]], i32 1, <32 x i1> [[TMP2]], <32 x i8> undef)
69; AUTOVF-NEXT:    [[TMP5:%.*]] = icmp eq <32 x i8> [[WIDE_MASKED_LOAD]], zeroinitializer
70; AUTOVF-NEXT:    [[TMP6:%.*]] = extractelement <32 x i1> [[TMP5]], i32 0
71; AUTOVF-NEXT:    [[TMP7:%.*]] = select <32 x i1> [[TMP5]], <32 x i8> <i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2>, <32 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
72; AUTOVF-NEXT:    [[TMP8:%.*]] = bitcast i8* [[TMP3]] to <32 x i8>*
73; AUTOVF-NEXT:    call void @llvm.masked.store.v32i8.p0v32i8(<32 x i8> [[TMP7]], <32 x i8>* [[TMP8]], i32 1, <32 x i1> [[TMP2]])
74; AUTOVF-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 32
75; AUTOVF-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[INDEX_NEXT]], 224
76; AUTOVF-NEXT:    br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !0
77; AUTOVF:       middle.block:
78; AUTOVF-NEXT:    br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]]
79; AUTOVF:       scalar.ph:
80; AUTOVF-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ 224, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
81; AUTOVF-NEXT:    br label [[FOR_BODY:%.*]]
82; AUTOVF:       for.body:
83; AUTOVF-NEXT:    [[I_08:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
84; AUTOVF-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 [[I_08]]
85; AUTOVF-NEXT:    [[TMP10:%.*]] = load i8, i8* [[ARRAYIDX]], align 1
86; AUTOVF-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[TMP10]], 0
87; AUTOVF-NEXT:    [[DOT:%.*]] = select i1 [[CMP1]], i8 2, i8 1
88; AUTOVF-NEXT:    store i8 [[DOT]], i8* [[ARRAYIDX]], align 1
89; AUTOVF-NEXT:    [[INC]] = add nsw i32 [[I_08]], 1
90; AUTOVF-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[I_08]], 202
91; AUTOVF-NEXT:    br i1 [[EXITCOND]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !2
92; AUTOVF:       for.end:
93; AUTOVF-NEXT:    ret i32 0
94;
95
96entry:
97  br label %for.body
98
99for.body:                                         ; preds = %for.body, %entry
100  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
101  %arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 %i.08
102  %0 = load i8, i8* %arrayidx, align 1
103  %cmp1 = icmp eq i8 %0, 0
104  %. = select i1 %cmp1, i8 2, i8 1
105  store i8 %., i8* %arrayidx, align 1
106  %inc = add nsw i32 %i.08, 1
107  %exitcond = icmp eq i32 %i.08, 202
108  br i1 %exitcond, label %for.end, label %for.body
109
110for.end:                                          ; preds = %for.body
111  ret i32 0
112}
113
114attributes #0 = { optsize }
115
116define i32 @foo_minsize() #1 {
117; CHECK-LABEL: @foo_minsize(
118; CHECK-NEXT:  entry:
119; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
120; CHECK:       vector.ph:
121; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
122; CHECK:       vector.body:
123; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
124; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[INDEX]], 0
125; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <64 x i32> undef, i32 [[TMP0]], i32 0
126; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <64 x i32> [[BROADCAST_SPLATINSERT]], <64 x i32> undef, <64 x i32> zeroinitializer
127; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 [[TMP0]]
128; CHECK-NEXT:    [[TMP2:%.*]] = icmp ule <64 x i32> [[BROADCAST_SPLAT]], <i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202>
129; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i32 0
130; CHECK-NEXT:    [[TMP4:%.*]] = bitcast i8* [[TMP3]] to <64 x i8>*
131; CHECK-NEXT:    [[WIDE_MASKED_LOAD:%.*]] = call <64 x i8> @llvm.masked.load.v64i8.p0v64i8(<64 x i8>* [[TMP4]], i32 1, <64 x i1> [[TMP2]], <64 x i8> undef)
132; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq <64 x i8> [[WIDE_MASKED_LOAD]], zeroinitializer
133; CHECK-NEXT:    [[TMP6:%.*]] = extractelement <64 x i1> [[TMP5]], i32 0
134; CHECK-NEXT:    [[TMP7:%.*]] = select <64 x i1> [[TMP5]], <64 x i8> <i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2>, <64 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
135; CHECK-NEXT:    [[TMP8:%.*]] = bitcast i8* [[TMP3]] to <64 x i8>*
136; CHECK-NEXT:    call void @llvm.masked.store.v64i8.p0v64i8(<64 x i8> [[TMP7]], <64 x i8>* [[TMP8]], i32 1, <64 x i1> [[TMP2]])
137; CHECK-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 64
138; CHECK-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[INDEX_NEXT]], 256
139; CHECK-NEXT:    br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !4
140; CHECK:       middle.block:
141; CHECK-NEXT:    br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]]
142; CHECK:       scalar.ph:
143; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ 256, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
144; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
145; CHECK:       for.body:
146; CHECK-NEXT:    [[I_08:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
147; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 [[I_08]]
148; CHECK-NEXT:    [[TMP10:%.*]] = load i8, i8* [[ARRAYIDX]], align 1
149; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[TMP10]], 0
150; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[CMP1]], i8 2, i8 1
151; CHECK-NEXT:    store i8 [[DOT]], i8* [[ARRAYIDX]], align 1
152; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_08]], 1
153; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[I_08]], 202
154; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !5
155; CHECK:       for.end:
156; CHECK-NEXT:    ret i32 0
157;
158; AUTOVF-LABEL: @foo_minsize(
159; AUTOVF-NEXT:  entry:
160; AUTOVF-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
161; AUTOVF:       vector.ph:
162; AUTOVF-NEXT:    br label [[VECTOR_BODY:%.*]]
163; AUTOVF:       vector.body:
164; AUTOVF-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
165; AUTOVF-NEXT:    [[TMP0:%.*]] = add i32 [[INDEX]], 0
166; AUTOVF-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <32 x i32> undef, i32 [[TMP0]], i32 0
167; AUTOVF-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <32 x i32> [[BROADCAST_SPLATINSERT]], <32 x i32> undef, <32 x i32> zeroinitializer
168; AUTOVF-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 [[TMP0]]
169; AUTOVF-NEXT:    [[TMP2:%.*]] = icmp ule <32 x i32> [[BROADCAST_SPLAT]], <i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202, i32 202>
170; AUTOVF-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i32 0
171; AUTOVF-NEXT:    [[TMP4:%.*]] = bitcast i8* [[TMP3]] to <32 x i8>*
172; AUTOVF-NEXT:    [[WIDE_MASKED_LOAD:%.*]] = call <32 x i8> @llvm.masked.load.v32i8.p0v32i8(<32 x i8>* [[TMP4]], i32 1, <32 x i1> [[TMP2]], <32 x i8> undef)
173; AUTOVF-NEXT:    [[TMP5:%.*]] = icmp eq <32 x i8> [[WIDE_MASKED_LOAD]], zeroinitializer
174; AUTOVF-NEXT:    [[TMP6:%.*]] = extractelement <32 x i1> [[TMP5]], i32 0
175; AUTOVF-NEXT:    [[TMP7:%.*]] = select <32 x i1> [[TMP5]], <32 x i8> <i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2>, <32 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
176; AUTOVF-NEXT:    [[TMP8:%.*]] = bitcast i8* [[TMP3]] to <32 x i8>*
177; AUTOVF-NEXT:    call void @llvm.masked.store.v32i8.p0v32i8(<32 x i8> [[TMP7]], <32 x i8>* [[TMP8]], i32 1, <32 x i1> [[TMP2]])
178; AUTOVF-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 32
179; AUTOVF-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[INDEX_NEXT]], 224
180; AUTOVF-NEXT:    br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !4
181; AUTOVF:       middle.block:
182; AUTOVF-NEXT:    br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]]
183; AUTOVF:       scalar.ph:
184; AUTOVF-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ 224, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
185; AUTOVF-NEXT:    br label [[FOR_BODY:%.*]]
186; AUTOVF:       for.body:
187; AUTOVF-NEXT:    [[I_08:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
188; AUTOVF-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 [[I_08]]
189; AUTOVF-NEXT:    [[TMP10:%.*]] = load i8, i8* [[ARRAYIDX]], align 1
190; AUTOVF-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[TMP10]], 0
191; AUTOVF-NEXT:    [[DOT:%.*]] = select i1 [[CMP1]], i8 2, i8 1
192; AUTOVF-NEXT:    store i8 [[DOT]], i8* [[ARRAYIDX]], align 1
193; AUTOVF-NEXT:    [[INC]] = add nsw i32 [[I_08]], 1
194; AUTOVF-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[I_08]], 202
195; AUTOVF-NEXT:    br i1 [[EXITCOND]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !5
196; AUTOVF:       for.end:
197; AUTOVF-NEXT:    ret i32 0
198;
199
200entry:
201  br label %for.body
202
203for.body:                                         ; preds = %for.body, %entry
204  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
205  %arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* @tab, i32 0, i32 %i.08
206  %0 = load i8, i8* %arrayidx, align 1
207  %cmp1 = icmp eq i8 %0, 0
208  %. = select i1 %cmp1, i8 2, i8 1
209  store i8 %., i8* %arrayidx, align 1
210  %inc = add nsw i32 %i.08, 1
211  %exitcond = icmp eq i32 %i.08, 202
212  br i1 %exitcond, label %for.end, label %for.body
213
214for.end:                                          ; preds = %for.body
215  ret i32 0
216}
217
218attributes #1 = { minsize }
219
220
221; We can't vectorize this one because we version for stride==1; even having TC
222; a multiple of VF.
223define void @scev4stride1(i32* noalias nocapture %a, i32* noalias nocapture readonly %b, i32 %k) #2 {
224; CHECK-LABEL: @scev4stride1(
225; CHECK-NEXT:  for.body.preheader:
226; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
227; CHECK:       for.body:
228; CHECK-NEXT:    [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER:%.*]] ]
229; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[I_07]], [[K:%.*]]
230; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i32 [[MUL]]
231; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
232; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_07]]
233; CHECK-NEXT:    store i32 [[TMP0]], i32* [[ARRAYIDX1]], align 4
234; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_07]], 1
235; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 256
236; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
237; CHECK:       for.end.loopexit:
238; CHECK-NEXT:    ret void
239;
240; AUTOVF-LABEL: @scev4stride1(
241; AUTOVF-NEXT:  for.body.preheader:
242; AUTOVF-NEXT:    br label [[FOR_BODY:%.*]]
243; AUTOVF:       for.body:
244; AUTOVF-NEXT:    [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER:%.*]] ]
245; AUTOVF-NEXT:    [[MUL:%.*]] = mul nsw i32 [[I_07]], [[K:%.*]]
246; AUTOVF-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i32 [[MUL]]
247; AUTOVF-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
248; AUTOVF-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[I_07]]
249; AUTOVF-NEXT:    store i32 [[TMP0]], i32* [[ARRAYIDX1]], align 4
250; AUTOVF-NEXT:    [[INC]] = add nuw nsw i32 [[I_07]], 1
251; AUTOVF-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 256
252; AUTOVF-NEXT:    br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
253; AUTOVF:       for.end.loopexit:
254; AUTOVF-NEXT:    ret void
255;
256for.body.preheader:
257  br label %for.body
258
259for.body:                                         ; preds = %for.body.preheader, %for.body
260  %i.07 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
261  %mul = mul nsw i32 %i.07, %k
262  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %mul
263  %0 = load i32, i32* %arrayidx, align 4
264  %arrayidx1 = getelementptr inbounds i32, i32* %a, i32 %i.07
265  store i32 %0, i32* %arrayidx1, align 4
266  %inc = add nuw nsw i32 %i.07, 1
267  %exitcond = icmp eq i32 %inc, 256
268  br i1 %exitcond, label %for.end.loopexit, label %for.body
269
270for.end.loopexit:                                 ; preds = %for.body
271  ret void
272}
273
274attributes #2 = { optsize }
275
276
277; PR39497
278; We can't vectorize this one because we version for overflow check and tiny
279; trip count leads to opt-for-size (which otherwise could fold the tail by
280; masking).
281define i32 @main() local_unnamed_addr {
282; CHECK-LABEL: @main(
283; CHECK-NEXT:  while.cond:
284; CHECK-NEXT:    br label [[FOR_COND:%.*]]
285; CHECK:       for.cond:
286; CHECK-NEXT:    [[D_0:%.*]] = phi i32 [ 0, [[WHILE_COND:%.*]] ], [ [[ADD:%.*]], [[FOR_COND]] ]
287; CHECK-NEXT:    [[CONV:%.*]] = and i32 [[D_0]], 65535
288; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[CONV]], 4
289; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[CONV]], 1
290; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_COND]], label [[WHILE_COND_LOOPEXIT:%.*]]
291; CHECK:       while.cond.loopexit:
292; CHECK-NEXT:    ret i32 0
293;
294; AUTOVF-LABEL: @main(
295; AUTOVF-NEXT:  while.cond:
296; AUTOVF-NEXT:    br label [[FOR_COND:%.*]]
297; AUTOVF:       for.cond:
298; AUTOVF-NEXT:    [[D_0:%.*]] = phi i32 [ 0, [[WHILE_COND:%.*]] ], [ [[ADD:%.*]], [[FOR_COND]] ]
299; AUTOVF-NEXT:    [[CONV:%.*]] = and i32 [[D_0]], 65535
300; AUTOVF-NEXT:    [[CMP:%.*]] = icmp ult i32 [[CONV]], 4
301; AUTOVF-NEXT:    [[ADD]] = add nuw nsw i32 [[CONV]], 1
302; AUTOVF-NEXT:    br i1 [[CMP]], label [[FOR_COND]], label [[WHILE_COND_LOOPEXIT:%.*]]
303; AUTOVF:       while.cond.loopexit:
304; AUTOVF-NEXT:    ret i32 0
305;
306while.cond:
307  br label %for.cond
308
309for.cond:
310  %d.0 = phi i32 [ 0, %while.cond ], [ %add, %for.cond ]
311  %conv = and i32 %d.0, 65535
312  %cmp = icmp ult i32 %conv, 4
313  %add = add nuw nsw i32 %conv, 1
314  br i1 %cmp, label %for.cond, label %while.cond.loopexit
315
316while.cond.loopexit:
317  ret i32 0
318}
319