1; RUN: opt -S -vectorize-num-stores-pred=1 -force-vector-width=1 -force-vector-interleave=2 -loop-vectorize -verify-loop-info -simplifycfg < %s | FileCheck %s --check-prefix=UNROLL 2; RUN: opt -S -vectorize-num-stores-pred=1 -force-vector-width=1 -force-vector-interleave=2 -loop-vectorize -verify-loop-info < %s | FileCheck %s --check-prefix=UNROLL-NOSIMPLIFY 3; RUN: opt -S -vectorize-num-stores-pred=1 -force-vector-width=2 -force-vector-interleave=1 -loop-vectorize -verify-loop-info -simplifycfg < %s | FileCheck %s --check-prefix=VEC 4 5target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 6 7; Test predication of stores. 8define i32 @test(i32* nocapture %f) #0 { 9entry: 10 br label %for.body 11 12; VEC-LABEL: test 13; VEC: %[[v0:.+]] = add i64 %index, 0 14; VEC: %[[v2:.+]] = getelementptr inbounds i32, i32* %f, i64 %[[v0]] 15; VEC: %[[v8:.+]] = icmp sgt <2 x i32> %{{.*}}, <i32 100, i32 100> 16; VEC: %[[v11:.+]] = extractelement <2 x i1> %[[v8]], i32 0 17; VEC: br i1 %[[v11]], label %[[cond:.+]], label %[[else:.+]] 18; 19; VEC: [[cond]]: 20; VEC: %[[v13:.+]] = extractelement <2 x i32> %wide.load, i32 0 21; VEC: %[[v9a:.+]] = add nsw i32 %[[v13]], 20 22; VEC: store i32 %[[v9a]], i32* %[[v2]], align 4 23; VEC: br label %[[else:.+]] 24; 25; VEC: [[else]]: 26; VEC: %[[v15:.+]] = extractelement <2 x i1> %[[v8]], i32 1 27; VEC: br i1 %[[v15]], label %[[cond2:.+]], label %[[else2:.+]] 28; 29; VEC: [[cond2]]: 30; VEC: %[[v17:.+]] = extractelement <2 x i32> %wide.load, i32 1 31; VEC: %[[v9b:.+]] = add nsw i32 %[[v17]], 20 32; VEC: %[[v1:.+]] = add i64 %index, 1 33; VEC: %[[v4:.+]] = getelementptr inbounds i32, i32* %f, i64 %[[v1]] 34; VEC: store i32 %[[v9b]], i32* %[[v4]], align 4 35; VEC: br label %[[else2:.+]] 36; 37; VEC: [[else2]]: 38 39; UNROLL-LABEL: test 40; UNROLL: vector.body: 41; UNROLL: %[[IND:[a-zA-Z0-9]+]] = add i64 %{{.*}}, 0 42; UNROLL: %[[IND1:[a-zA-Z0-9]+]] = add i64 %{{.*}}, 1 43; UNROLL: %[[v0:[a-zA-Z0-9]+]] = getelementptr inbounds i32, i32* %f, i64 %[[IND]] 44; UNROLL: %[[v1:[a-zA-Z0-9]+]] = getelementptr inbounds i32, i32* %f, i64 %[[IND1]] 45; UNROLL: %[[v2:[a-zA-Z0-9]+]] = load i32, i32* %[[v0]], align 4 46; UNROLL: %[[v3:[a-zA-Z0-9]+]] = load i32, i32* %[[v1]], align 4 47; UNROLL: %[[v4:[a-zA-Z0-9]+]] = icmp sgt i32 %[[v2]], 100 48; UNROLL: %[[v5:[a-zA-Z0-9]+]] = icmp sgt i32 %[[v3]], 100 49; UNROLL: br i1 %[[v4]], label %[[cond:[a-zA-Z0-9.]+]], label %[[else:[a-zA-Z0-9.]+]] 50; 51; UNROLL: [[cond]]: 52; UNROLL: %[[v6:[a-zA-Z0-9]+]] = add nsw i32 %[[v2]], 20 53; UNROLL: store i32 %[[v6]], i32* %[[v0]], align 4 54; UNROLL: br label %[[else]] 55; 56; UNROLL: [[else]]: 57; UNROLL: br i1 %[[v5]], label %[[cond2:[a-zA-Z0-9.]+]], label %[[else2:[a-zA-Z0-9.]+]] 58; 59; UNROLL: [[cond2]]: 60; UNROLL: %[[v7:[a-zA-Z0-9]+]] = add nsw i32 %[[v3]], 20 61; UNROLL: store i32 %[[v7]], i32* %[[v1]], align 4 62; UNROLL: br label %[[else2]] 63; 64; UNROLL: [[else2]]: 65 66for.body: 67 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ] 68 %arrayidx = getelementptr inbounds i32, i32* %f, i64 %indvars.iv 69 %0 = load i32, i32* %arrayidx, align 4 70 %cmp1 = icmp sgt i32 %0, 100 71 br i1 %cmp1, label %if.then, label %for.inc 72 73if.then: 74 %add = add nsw i32 %0, 20 75 store i32 %add, i32* %arrayidx, align 4 76 br label %for.inc 77 78for.inc: 79 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 80 %exitcond = icmp eq i64 %indvars.iv.next, 128 81 br i1 %exitcond, label %for.end, label %for.body 82 83for.end: 84 ret i32 0 85} 86 87; Track basic blocks when unrolling conditional blocks. This code used to assert 88; because we did not update the phi nodes with the proper predecessor in the 89; vectorized loop body. 90; PR18724 91 92; UNROLL-NOSIMPLIFY-LABEL: bug18724 93; UNROLL-NOSIMPLIFY: store i32 94; UNROLL-NOSIMPLIFY: store i32 95 96define void @bug18724() { 97entry: 98 br label %for.body9 99 100for.body9: 101 br i1 undef, label %for.inc26, label %for.body14 102 103for.body14: 104 %indvars.iv3 = phi i64 [ %indvars.iv.next4, %for.inc23 ], [ undef, %for.body9 ] 105 %iNewChunks.120 = phi i32 [ %iNewChunks.2, %for.inc23 ], [ undef, %for.body9 ] 106 %arrayidx16 = getelementptr inbounds [768 x i32], [768 x i32]* undef, i64 0, i64 %indvars.iv3 107 %tmp = load i32, i32* %arrayidx16, align 4 108 br i1 undef, label %if.then18, label %for.inc23 109 110if.then18: 111 store i32 2, i32* %arrayidx16, align 4 112 %inc21 = add nsw i32 %iNewChunks.120, 1 113 br label %for.inc23 114 115for.inc23: 116 %iNewChunks.2 = phi i32 [ %inc21, %if.then18 ], [ %iNewChunks.120, %for.body14 ] 117 %indvars.iv.next4 = add nsw i64 %indvars.iv3, 1 118 %tmp1 = trunc i64 %indvars.iv3 to i32 119 %cmp13 = icmp slt i32 %tmp1, 0 120 br i1 %cmp13, label %for.body14, label %for.inc26 121 122for.inc26: 123 %iNewChunks.1.lcssa = phi i32 [ undef, %for.body9 ], [ %iNewChunks.2, %for.inc23 ] 124 unreachable 125} 126 127; VEC-LABEL: @minimal_bit_widths( 128; 129; In the test below, it's more profitable for the expression feeding the 130; conditional store to remain scalar. Since we can only type-shrink vector 131; types, we shouldn't try to represent the expression in a smaller type. 132; 133; VEC: vector.body: 134; VEC: %wide.load = load <2 x i8>, <2 x i8>* {{.*}}, align 1 135; VEC: br i1 {{.*}}, label %[[IF0:.+]], label %[[CONT0:.+]] 136; VEC: [[IF0]]: 137; VEC: %[[E0:.+]] = extractelement <2 x i8> %wide.load, i32 0 138; VEC: %[[Z0:.+]] = zext i8 %[[E0]] to i32 139; VEC: %[[T0:.+]] = trunc i32 %[[Z0]] to i8 140; VEC: store i8 %[[T0]], i8* {{.*}}, align 1 141; VEC: br label %[[CONT0]] 142; VEC: [[CONT0]]: 143; VEC: br i1 {{.*}}, label %[[IF1:.+]], label %[[CONT1:.+]] 144; VEC: [[IF1]]: 145; VEC: %[[E1:.+]] = extractelement <2 x i8> %wide.load, i32 1 146; VEC: %[[Z1:.+]] = zext i8 %[[E1]] to i32 147; VEC: %[[T1:.+]] = trunc i32 %[[Z1]] to i8 148; VEC: store i8 %[[T1]], i8* {{.*}}, align 1 149; VEC: br label %[[CONT1]] 150; VEC: [[CONT1]]: 151; VEC: br i1 {{.*}}, label %middle.block, label %vector.body 152; 153define void @minimal_bit_widths(i1 %c) { 154entry: 155 br label %for.body 156 157for.body: 158 %tmp0 = phi i64 [ %tmp6, %for.inc ], [ 0, %entry ] 159 %tmp1 = phi i64 [ %tmp7, %for.inc ], [ undef, %entry ] 160 %tmp2 = getelementptr i8, i8* undef, i64 %tmp0 161 %tmp3 = load i8, i8* %tmp2, align 1 162 br i1 %c, label %if.then, label %for.inc 163 164if.then: 165 %tmp4 = zext i8 %tmp3 to i32 166 %tmp5 = trunc i32 %tmp4 to i8 167 store i8 %tmp5, i8* %tmp2, align 1 168 br label %for.inc 169 170for.inc: 171 %tmp6 = add nuw nsw i64 %tmp0, 1 172 %tmp7 = add i64 %tmp1, -1 173 %tmp8 = icmp eq i64 %tmp7, 0 174 br i1 %tmp8, label %for.end, label %for.body 175 176for.end: 177 ret void 178} 179