Skip to content

Commit 95800da

Browse files
committed
[LoopVectorize] Add support for replication of more intrinsics with scalable vectors
This patch adds more instructions to the Uniforms list, for example certain intrinsics that are uniform by definition or whose operands are loop invariant. This list includes: 1. The intrinsics 'experimental.noalias.scope.decl' and 'sideeffect', which are always uniform by definition. 2. If intrinsics 'lifetime.start', 'lifetime.end' and 'assume' have loop invariant input operands then these are also uniform too. Also, in VPRecipeBuilder::handleReplication we check if an instruction is uniform based purely on whether or not the instruction lives in the Uniforms list. However, there are certain cases where calls to some intrinsics can be effectively treated as uniform too. Therefore, we now also treat the following cases as uniform for scalable vectors: 1. If the 'assume' intrinsic's operand is not loop invariant, then we are free to treat this as uniform anyway since it's only a performance hint. We will get the benefit for the first lane. 2. When the input pointers for 'lifetime.start' and 'lifetime.end' are loop variant then for scalable vectors we assume these still ultimately come from the broadcast of an alloca. We do not support scalable vectorisation of loops containing alloca instructions, hence the alloca itself would be invariant. If the pointer does not come from an alloca then the intrinsic itself has no effect. I have updated the assume test for fixed width, since we now treat it as uniform: Transforms/LoopVectorize/assume.ll I've also added new scalable vectorisation tests for other intriniscs: Transforms/LoopVectorize/scalable-assume.ll Transforms/LoopVectorize/scalable-lifetime.ll Transforms/LoopVectorize/scalable-noalias-scope-decl.ll Differential Revision: https://reviews.llvm.org/D107284
1 parent 91e3995 commit 95800da

File tree

5 files changed

+363
-4
lines changed

5 files changed

