147 lines · plain
1; REQUIRES: asserts2; RUN: opt < %s -mcpu=neoverse-v2 -passes=loop-vectorize -debug-only=loop-vectorize -disable-output 2>&1 | FileCheck %s3 4target triple="aarch64--linux-gnu"5 6; This test shows that comparison and next iteration IV have zero cost if the7; vector loop gets executed exactly once with the given VF.8define i64 @test(ptr %a, ptr %b) #0 {9; CHECK-LABEL: LV: Checking a loop in 'test'10; CHECK: Cost of 1 for VF 8: induction instruction %i.iv.next = add nuw nsw i64 %i.iv, 111; CHECK-NEXT: Cost of 0 for VF 8: induction instruction %i.iv = phi i64 [ 0, %entry ], [ %i.iv.next, %for.body ]12; CHECK-NEXT: Cost of 1 for VF 8: exit condition instruction %exitcond.not = icmp eq i64 %i.iv.next, 1613; CHECK-NEXT: Cost of 0 for VF 8: EMIT vp<{{.+}}> = CANONICAL-INDUCTION ir<0>, vp<%index.next>14; CHECK: Cost for VF 8: 3015; CHECK-NEXT: Cost of 0 for VF 16: induction instruction %i.iv = phi i64 [ 0, %entry ], [ %i.iv.next, %for.body ]16; CHECK-NEXT: Cost of 0 for VF 16: EMIT vp<{{.+}}> = CANONICAL-INDUCTION ir<0>, vp<%index.next>17; CHECK: Cost for VF 16: 5618; CHECK: LV: Selecting VF: 1619entry:20 br label %for.body21 22exit: ; preds = %for.body23 ret i64 %add24 25for.body: ; preds = %entry, %for.body26 %i.iv = phi i64 [ 0, %entry ], [ %i.iv.next, %for.body ]27 %sum = phi i64 [ 0, %entry ], [ %add, %for.body ]28 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %i.iv29 %0 = load i8, ptr %arrayidx, align 130 %conv = zext i8 %0 to i6431 %arrayidx2 = getelementptr inbounds i8, ptr %b, i64 %i.iv32 %1 = load i8, ptr %arrayidx2, align 133 %conv3 = zext i8 %1 to i6434 %div = udiv i64 %conv3, %conv35 %add = add i64 %div, %sum36 %i.iv.next = add nuw nsw i64 %i.iv, 137 %exitcond.not = icmp eq i64 %i.iv.next, 1638 br i1 %exitcond.not, label %exit, label %for.body39}40 41; Same as above, but in the next iteration IV has extra users, and thus, the cost is not zero.42define i64 @test_external_iv_user(ptr %a, ptr %b) #0 {43; CHECK-LABEL: LV: Checking a loop in 'test_external_iv_user'44; CHECK: Cost of 1 for VF 8: induction instruction %i.iv.next = add nuw nsw i64 %i.iv, 145; CHECK-NEXT: Cost of 0 for VF 8: induction instruction %i.iv = phi i64 [ 0, %entry ], [ %i.iv.next, %for.body ]46; CHECK-NEXT: Cost of 1 for VF 8: exit condition instruction %exitcond.not = icmp eq i64 %i.iv.next, 1647; CHECK-NEXT: Cost of 0 for VF 8: EMIT vp<{{.+}}> = CANONICAL-INDUCTION ir<0>, vp<%index.next>48; CHECK: Cost for VF 8: 3049; CHECK-NEXT: Cost of 1 for VF 16: induction instruction %i.iv.next = add nuw nsw i64 %i.iv, 150; CHECK-NEXT: Cost of 0 for VF 16: induction instruction %i.iv = phi i64 [ 0, %entry ], [ %i.iv.next, %for.body ]51; CHECK-NEXT: Cost of 0 for VF 16: EMIT vp<{{.+}}> = CANONICAL-INDUCTION ir<0>, vp<%index.next>52; CHECK: Cost for VF 16: 5753; CHECK: LV: Selecting VF: 1654entry:55 br label %for.body56 57for.body: ; preds = %entry, %for.body58 %i.iv = phi i64 [ 0, %entry ], [ %i.iv.next, %for.body ]59 %sum = phi i64 [ 0, %entry ], [ %add, %for.body ]60 %arrayidx = getelementptr inbounds nuw i8, ptr %a, i64 %i.iv61 %0 = load i8, ptr %arrayidx, align 162 %conv = zext i8 %0 to i6463 %i.iv.next = add nuw nsw i64 %i.iv, 164 %arrayidx2 = getelementptr inbounds nuw i8, ptr %b, i64 %i.iv.next65 %1 = load i8, ptr %arrayidx2, align 166 %conv3 = zext i8 %1 to i6467 %div = udiv i64 %conv3, %conv68 %add = add i64 %sum, %div69 %exitcond.not = icmp eq i64 %i.iv.next, 1670 br i1 %exitcond.not, label %exit, label %for.body71 72exit: ; preds = %for.body73 ret i64 %add74}75 76; Same as above but with two IVs without extra users. They all have zero cost when VF equals the number of iterations.77define i64 @test_two_ivs(ptr %a, ptr %b, i64 %start) #0 {78; CHECK-LABEL: LV: Checking a loop in 'test_two_ivs'79; CHECK: Cost of 1 for VF 8: induction instruction %i.iv.next = add nuw nsw i64 %i.iv, 180; CHECK-NEXT: Cost of 0 for VF 8: induction instruction %i.iv = phi i64 [ 0, %entry ], [ %i.iv.next, %for.body ]81; CHECK-NEXT: Cost of 1 for VF 8: induction instruction %j.iv.next = add nuw nsw i64 %j.iv, 182; CHECK-NEXT: Cost of 0 for VF 8: induction instruction %j.iv = phi i64 [ %start, %entry ], [ %j.iv.next, %for.body ]83; CHECK-NEXT: Cost of 1 for VF 8: exit condition instruction %exitcond.not = icmp eq i64 %i.iv.next, 1684; CHECK-NEXT: Cost of 0 for VF 8: EMIT vp<{{.+}}> = CANONICAL-INDUCTION ir<0>, vp<%index.next>85; CHECK: Cost for VF 8: 1686; CHECK-NEXT: Cost of 0 for VF 16: induction instruction %i.iv = phi i64 [ 0, %entry ], [ %i.iv.next, %for.body ]87; CHECK-NEXT: Cost of 0 for VF 16: induction instruction %j.iv = phi i64 [ %start, %entry ], [ %j.iv.next, %for.body ]88; CHECK-NEXT: Cost of 0 for VF 16: EMIT vp<{{.+}}> = CANONICAL-INDUCTION ir<0>, vp<%index.next>89; CHECK: Cost of 1 for VF 16: EXPRESSION vp<%11> = ir<%sum> + partial.reduce.add (mul nuw nsw (ir<%1> zext to i64), (ir<%0> zext to i64))90; CHECK: Cost for VF 16: 391; CHECK: LV: Selecting VF: 1692entry:93 br label %for.body94 95exit: ; preds = %for.body96 ret i64 %add97 98for.body: ; preds = %entry, %for.body99 %i.iv = phi i64 [ 0, %entry ], [ %i.iv.next, %for.body ]100 %j.iv = phi i64 [ %start, %entry ], [ %j.iv.next, %for.body ]101 %sum = phi i64 [ 0, %entry ], [ %add, %for.body ]102 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %i.iv103 %0 = load i8, ptr %arrayidx, align 1104 %conv = zext i8 %0 to i64105 %arrayidx2 = getelementptr inbounds i8, ptr %b, i64 %j.iv106 %1 = load i8, ptr %arrayidx2, align 1107 %conv3 = zext i8 %1 to i64108 %mul = mul nuw nsw i64 %conv3, %conv109 %add = add i64 %mul, %sum110 %i.iv.next = add nuw nsw i64 %i.iv, 1111 %j.iv.next = add nuw nsw i64 %j.iv, 1112 %exitcond.not = icmp eq i64 %i.iv.next, 16113 br i1 %exitcond.not, label %exit, label %for.body114}115 116define i1 @test_extra_cmp_user(ptr nocapture noundef %dst, ptr nocapture noundef readonly %src) {117; CHECK-LABEL: LV: Checking a loop in 'test_extra_cmp_user'118; CHECK: Cost of 4 for VF 8: induction instruction %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1119; CHECK-NEXT: Cost of 0 for VF 8: induction instruction %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]120; CHECK-NEXT: Cost of 4 for VF 8: exit condition instruction %exitcond.not = icmp eq i64 %indvars.iv.next, 16121; CHECK-NEXT: Cost of 0 for VF 8: EMIT vp<{{.+}}> = CANONICAL-INDUCTION ir<0>, vp<%index.next>122; CHECK: Cost for VF 8: 12123; CHECK-NEXT: Cost of 0 for VF 16: induction instruction %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]124; CHECK-NEXT: Cost of 0 for VF 16: EMIT vp<{{.+}}> = CANONICAL-INDUCTION ir<0>, vp<%index.next>125; CHECK: Cost for VF 16: 4126; CHECK: LV: Selecting VF: 16127entry:128 br label %for.body129 130for.body:131 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]132 %arrayidx = getelementptr inbounds nuw i8, ptr %src, i64 %indvars.iv133 %0 = load i8, ptr %arrayidx, align 4134 %arrayidx2 = getelementptr inbounds nuw i8, ptr %dst, i64 %indvars.iv135 %1 = load i8, ptr %arrayidx2, align 4136 %add = add nsw i8 %1, %0137 store i8 %add, ptr %arrayidx2, align 4138 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1139 %exitcond.not = icmp eq i64 %indvars.iv.next, 16140 br i1 %exitcond.not, label %exit, label %for.body141 142exit:143 ret i1 %exitcond.not144}145 146attributes #0 = { vscale_range(1, 16) "target-features"="+sve" }147