182 lines · plain
1; RUN: opt < %s -passes=loop-vectorize,dce,instcombine -force-vector-width=4 -S | FileCheck %s2 3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"4 5; tests skipping iterations within a VF through break/continue/gotos.6 7; The main difficulty in vectorizing these loops in test1,test2 and test3 is8; safely speculating that the widened load of A[i] should not fault if the9; scalarized loop does not fault. For example, the10; original load in the scalar loop may not fault, but the last iteration of the11; vectorized load can fault (if it crosses a page boudary for example).12; This last vector iteration is where *one* of the13; scalar iterations lead to the early exit.14 15; int test(int *A, int Length) {16; for (int i = 0; i < Length; i++) {17; if (A[i] > 10.0) goto end;18; A[i] = 0;19; }20; end:21; return 0;22; }23; CHECK-LABEL: test1(24; CHECK-NOT: <4 x i32>25define i32 @test1(ptr nocapture %A, i32 %Length) {26entry:27 %cmp8 = icmp sgt i32 %Length, 028 br i1 %cmp8, label %for.body.preheader, label %end29 30for.body.preheader: ; preds = %entry31 br label %for.body32 33for.body: ; preds = %for.body.preheader, %if.else34 %indvars.iv = phi i64 [ %indvars.iv.next, %if.else ], [ 0, %for.body.preheader ]35 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv36 %0 = load i32, ptr %arrayidx, align 4, !tbaa !1537 %cmp1 = icmp sgt i32 %0, 1038 br i1 %cmp1, label %end.loopexit, label %if.else39 40if.else: ; preds = %for.body41 store i32 0, ptr %arrayidx, align 4, !tbaa !1542 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 143 %1 = trunc i64 %indvars.iv.next to i3244 %cmp = icmp slt i32 %1, %Length45 br i1 %cmp, label %for.body, label %end.loopexit46 47end.loopexit: ; preds = %if.else, %for.body48 br label %end49 50end: ; preds = %end.loopexit, %entry51 ret i32 052}53 54; We don't use anything from within the loop at the early exit path55; so we do not need to know which iteration caused the early exit path.56; bool test2(int *A, int Length, int K) {57; for (int i = 0; i < Length; i++) {58; if (A[i] == K) return true;59; }60; return false;61; }62; TODO: Today we do not vectorize this, but we could teach the vectorizer, once63; the hard part of proving/speculating A[i:VF - 1] loads does not fault is handled by the64; compiler/hardware.65 66; CHECK-LABEL: test2(67; CHECK-NOT: <4 x i32>68define i32 @test2(ptr nocapture %A, i32 %Length, i32 %K) {69entry:70 %cmp8 = icmp sgt i32 %Length, 071 br i1 %cmp8, label %for.body.preheader, label %end72 73for.body.preheader: ; preds = %entry74 br label %for.body75 76for.body: ; preds = %for.body.preheader, %if.else77 %indvars.iv = phi i64 [ %indvars.iv.next, %if.else ], [ 0, %for.body.preheader ]78 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv79 %ld = load i32, ptr %arrayidx, align 480 %cmp1 = icmp eq i32 %ld, %K81 br i1 %cmp1, label %end.loopexit, label %if.else82 83if.else: ; preds = %for.body84 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 185 %trunc = trunc i64 %indvars.iv.next to i3286 %cmp = icmp slt i32 %trunc, %Length87 br i1 %cmp, label %for.body, label %end.loopexit88 89end.loopexit: ; preds = %if.else, %for.body90 %result.lcssa = phi i32 [ 1, %for.body ], [ 0, %if.else ]91 br label %end92 93end: ; preds = %end.loopexit, %entry94 %result = phi i32 [ %result.lcssa, %end.loopexit ], [ 0, %entry ]95 ret i32 %result96}97 98; We use the IV in the early exit99; so we need to know which iteration caused the early exit path.100; int test3(int *A, int Length, int K) {101; for (int i = 0; i < Length; i++) {102; if (A[i] == K) return i;103; }104; return -1;105; }106; TODO: Today we do not vectorize this, but we could teach the vectorizer (once107; we handle the speculation safety of the widened load).108; CHECK-LABEL: test3(109; CHECK-NOT: <4 x i32>110define i32 @test3(ptr nocapture %A, i32 %Length, i32 %K) {111entry:112 %cmp8 = icmp sgt i32 %Length, 0113 br i1 %cmp8, label %for.body.preheader, label %end114 115for.body.preheader: ; preds = %entry116 br label %for.body117 118for.body: ; preds = %for.body.preheader, %if.else119 %indvars.iv = phi i64 [ %indvars.iv.next, %if.else ], [ 0, %for.body.preheader ]120 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv121 %ld = load i32, ptr %arrayidx, align 4122 %cmp1 = icmp eq i32 %ld, %K123 br i1 %cmp1, label %end.loopexit, label %if.else124 125if.else: ; preds = %for.body126 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1127 %trunc = trunc i64 %indvars.iv.next to i32128 %cmp = icmp slt i32 %trunc, %Length129 br i1 %cmp, label %for.body, label %end.loopexit130 131end.loopexit: ; preds = %if.else, %for.body132 %result.lcssa = phi i64 [ %indvars.iv, %for.body ], [ -1, %if.else ]133 %res.trunc = trunc i64 %result.lcssa to i32134 br label %end135 136end: ; preds = %end.loopexit, %entry137 %result = phi i32 [ %res.trunc, %end.loopexit ], [ -1, %entry ]138 ret i32 %result139}140 141; bool test4(int *A, int Length, int K, int J) {142; for (int i = 0; i < Length; i++) {143; if (A[i] == K) continue;144; A[i] = J;145; }146; }147; For this test, we vectorize and generate predicated stores to A[i].148; CHECK-LABEL: test4(149; CHECK: <4 x i32>150define void @test4(ptr nocapture %A, i32 %Length, i32 %K, i32 %J) {151entry:152 %cmp8 = icmp sgt i32 %Length, 0153 br i1 %cmp8, label %for.body.preheader, label %end.loopexit154 155for.body.preheader: ; preds = %entry156 br label %for.body157 158for.body: ; preds = %for.body.preheader, %if.else159 %indvars.iv = phi i64 [ %indvars.iv.next, %latch ], [ 0, %for.body.preheader ]160 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv161 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1162 %trunc = trunc i64 %indvars.iv.next to i32163 %ld = load i32, ptr %arrayidx, align 4164 %cmp1 = icmp eq i32 %ld, %K165 br i1 %cmp1, label %latch, label %if.else166 167if.else:168 store i32 %J, ptr %arrayidx, align 4169 br label %latch170 171latch: ; preds = %for.body172 %cmp = icmp slt i32 %trunc, %Length173 br i1 %cmp, label %for.body, label %end.loopexit174 175end.loopexit: ; preds = %if.else, %for.body176 ret void177}178!15 = !{!16, !16, i64 0}179!16 = !{!"int", !17, i64 0}180!17 = !{!"omnipotent char", !18, i64 0}181!18 = !{!"Simple C/C++ TBAA"}182