-
Notifications
You must be signed in to change notification settings - Fork 18k
[ValueTracking] Conservative NoSync check prevents vectorization #199002
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
a45e23b
291b928
7ef20bd
8752bd7
cc94ce5
8fd4903
bd85427
cb5f6a7
615daab
a247f2c
03fdf50
30f80af
bcd5a88
ce288bd
122a413
2e56d67
9a6df94
9e04362
bf39dd9
b3c08f8
c56f2ce
4520163
05197a0
d9da6ca
87287cb
622601e
97183ce
fa09e32
87af6d7
425c64e
b270ecb
a135b2a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1456,4 +1456,364 @@ exit: | |
| ret void | ||
| } | ||
|
|
||
| define i64 @VectorizingWithoutNoSyncAttributeTest(ptr noundef nonnull readonly align 8 captures(none) dereferenceable(24) %v, i32 noundef %n) { | ||
| ; CHECK-LABEL: define i64 @VectorizingWithoutNoSyncAttributeTest( | ||
| ; CHECK-SAME: ptr noundef nonnull readonly align 8 captures(none) dereferenceable(24) [[V:%.*]], i32 noundef [[N:%.*]]) { | ||
| ; CHECK-NEXT: [[ENTRY:.*:]] | ||
| ; CHECK-NEXT: [[L_V:%.*]] = load ptr, ptr [[V]], align 8 | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[PI_L_V:%.*]] = ptrtoint ptr [[L_V]] to i64 | ||
| ; CHECK-NEXT: [[GEP_V:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 8 | ||
| ; CHECK-NEXT: [[L_GEP_V:%.*]] = load ptr, ptr [[GEP_V]], align 8 | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_GEP_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[PI_L_GEP_V:%.*]] = ptrtoint ptr [[L_GEP_V]] to i64 | ||
| ; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PI_L_GEP_V]], [[PI_L_V]] | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[L_V]], i64 [[SUB]]) ] | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_V]], i64 4) ] | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_GEP_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[L_V]], [[L_GEP_V]] | ||
| ; CHECK-NEXT: br i1 [[C_1]], [[EXIT:label %.*]], label %[[LOOP_PREHEADER:.*]] | ||
| ; CHECK: [[LOOP_PREHEADER]]: | ||
| ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[PI_L_GEP_V]], -4 | ||
| ; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[PI_L_V]] | ||
| ; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 2 | ||
| ; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 1 | ||
| ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP3]], 2 | ||
| ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] | ||
| ; CHECK: [[VECTOR_PH]]: | ||
| ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 2 | ||
| ; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[N_MOD_VF]] | ||
| ; CHECK-NEXT: [[TMP4:%.*]] = shl i64 [[N_VEC]], 2 | ||
| ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[L_V]], i64 [[TMP4]] | ||
| ; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i32> poison, i32 [[N]], i64 0 | ||
| ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i32> [[BROADCAST_SPLATINSERT]], <2 x i32> poison, <2 x i32> zeroinitializer | ||
| ; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] | ||
| ; CHECK: [[LOOP_HEADER]]: | ||
| ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] | ||
| ; CHECK-NEXT: [[TMP6:%.*]] = shl i64 [[INDEX]], 2 | ||
| ; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[L_V]], i64 [[TMP6]] | ||
| ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[NEXT_GEP]], align 4 | ||
| ; CHECK-NEXT: [[TMP7:%.*]] = icmp slt <2 x i32> [[WIDE_LOAD]], [[BROADCAST_SPLAT]] | ||
| ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 | ||
| ; CHECK-NEXT: [[TMP8:%.*]] = freeze <2 x i1> [[TMP7]] | ||
| ; CHECK-NEXT: [[C_2:%.*]] = call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> [[TMP8]]) | ||
| ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] | ||
| ; CHECK-NEXT: br i1 [[C_2]], label %[[LOOP_EARLY_EXIT:.*]], label %[[LOOP_LATCH]] | ||
| ; CHECK: [[LOOP_LATCH]]: | ||
| ; CHECK-NEXT: br i1 [[TMP10]], label %[[LOOP_COMP:.*]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP24:![0-9]+]] | ||
| ; CHECK: [[LOOP_COMP]]: | ||
| ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC]] | ||
| ; CHECK-NEXT: br i1 [[CMP_N]], [[LOOP_COMP1:label %.*]], label %[[SCALAR_PH]] | ||
| ; CHECK: [[LOOP_EARLY_EXIT]]: | ||
| ; CHECK-NEXT: [[TMP11:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v2i1(<2 x i1> [[TMP7]], i1 false) | ||
| ; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], [[TMP11]] | ||
| ; CHECK-NEXT: [[TMP13:%.*]] = shl i64 [[TMP12]], 2 | ||
| ; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[L_V]], i64 [[TMP13]] | ||
| ; CHECK-NEXT: br [[LOOP_EARLY_EXIT1:label %.*]] | ||
| ; CHECK: [[SCALAR_PH]]: | ||
| ; | ||
| entry: | ||
| %l.v = load ptr, ptr %v, align 8 | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.v, i64 4) ] | ||
| %pi.l.v = ptrtoint ptr %l.v to i64 | ||
| %gep.v = getelementptr inbounds nuw i8, ptr %v, i64 8 | ||
| %l.gep.v = load ptr, ptr %gep.v, align 8 | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.gep.v, i64 4) ] | ||
| %pi.l.gep.v = ptrtoint ptr %l.gep.v to i64 | ||
| %sub = sub i64 %pi.l.gep.v, %pi.l.v | ||
| call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %l.v, i64 %sub) ] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The file focuses on testing deref assumptions with constant sizes. With non-constant expressions should go to But the interesting aspect of the new tests are the nosync etc checks. so I think you can just remove the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On removing those ptrtoint/sub the Tests which should be vectorized are not getting vectorized.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, but I think it should be possible to take one of the existing simpler tests that do not get vectorized from The existing positive test with the early exit could go
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @fhahn Isn't The Check-Lines contain the Vector-Preheader and Vector-Body which means it is getting vectorized.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I attempted rewrote it to not get vectorized by creating a new point However still that is getting vectorized.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of the tests within that file are getting vectorized.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, what I meant is take
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here is my modified test. I have added the Atomic Instruction after the Dereferenceable Asssume Instruction. However still this is getting Vectorized... Putting the Atomic Instruction inside the Loop Header stops vectorization but that's not what we want to test right?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes it vectorizes, but does not execute the load in So with and without the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have made the changes. |
||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.v, i64 4) ] | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.gep.v, i64 4) ] | ||
|
kshitijvp marked this conversation as resolved.
Outdated
|
||
| %c.1 = icmp eq ptr %l.v, %l.gep.v | ||
| br i1 %c.1, label %exit, label %loop.preheader | ||
|
|
||
| loop.preheader: | ||
| br label %loop.header | ||
|
|
||
| loop.header: | ||
| %merge = phi ptr [ %gep.merge, %loop.latch ], [ %l.v, %loop.preheader ] | ||
|
kshitijvp marked this conversation as resolved.
Outdated
|
||
| %val = load i32, ptr %merge, align 4 | ||
| %c.2 = icmp slt i32 %val, %n | ||
| br i1 %c.2, label %loop.early.exit, label %loop.latch | ||
|
|
||
| loop.early.exit: | ||
| %iv = phi ptr [ %merge, %loop.header ] | ||
| %pi.iv = ptrtoint ptr %iv to i64 | ||
|
kshitijvp marked this conversation as resolved.
Outdated
|
||
| br label %exit | ||
|
|
||
| loop.latch: | ||
| %gep.merge = getelementptr inbounds nuw i8, ptr %merge, i64 4 | ||
| %c.3 = icmp eq ptr %gep.merge, %l.gep.v | ||
| br i1 %c.3, label %loop.comp, label %loop.header | ||
|
|
||
| loop.comp: | ||
| br label %exit | ||
|
|
||
| exit: | ||
| %mer = phi i64 [ %pi.l.gep.v, %entry ], [ %pi.iv, %loop.early.exit ], [ %pi.l.gep.v, %loop.comp ] | ||
| ret i64 %mer | ||
| } | ||
|
|
||
| define i64 @volatileVectorizingTest(ptr noundef nonnull readonly align 8 captures(none) dereferenceable(24) %v, i32 noundef %n) { | ||
| ; CHECK-LABEL: define i64 @volatileVectorizingTest( | ||
| ; CHECK-SAME: ptr noundef nonnull readonly align 8 captures(none) dereferenceable(24) [[V:%.*]], i32 noundef [[N:%.*]]) { | ||
| ; CHECK-NEXT: [[ENTRY:.*:]] | ||
| ; CHECK-NEXT: [[L_V:%.*]] = load ptr, ptr [[V]], align 8 | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[PI_L_V:%.*]] = ptrtoint ptr [[L_V]] to i64 | ||
| ; CHECK-NEXT: [[GEP_V:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 8 | ||
| ; CHECK-NEXT: [[L_GEP_V:%.*]] = load ptr, ptr [[GEP_V]], align 8 | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_GEP_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[PI_L_GEP_V:%.*]] = ptrtoint ptr [[L_GEP_V]] to i64 | ||
| ; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PI_L_GEP_V]], [[PI_L_V]] | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[L_V]], i64 [[SUB]]) ] | ||
| ; CHECK-NEXT: [[VOLATILE:%.*]] = load volatile ptr, ptr [[V]], align 8 | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_V]], i64 4) ] | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_GEP_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[L_V]], [[L_GEP_V]] | ||
| ; CHECK-NEXT: br i1 [[C_1]], [[EXIT:label %.*]], label %[[LOOP_PREHEADER:.*]] | ||
| ; CHECK: [[LOOP_PREHEADER]]: | ||
| ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[PI_L_GEP_V]], -4 | ||
| ; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[PI_L_V]] | ||
| ; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 2 | ||
| ; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 1 | ||
| ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP3]], 2 | ||
| ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] | ||
| ; CHECK: [[VECTOR_PH]]: | ||
| ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 2 | ||
| ; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[N_MOD_VF]] | ||
| ; CHECK-NEXT: [[TMP4:%.*]] = shl i64 [[N_VEC]], 2 | ||
| ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[L_V]], i64 [[TMP4]] | ||
| ; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i32> poison, i32 [[N]], i64 0 | ||
| ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i32> [[BROADCAST_SPLATINSERT]], <2 x i32> poison, <2 x i32> zeroinitializer | ||
| ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] | ||
| ; CHECK: [[VECTOR_BODY]]: | ||
| ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY_INTERIM:.*]] ] | ||
| ; CHECK-NEXT: [[TMP6:%.*]] = shl i64 [[INDEX]], 2 | ||
| ; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[L_V]], i64 [[TMP6]] | ||
| ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[NEXT_GEP]], align 4 | ||
| ; CHECK-NEXT: [[TMP7:%.*]] = icmp slt <2 x i32> [[WIDE_LOAD]], [[BROADCAST_SPLAT]] | ||
| ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 | ||
| ; CHECK-NEXT: [[TMP8:%.*]] = freeze <2 x i1> [[TMP7]] | ||
| ; CHECK-NEXT: [[TMP9:%.*]] = call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> [[TMP8]]) | ||
| ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] | ||
| ; CHECK-NEXT: br i1 [[TMP9]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[VECTOR_BODY_INTERIM]] | ||
| ; CHECK: [[VECTOR_BODY_INTERIM]]: | ||
| ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP26:![0-9]+]] | ||
| ; CHECK: [[MIDDLE_BLOCK]]: | ||
| ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC]] | ||
| ; CHECK-NEXT: br i1 [[CMP_N]], [[LOOP_COMP:label %.*]], label %[[SCALAR_PH]] | ||
| ; CHECK: [[VECTOR_EARLY_EXIT]]: | ||
| ; CHECK-NEXT: [[TMP11:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v2i1(<2 x i1> [[TMP7]], i1 false) | ||
| ; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], [[TMP11]] | ||
| ; CHECK-NEXT: [[TMP13:%.*]] = shl i64 [[TMP12]], 2 | ||
| ; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[L_V]], i64 [[TMP13]] | ||
| ; CHECK-NEXT: br [[LOOP_EARLY_EXIT:label %.*]] | ||
| ; CHECK: [[SCALAR_PH]]: | ||
| ; | ||
| entry: | ||
| %l.v = load ptr, ptr %v, align 8 | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.v, i64 4) ] | ||
| %pi.l.v = ptrtoint ptr %l.v to i64 | ||
| %gep.v = getelementptr inbounds nuw i8, ptr %v, i64 8 | ||
| %l.gep.v = load ptr, ptr %gep.v, align 8 | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.gep.v, i64 4) ] | ||
| %pi.l.gep.v = ptrtoint ptr %l.gep.v to i64 | ||
| %sub = sub i64 %pi.l.gep.v, %pi.l.v | ||
| call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %l.v, i64 %sub) ] | ||
| %volatile = load volatile ptr, ptr %v, align 8 ; Volatile Instruction | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.v, i64 4) ] | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.gep.v, i64 4) ] | ||
| %c.1 = icmp eq ptr %l.v, %l.gep.v | ||
| br i1 %c.1, label %exit, label %loop.preheader | ||
|
|
||
| loop.preheader: | ||
| br label %loop.header | ||
|
|
||
| loop.header: | ||
| %merge = phi ptr [ %gep.merge, %loop.latch ], [ %l.v, %loop.preheader ] | ||
| %val = load i32, ptr %merge, align 4 | ||
| %c.2 = icmp slt i32 %val, %n | ||
| br i1 %c.2, label %loop.early.exit, label %loop.latch | ||
|
|
||
| loop.early.exit: | ||
| %iv = phi ptr [ %merge, %loop.header ] | ||
| %pi.iv = ptrtoint ptr %iv to i64 | ||
| br label %exit | ||
|
|
||
| loop.latch: | ||
| %gep.merge = getelementptr inbounds nuw i8, ptr %merge, i64 4 | ||
| %c.3 = icmp eq ptr %gep.merge, %l.gep.v | ||
| br i1 %c.3, label %loop.comp, label %loop.header | ||
|
|
||
| loop.comp: | ||
| br label %exit | ||
|
|
||
| exit: | ||
| %mer = phi i64 [ %pi.l.gep.v, %entry ], [ %pi.iv, %loop.early.exit ], [ %pi.l.gep.v, %loop.comp ] | ||
| ret i64 %mer | ||
| } | ||
|
|
||
| define i64 @fenceNotVectorizingTest(ptr noundef nonnull readonly align 8 captures(none) dereferenceable(24) %v, i32 noundef %n) { | ||
| ; CHECK-LABEL: define i64 @fenceNotVectorizingTest( | ||
| ; CHECK-SAME: ptr noundef nonnull readonly align 8 captures(none) dereferenceable(24) [[V:%.*]], i32 noundef [[N:%.*]]) { | ||
| ; CHECK-NEXT: [[ENTRY:.*]]: | ||
| ; CHECK-NEXT: [[L_V:%.*]] = load ptr, ptr [[V]], align 8 | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[PI_L_V:%.*]] = ptrtoint ptr [[L_V]] to i64 | ||
| ; CHECK-NEXT: [[GEP_V:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 8 | ||
| ; CHECK-NEXT: [[L_GEP_V:%.*]] = load ptr, ptr [[GEP_V]], align 8 | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_GEP_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[PI_L_GEP_V:%.*]] = ptrtoint ptr [[L_GEP_V]] to i64 | ||
| ; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PI_L_GEP_V]], [[PI_L_V]] | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[L_V]], i64 [[SUB]]) ] | ||
| ; CHECK-NEXT: fence seq_cst | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_V]], i64 4) ] | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_GEP_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[L_V]], [[L_GEP_V]] | ||
| ; CHECK-NEXT: br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]] | ||
| ; CHECK: [[LOOP_PREHEADER]]: | ||
| ; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] | ||
| ; CHECK: [[LOOP_HEADER]]: | ||
| ; CHECK-NEXT: [[MERGE:%.*]] = phi ptr [ [[GEP_MERGE:%.*]], %[[LOOP_LATCH:.*]] ], [ [[L_V]], %[[LOOP_PREHEADER]] ] | ||
| ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[MERGE]], align 4 | ||
| ; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[VAL]], [[N]] | ||
| ; CHECK-NEXT: br i1 [[C_2]], label %[[LOOP_EARLY_EXIT:.*]], label %[[LOOP_LATCH]] | ||
| ; CHECK: [[LOOP_EARLY_EXIT]]: | ||
| ; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[MERGE]], %[[LOOP_HEADER]] ] | ||
| ; CHECK-NEXT: [[PI_IV:%.*]] = ptrtoint ptr [[IV]] to i64 | ||
| ; CHECK-NEXT: br label %[[EXIT]] | ||
| ; CHECK: [[LOOP_LATCH]]: | ||
| ; CHECK-NEXT: [[GEP_MERGE]] = getelementptr inbounds nuw i8, ptr [[MERGE]], i64 4 | ||
| ; CHECK-NEXT: [[C_3:%.*]] = icmp eq ptr [[GEP_MERGE]], [[L_GEP_V]] | ||
| ; CHECK-NEXT: br i1 [[C_3]], label %[[LOOP_COMP:.*]], label %[[LOOP_HEADER]] | ||
| ; CHECK: [[LOOP_COMP]]: | ||
| ; CHECK-NEXT: br label %[[EXIT]] | ||
| ; CHECK: [[EXIT]]: | ||
| ; CHECK-NEXT: [[MER:%.*]] = phi i64 [ [[PI_L_GEP_V]], %[[ENTRY]] ], [ [[PI_IV]], %[[LOOP_EARLY_EXIT]] ], [ [[PI_L_GEP_V]], %[[LOOP_COMP]] ] | ||
| ; CHECK-NEXT: ret i64 [[MER]] | ||
| ; | ||
| entry: | ||
| %l.v = load ptr, ptr %v, align 8 | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.v, i64 4) ] | ||
| %pi.l.v = ptrtoint ptr %l.v to i64 | ||
| %gep.v = getelementptr inbounds nuw i8, ptr %v, i64 8 | ||
| %l.gep.v = load ptr, ptr %gep.v, align 8 | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.gep.v, i64 4) ] | ||
| %pi.l.gep.v = ptrtoint ptr %l.gep.v to i64 | ||
| %sub = sub i64 %pi.l.gep.v, %pi.l.v | ||
| call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %l.v, i64 %sub) ] | ||
| fence seq_cst ; Fence Instruction | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.v, i64 4) ] | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.gep.v, i64 4) ] | ||
| %c.1 = icmp eq ptr %l.v, %l.gep.v | ||
| br i1 %c.1, label %exit, label %loop.preheader | ||
|
|
||
| loop.preheader: | ||
| br label %loop.header | ||
|
|
||
| loop.header: | ||
| %merge = phi ptr [ %gep.merge, %loop.latch ], [ %l.v, %loop.preheader ] | ||
| %val = load i32, ptr %merge, align 4 | ||
| %c.2 = icmp slt i32 %val, %n | ||
| br i1 %c.2, label %loop.early.exit, label %loop.latch | ||
|
|
||
| loop.early.exit: | ||
| %iv = phi ptr [ %merge, %loop.header ] | ||
| %pi.iv = ptrtoint ptr %iv to i64 | ||
| br label %exit | ||
|
|
||
| loop.latch: | ||
| %gep.merge = getelementptr inbounds nuw i8, ptr %merge, i64 4 | ||
| %c.3 = icmp eq ptr %gep.merge, %l.gep.v | ||
| br i1 %c.3, label %loop.comp, label %loop.header | ||
|
|
||
| loop.comp: | ||
| br label %exit | ||
|
|
||
| exit: | ||
| %mer = phi i64 [ %pi.l.gep.v, %entry ], [ %pi.iv, %loop.early.exit ], [ %pi.l.gep.v, %loop.comp ] | ||
| ret i64 %mer | ||
| } | ||
|
|
||
| define i64 @atomicNotVectorizingTest(ptr noundef nonnull readonly align 8 captures(none) dereferenceable(24) %v, i32 noundef %n) { | ||
| ; CHECK-LABEL: define i64 @atomicNotVectorizingTest( | ||
| ; CHECK-SAME: ptr noundef nonnull readonly align 8 captures(none) dereferenceable(24) [[V:%.*]], i32 noundef [[N:%.*]]) { | ||
| ; CHECK-NEXT: [[ENTRY:.*]]: | ||
| ; CHECK-NEXT: [[L_V:%.*]] = load ptr, ptr [[V]], align 8 | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[PI_L_V:%.*]] = ptrtoint ptr [[L_V]] to i64 | ||
| ; CHECK-NEXT: [[GEP_V:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 8 | ||
| ; CHECK-NEXT: [[L_GEP_V:%.*]] = load ptr, ptr [[GEP_V]], align 8 | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_GEP_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[PI_L_GEP_V:%.*]] = ptrtoint ptr [[L_GEP_V]] to i64 | ||
| ; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PI_L_GEP_V]], [[PI_L_V]] | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[L_V]], i64 [[SUB]]) ] | ||
| ; CHECK-NEXT: [[ATOMIC:%.*]] = load atomic ptr, ptr [[V]] seq_cst, align 8 | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_V]], i64 4) ] | ||
| ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[L_GEP_V]], i64 4) ] | ||
| ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[L_V]], [[L_GEP_V]] | ||
| ; CHECK-NEXT: br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]] | ||
| ; CHECK: [[LOOP_PREHEADER]]: | ||
| ; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] | ||
| ; CHECK: [[LOOP_HEADER]]: | ||
| ; CHECK-NEXT: [[MERGE:%.*]] = phi ptr [ [[GEP_MERGE:%.*]], %[[LOOP_LATCH:.*]] ], [ [[L_V]], %[[LOOP_PREHEADER]] ] | ||
| ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[MERGE]], align 4 | ||
| ; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[VAL]], [[N]] | ||
| ; CHECK-NEXT: br i1 [[C_2]], label %[[LOOP_EARLY_EXIT:.*]], label %[[LOOP_LATCH]] | ||
| ; CHECK: [[LOOP_EARLY_EXIT]]: | ||
| ; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[MERGE]], %[[LOOP_HEADER]] ] | ||
| ; CHECK-NEXT: [[PI_IV:%.*]] = ptrtoint ptr [[IV]] to i64 | ||
| ; CHECK-NEXT: br label %[[EXIT]] | ||
| ; CHECK: [[LOOP_LATCH]]: | ||
| ; CHECK-NEXT: [[GEP_MERGE]] = getelementptr inbounds nuw i8, ptr [[MERGE]], i64 4 | ||
| ; CHECK-NEXT: [[C_3:%.*]] = icmp eq ptr [[GEP_MERGE]], [[L_GEP_V]] | ||
| ; CHECK-NEXT: br i1 [[C_3]], label %[[LOOP_COMP:.*]], label %[[LOOP_HEADER]] | ||
| ; CHECK: [[LOOP_COMP]]: | ||
| ; CHECK-NEXT: br label %[[EXIT]] | ||
| ; CHECK: [[EXIT]]: | ||
| ; CHECK-NEXT: [[MER:%.*]] = phi i64 [ [[PI_L_GEP_V]], %[[ENTRY]] ], [ [[PI_IV]], %[[LOOP_EARLY_EXIT]] ], [ [[PI_L_GEP_V]], %[[LOOP_COMP]] ] | ||
| ; CHECK-NEXT: ret i64 [[MER]] | ||
| ; | ||
| entry: | ||
| %l.v = load ptr, ptr %v, align 8 | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.v, i64 4) ] | ||
| %pi.l.v = ptrtoint ptr %l.v to i64 | ||
| %gep.v = getelementptr inbounds nuw i8, ptr %v, i64 8 | ||
| %l.gep.v = load ptr, ptr %gep.v, align 8 | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.gep.v, i64 4) ] | ||
| %pi.l.gep.v = ptrtoint ptr %l.gep.v to i64 | ||
| %sub = sub i64 %pi.l.gep.v, %pi.l.v | ||
| call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %l.v, i64 %sub) ] | ||
| %atomic = load atomic ptr, ptr %v seq_cst, align 8 ; Atomic Instruction | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.v, i64 4) ] | ||
| call void @llvm.assume(i1 true) [ "align"(ptr %l.gep.v, i64 4) ] | ||
| %c.1 = icmp eq ptr %l.v, %l.gep.v | ||
| br i1 %c.1, label %exit, label %loop.preheader | ||
|
|
||
| loop.preheader: | ||
| br label %loop.header | ||
|
|
||
| loop.header: | ||
| %merge = phi ptr [ %gep.merge, %loop.latch ], [ %l.v, %loop.preheader ] | ||
| %val = load i32, ptr %merge, align 4 | ||
| %c.2 = icmp slt i32 %val, %n | ||
| br i1 %c.2, label %loop.early.exit, label %loop.latch | ||
|
|
||
| loop.early.exit: | ||
| %iv = phi ptr [ %merge, %loop.header ] | ||
| %pi.iv = ptrtoint ptr %iv to i64 | ||
| br label %exit | ||
|
|
||
| loop.latch: | ||
| %gep.merge = getelementptr inbounds nuw i8, ptr %merge, i64 4 | ||
| %c.3 = icmp eq ptr %gep.merge, %l.gep.v | ||
| br i1 %c.3, label %loop.comp, label %loop.header | ||
|
|
||
| loop.comp: | ||
| br label %exit | ||
|
|
||
| exit: | ||
| %mer = phi i64 [ %pi.l.gep.v, %entry ], [ %pi.iv, %loop.early.exit ], [ %pi.l.gep.v, %loop.comp ] | ||
| ret i64 %mer | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.