+363
-4
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5427,6 +5427,20 @@ void LoopVectorizationCostModel::collectLoopUniforms(ElementCount VF) {
54275427
// lane 0 demanded or b) are uses which demand only lane 0 of their operand.
54285428
for (auto *BB : TheLoop->blocks())
54295429
for (auto &I : *BB) {
5430+
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) {
5431+
switch (II->getIntrinsicID()) {
5432+
case Intrinsic::sideeffect:
5433+
case Intrinsic::experimental_noalias_scope_decl:
5434+
case Intrinsic::assume:
5435+
case Intrinsic::lifetime_start:
5436+
case Intrinsic::lifetime_end:
5437+
if (TheLoop->hasLoopInvariantOperands(&I))
5438+
addToWorklistIfAllowed(&I);
5439+
default:
5440+
break;
5441+
}
5442+
}
5443+
54305444
// If there's no pointer operand, there's nothing to do.
54315445
auto *Ptr = getLoadStorePointerOperand(&I);
54325446
if (!Ptr)
@@ -8943,6 +8957,36 @@ VPBasicBlock *VPRecipeBuilder::handleReplication(
89438957
bool IsPredicated = LoopVectorizationPlanner::getDecisionAndClampRange(
89448958
[&](ElementCount VF) { return CM.isPredicatedInst(I); }, Range);
89458959

8960+
// Even if the instruction is not marked as uniform, there are certain
8961+
// intrinsic calls that can be effectively treated as such, so we check for
8962+
// them here. Conservatively, we only do this for scalable vectors, since
8963+
// for fixed-width VFs we can always fall back on full scalarization.
8964+
if (!IsUniform && Range.Start.isScalable() && isa<IntrinsicInst>(I)) {
8965+
switch (cast<IntrinsicInst>(I)->getIntrinsicID()) {
8966+
case Intrinsic::assume:
8967+
case Intrinsic::lifetime_start:
8968+
case Intrinsic::lifetime_end:
8969+
// For scalable vectors if one of the operands is variant then we still
8970+
// want to mark as uniform, which will generate one instruction for just
8971+
// the first lane of the vector. We can't scalarize the call in the same
8972+
// way as for fixed-width vectors because we don't know how many lanes
8973+
// there are.
8974+
//
8975+
// The reasons for doing it this way for scalable vectors are:
8976+
// 1. For the assume intrinsic generating the instruction for the first
8977+
// lane is still be better than not generating any at all. For
8978+
// example, the input may be a splat across all lanes.
8979+
// 2. For the lifetime start/end intrinsics the pointer operand only
8980+
// does anything useful when the input comes from a stack object,
8981+
// which suggests it should always be uniform. For non-stack objects
8982+
// the effect is to poison the object, which still allows us to
8983+
// remove the call.
8984+
IsUniform = true;
8985+
default:
8986+
break;
8987+
}
8988+
}
8989+
89468990
auto *Recipe = new VPReplicateRecipe(I, Plan->mapToVPValues(I->operands()),
89478991
IsUniform, IsPredicated);
89488992
setRecipe(I, Recipe);

llvm/test/Transforms/LoopVectorize/assume.ll

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,8 @@ define void @test2(%struct.data* nocapture readonly %d) {
4949
; CHECK: vector.body:
5050
; CHECK: tail call void @llvm.assume(i1 [[MASKCOND]])
5151
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]])
52-
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]])
53-
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]])
5452
; CHECK: tail call void @llvm.assume(i1 [[MASKCOND4]])
5553
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND4]])
56-
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND4]])
57-
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND4]])
5854
; CHECK: for.body:
5955
entry:
6056
%b = getelementptr inbounds %struct.data, %struct.data* %d, i64 0, i32 1
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
; RUN: opt < %s -scalable-vectorization=on -force-target-supports-scalable-vectors=true -loop-vectorize -force-vector-width=2 -force-vector-interleave=2 -S | FileCheck %s
2+
3+
define void @test1(float* noalias nocapture %a, float* noalias nocapture readonly %b) {
4+
; CHECK-LABEL: @test1(
5+
; CHECK: vector.body:
6+
; CHECK: [[FCMP1:%.*]] = fcmp ogt <vscale x 2 x float>
7+
; CHECK-NEXT: [[FCMP2:%.*]] = fcmp ogt <vscale x 2 x float>
8+
; CHECK-NEXT: [[FCMP1L0:%.*]] = extractelement <vscale x 2 x i1> [[FCMP1]], i32 0
9+
; CHECK-NEXT: tail call void @llvm.assume(i1 [[FCMP1L0]])
10+
; CHECK-NEXT: [[FCMP2L0:%.*]] = extractelement <vscale x 2 x i1> [[FCMP2]], i32 0
11+
; CHECK-NEXT: tail call void @llvm.assume(i1 [[FCMP2L0]])
12+
entry:
13+
br label %for.body
14+
15+
for.body: ; preds = %for.body, %entry
16+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
17+
%arrayidx = getelementptr inbounds float, float* %b, i64 %indvars.iv
18+
%0 = load float, float* %arrayidx, align 4
19+
%cmp1 = fcmp ogt float %0, 1.000000e+02
20+
tail call void @llvm.assume(i1 %cmp1)
21+
%add = fadd float %0, 1.000000e+00
22+
%arrayidx5 = getelementptr inbounds float, float* %a, i64 %indvars.iv
23+
store float %add, float* %arrayidx5, align 4
24+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
25+
%exitcond = icmp eq i64 %indvars.iv, 1599
26+
br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
27+
28+
for.end: ; preds = %for.body
29+
ret void
30+
}
31+
32+
declare void @llvm.assume(i1) #0
33+
34+
attributes #0 = { nounwind willreturn }
35+
36+
%struct.data = type { float*, float* }
37+
38+
define void @test2(float *%a, float *%b) {
39+
; CHECK-LABEL: @test2(
40+
; CHECK: entry:
41+
; CHECK: [[MASKCOND:%.*]] = icmp eq i64 %ptrint1, 0
42+
; CHECK: [[MASKCOND4:%.*]] = icmp eq i64 %ptrint2, 0
43+
; CHECK: vector.body:
44+
; CHECK: tail call void @llvm.assume(i1 [[MASKCOND]])
45+
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]])
46+
; CHECK: tail call void @llvm.assume(i1 [[MASKCOND4]])
47+
; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND4]])
48+
entry:
49+
%ptrint1 = ptrtoint float* %a to i64
50+
%maskcond = icmp eq i64 %ptrint1, 0
51+
%ptrint2 = ptrtoint float* %b to i64
52+
%maskcond4 = icmp eq i64 %ptrint2, 0
53+
br label %for.body
54+
55+
56+
for.body: ; preds = %for.body, %entry
57+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
58+
tail call void @llvm.assume(i1 %maskcond)
59+
%arrayidx = getelementptr inbounds float, float* %a, i64 %indvars.iv
60+
%0 = load float, float* %arrayidx, align 4
61+
%add = fadd float %0, 1.000000e+00
62+
tail call void @llvm.assume(i1 %maskcond4)
63+
%arrayidx5 = getelementptr inbounds float, float* %b, i64 %indvars.iv
64+
store float %add, float* %arrayidx5, align 4
65+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
66+
%exitcond = icmp eq i64 %indvars.iv, 1599
67+
br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
68+
69+
for.end: ; preds = %for.body
70+
ret void
71+
}
72+
73+
; Test case for PR43620. Make sure we can vectorize with predication in presence
74+
; of assume calls. For now, check that we drop all assumes in predicated blocks
75+
; in the vector body.
76+
define void @predicated_assume(float* noalias nocapture readonly %a, float* noalias nocapture %b, i64 %n) {
77+
; Check that the vector.body does not contain any assumes.
78+
; CHECK-LABEL: @predicated_assume(
79+
; CHECK: vector.body:
80+
; CHECK-NOT: llvm.assume
81+
; CHECK: for.body:
82+
entry:
83+
br label %for.body
84+
85+
for.body: ; preds = %for.body.preheader, %if.end5
86+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %if.end5 ]
87+
%cmp1 = icmp ult i64 %indvars.iv, 495616
88+
br i1 %cmp1, label %if.end5, label %if.else
89+
90+
if.else: ; preds = %for.body
91+
%cmp2 = icmp ult i64 %indvars.iv, 991232
92+
tail call void @llvm.assume(i1 %cmp2)
93+
br label %if.end5
94+
95+
if.end5: ; preds = %for.body, %if.else
96+
%x.0 = phi float [ 4.200000e+01, %if.else ], [ 2.300000e+01, %for.body ]
97+
%arrayidx = getelementptr inbounds float, float* %a, i64 %indvars.iv
98+
%0 = load float, float* %arrayidx, align 4
99+
%mul = fmul float %x.0, %0
100+
%arrayidx7 = getelementptr inbounds float, float* %b, i64 %indvars.iv
101+
store float %mul, float* %arrayidx7, align 4
102+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
103+
%cmp = icmp eq i64 %indvars.iv.next, %n
104+
br i1 %cmp, label %for.cond.cleanup, label %for.body, !llvm.loop !0
105+
106+
for.cond.cleanup: ; preds = %if.end5, %entry
107+
ret void
108+
}
109+
110+
!0 = distinct !{!0, !1}
111+
!1 = !{!"llvm.loop.vectorize.scalable.enable", i1 true}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
; RUN: opt -S -scalable-vectorization=on -force-target-supports-scalable-vectors=true -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 < %s | FileCheck %s
2+
3+
target 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+
; Make sure we can vectorize loops which contain lifetime markers.
6+
7+
define void @test(i32 *%d) {
8+
; CHECK-LABEL: @test(
9+
; CHECK: entry:
10+
; CHECK: [[ALLOCA:%.*]] = alloca [1024 x i32], align 16
11+
; CHECK-NEXT: [[BC:%.*]] = bitcast [1024 x i32]* [[ALLOCA]] to i8*
12+
; CHECK: vector.body:
13+
; CHECK: call void @llvm.lifetime.end.p0i8(i64 4096, i8* [[BC]])
14+
; CHECK: store <vscale x 2 x i32>
15+
; CHECK: call void @llvm.lifetime.start.p0i8(i64 4096, i8* [[BC]])
16+
17+
entry:
18+
%arr = alloca [1024 x i32], align 16
19+
%0 = bitcast [1024 x i32]* %arr to i8*
20+
call void @llvm.lifetime.start.p0i8(i64 4096, i8* %0) #1
21+
br label %for.body
22+
23+
for.body:
24+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
25+
call void @llvm.lifetime.end.p0i8(i64 4096, i8* %0) #1
26+
%arrayidx = getelementptr inbounds i32, i32* %d, i64 %indvars.iv
27+
%1 = load i32, i32* %arrayidx, align 8
28+
store i32 100, i32* %arrayidx, align 8
29+
call void @llvm.lifetime.start.p0i8(i64 4096, i8* %0) #1
30+
%indvars.iv.next = add i64 %indvars.iv, 1
31+
%lftr.wideiv = trunc i64 %indvars.iv.next to i32
32+
%exitcond = icmp ne i32 %lftr.wideiv, 128
33+
br i1 %exitcond, label %for.body, label %for.end, !llvm.loop !0
34+
35+
for.end:
36+
call void @llvm.lifetime.end.p0i8(i64 4096, i8* %0) #1
37+
ret void
38+
}
39+
40+
; CHECK-LABEL: @testloopvariant(
41+
; CHECK: entry:
42+
; CHECK: [[ALLOCA:%.*]] = alloca [1024 x i32], align 16
43+
; CHECK: vector.ph:
44+
; CHECK: [[TMP1:%.*]] = insertelement <vscale x 2 x [1024 x i32]*> poison, [1024 x i32]* %arr, i32 0
45+
; CHECK-NEXT: [[SPLAT_ALLOCA:%.*]] = shufflevector <vscale x 2 x [1024 x i32]*> [[TMP1]], <vscale x 2 x [1024 x i32]*> poison, <vscale x 2 x i32> zeroinitializer
46+
; CHECK: vector.body:
47+
; CHECK: [[BC_ALLOCA:%.*]] = bitcast <vscale x 2 x [1024 x i32]*> [[SPLAT_ALLOCA]] to <vscale x 2 x i8*>
48+
; CHECK-NEXT: [[ONE_LIFETIME:%.*]] = extractelement <vscale x 2 x i8*> [[BC_ALLOCA]], i32 0
49+
; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4096, i8* [[ONE_LIFETIME]])
50+
; CHECK: store <vscale x 2 x i32>
51+
; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4096, i8* [[ONE_LIFETIME]])
52+
53+
define void @testloopvariant(i32 *%d) {
54+
entry:
55+
%arr = alloca [1024 x i32], align 16
56+
br label %for.body
57+
58+
for.body:
59+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
60+
%0 = getelementptr [1024 x i32], [1024 x i32]* %arr, i32 0, i64 %indvars.iv
61+
%1 = bitcast [1024 x i32]* %arr to i8*
62+
call void @llvm.lifetime.end.p0i8(i64 4096, i8* %1) #1
63+
%arrayidx = getelementptr inbounds i32, i32* %d, i64 %indvars.iv
64+
%2 = load i32, i32* %arrayidx, align 8
65+
store i32 100, i32* %arrayidx, align 8
66+
call void @llvm.lifetime.start.p0i8(i64 4096, i8* %1) #1
67+
%indvars.iv.next = add i64 %indvars.iv, 1
68+
%lftr.wideiv = trunc i64 %indvars.iv.next to i32
69+
%exitcond = icmp ne i32 %lftr.wideiv, 128
70+
br i1 %exitcond, label %for.body, label %for.end, !llvm.loop !0
71+
72+
for.end:
73+
ret void
74+
}
75+
76+
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
77+
78+
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
79+
80+
!0 = distinct !{!0, !1}
81+
!1 = !{!"llvm.loop.vectorize.scalable.enable", i1 true}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
; RUN: opt < %s -scalable-vectorization=on -force-target-supports-scalable-vectors=true -loop-vectorize -force-vector-width=4 -force-vector-interleave=2 -S | FileCheck %s
2+
3+
define void @test1(float* noalias nocapture %a, float* noalias nocapture readonly %b) {
4+
entry:
5+
br label %for.body
6+
7+
; CHECK-LABEL: @test1
8+
; CHECK: vector.body:
9+
; CHECK: @llvm.experimental.noalias.scope.decl
10+
; CHECK-NOT: @llvm.experimental.noalias.scope.decl
11+
; CHECK: for.body:
12+
; CHECK: @llvm.experimental.noalias.scope.decl
13+
; CHECK-NOT: @llvm.experimental.noalias.scope.decl
14+
; CHECK: ret void
15+
16+
for.body: ; preds = %for.body, %entry
17+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
18+
%arrayidx = getelementptr inbounds float, float* %b, i64 %indvars.iv
19+
%0 = load float, float* %arrayidx, align 4
20+
%cmp1 = fcmp ogt float %0, 1.000000e+02
21+
tail call void @llvm.experimental.noalias.scope.decl(metadata !0)
22+
%add = fadd float %0, 1.000000e+00
23+
%arrayidx5 = getelementptr inbounds float, float* %a, i64 %indvars.iv
24+
store float %add, float* %arrayidx5, align 4
25+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
26+
%exitcond = icmp eq i64 %indvars.iv, 1599
27+
br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !5
28+
29+
for.end: ; preds = %for.body
30+
ret void
31+
}
32+
33+
declare void @llvm.experimental.noalias.scope.decl(metadata)
34+
35+
%struct.data = type { float*, float* }
36+
37+
define void @test2(float* %a, float* %b) {
38+
; CHECK-LABEL: @test2
39+
; CHECK: vector.body:
40+
; CHECK: @llvm.experimental.noalias.scope.decl(metadata [[SCOPE0_LIST:!.*]])
41+
; CHECK: @llvm.experimental.noalias.scope.decl(metadata [[SCOPE4_LIST:!.*]])
42+
; CHECK-NOT: @llvm.experimental.noalias.scope.decl
43+
; CHECK: for.body:
44+
; CHECK: @llvm.experimental.noalias.scope.decl(metadata [[SCOPE0_LIST]])
45+
; CHECK: @llvm.experimental.noalias.scope.decl(metadata [[SCOPE4_LIST]])
46+
; CHECK-NOT: @llvm.experimental.noalias.scope.decl
47+
; CHECK: ret void
48+
entry:
49+
%ptrint = ptrtoint float* %b to i64
50+
%maskcond = icmp eq i64 %ptrint, 0
51+
%ptrint2 = ptrtoint float* %a to i64
52+
%maskcond4 = icmp eq i64 %ptrint2, 0
53+
br label %for.body
54+
55+
for.body: ; preds = %for.body, %entry
56+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
57+
tail call void @llvm.experimental.noalias.scope.decl(metadata !0)
58+
%arrayidx = getelementptr inbounds float, float* %b, i64 %indvars.iv
59+
%0 = load float, float* %arrayidx, align 4
60+
%add = fadd float %0, 1.000000e+00
61+
tail call void @llvm.experimental.noalias.scope.decl(metadata !4)
62+
%arrayidx5 = getelementptr inbounds float, float* %a, i64 %indvars.iv
63+
store float %add, float* %arrayidx5, align 4
64+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
65+
%exitcond = icmp eq i64 %indvars.iv, 1599
66+
br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !5
67+
68+
for.end: ; preds = %for.body
69+
ret void
70+
}
71+
72+
define void @predicated_noalias_scope_decl(float* noalias nocapture readonly %a, float* noalias nocapture %b, i64 %n) {
73+
74+
; Check that the vector.body still contains a llvm.experimental.noalias.scope.decl
75+
76+
; CHECK-LABEL: @predicated_noalias_scope_decl(
77+
; CHECK: vector.body:
78+
; CHECK: call void @llvm.experimental.noalias.scope.decl
79+
; CHECK-NOT: @llvm.experimental.noalias.scope.decl
80+
; CHECK: scalar.ph:
81+
; CHECK-NOT: @llvm.experimental.noalias.scope.decl
82+
; CHECK: if.else:
83+
; CHECK: call void @llvm.experimental.noalias.scope.decl
84+
; CHECK-NOT: @llvm.experimental.noalias.scope.decl
85+
; CHECK: }
86+
87+
entry:
88+
br label %for.body
89+
90+
for.body: ; preds = %entry, %if.end5
91+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %if.end5 ]
92+
%cmp1 = icmp ult i64 %indvars.iv, 495616
93+
br i1 %cmp1, label %if.end5, label %if.else
94+
95+
if.else: ; preds = %for.body
96+
%cmp2 = icmp ult i64 %indvars.iv, 991232
97+
tail call void @llvm.experimental.noalias.scope.decl(metadata !0)
98+
br label %if.end5
99+
100+
if.end5: ; preds = %for.body, %if.else
101+
%x.0 = phi float [ 4.200000e+01, %if.else ], [ 2.300000e+01, %for.body ]
102+
%arrayidx = getelementptr inbounds float, float* %a, i64 %indvars.iv
103+
%0 = load float, float* %arrayidx, align 4
104+
%mul = fmul float %x.0, %0
105+
%arrayidx7 = getelementptr inbounds float, float* %b, i64 %indvars.iv
106+
store float %mul, float* %arrayidx7, align 4
107+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
108+
%cmp = icmp eq i64 %indvars.iv.next, %n
109+
br i1 %cmp, label %for.cond.cleanup, label %for.body, !llvm.loop !5
110+
111+
for.cond.cleanup: ; preds = %if.end5
112+
ret void
113+
}
114+
115+
!0 = !{ !1 }
116+
!1 = distinct !{ !1, !2 }
117+
!2 = distinct !{ !2 }
118+
!3 = distinct !{ !3, !2 }
119+
!4 = !{ !3 }
120+
!5 = distinct !{!5, !6}
121+
!6 = !{!"llvm.loop.vectorize.scalable.enable", i1 true}
122+
123+
; CHECK: [[SCOPE0_LIST]] = !{[[SCOPE0:!.*]]}
124+
; CHECK: [[SCOPE0]] = distinct !{[[SCOPE0]], [[SCOPE0_DOM:!.*]]}
125+
; CHECK: [[SCOPE0_DOM]] = distinct !{[[SCOPE0_DOM]]}
126+
; CHECK: [[SCOPE4_LIST]] = !{[[SCOPE4:!.*]]}
127+
; CHECK: [[SCOPE4]] = distinct !{[[SCOPE4]], [[SCOPE0_DOM]]}

0 commit comments

Comments
 (0)