-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[AssumeBundles] Dereferenceable used in bundle only applies at assume. #126117
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 all commits
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 |
---|---|---|
|
@@ -1474,7 +1474,9 @@ Currently, only the following parameter attributes are defined: | |
``null_pointer_is_valid`` function attribute is present. | ||
``n`` should be a positive number. The pointer should be well defined, | ||
otherwise it is undefined behavior. This means ``dereferenceable(<n>)`` | ||
implies ``noundef``. | ||
implies ``noundef``. When used in an assume operand bundle, more restricted | ||
semantics apply. See :ref:`assume operand bundles <assume_opbundles>` for | ||
more details. | ||
|
||
``dereferenceable_or_null(<n>)`` | ||
preames marked this conversation as resolved.
Show resolved
Hide resolved
|
||
This indicates that the parameter or return value isn't both | ||
|
@@ -2926,6 +2928,11 @@ the behavior is undefined, unless one of the following exceptions applies: | |
(including a zero alignment). If this is the case, then the pointer value | ||
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. "and may not be" seems like you're referring to the assumption at first. Maybe: ". The pointer may not be " (the rest of the sentence is fine) 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. Updated, thanks! |
||
must be a null pointer, otherwise the behavior is undefined. | ||
|
||
* ``dereferenceable(<n>)`` operand bundles only guarantee the pointer is | ||
dereferenceable at the point of the assumption. The pointer may not be | ||
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. This is indented too far and ends up rendering weirdly. 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. Should hopefully be fixed by 2d6330f |
||
dereferenceable at later pointers, e.g. because it could have been | ||
freed. | ||
|
||
In addition to allowing operand bundles encoding function and parameter | ||
attributes, an assume operand bundle my also encode a ``separate_storage`` | ||
operand bundle. This has the form: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,12 +11,12 @@ define void @f(i32 %ptr_i, ptr %ptr2, i1 %cond) { | |
; CHECK-NEXT: store i32 0, ptr [[PTR2:%.*]], align 4 | ||
; CHECK-NEXT: br label [[FOR_BODY_LR_PH]] | ||
; CHECK: for.body.lr.ph: | ||
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[PTR]], align 4 | ||
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 think you'd preserve test intent by adding nofree nosyc to this one (maybe with a name change), and then adding a separate one without it. It isn't clear to my why with the additional attributes we still can't hoist the load. That's concerning? 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 added So eventually we will probably need more powerful analysis. 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. Maybe add a variant which doesn't involve the inttoptr then? 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. Added a variant at the bottom, thanks |
||
; CHECK-NEXT: br label [[FOR_BODY:%.*]] | ||
; CHECK: for.body: | ||
; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH]] ], [ [[INC:%.*]], [[IF_END:%.*]] ] | ||
; CHECK-NEXT: br i1 [[COND]], label [[IF_END]], label [[IF:%.*]] | ||
; CHECK: if: | ||
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[PTR]], align 4, !invariant.load [[META0:![0-9]+]] | ||
; CHECK-NEXT: store i32 [[TMP0]], ptr [[PTR2]], align 4 | ||
; CHECK-NEXT: br label [[IF_END]] | ||
; CHECK: if.end: | ||
|
@@ -56,4 +56,112 @@ exit: ; preds = %if.end, %entry | |
ret void | ||
} | ||
|
||
define void @f_nofree_nosync(i32 %ptr_i, ptr %ptr2, i1 %cond) nofree nosync { | ||
; CHECK-LABEL: @f_nofree_nosync( | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[PTR_I:%.*]] to ptr | ||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[PTR]], i32 16), "dereferenceable"(ptr [[PTR]], i32 16) ] | ||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR_BODY_LR_PH:%.*]], label [[IF0:%.*]] | ||
; CHECK: if0: | ||
; CHECK-NEXT: store i32 0, ptr [[PTR2:%.*]], align 4 | ||
; CHECK-NEXT: br label [[FOR_BODY_LR_PH]] | ||
; CHECK: for.body.lr.ph: | ||
; CHECK-NEXT: br label [[FOR_BODY:%.*]] | ||
; CHECK: for.body: | ||
; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH]] ], [ [[INC:%.*]], [[IF_END:%.*]] ] | ||
; CHECK-NEXT: br i1 [[COND]], label [[IF_END]], label [[IF:%.*]] | ||
; CHECK: if: | ||
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[PTR]], align 4, !invariant.load [[META0]] | ||
; CHECK-NEXT: store i32 [[TMP0]], ptr [[PTR2]], align 4 | ||
; CHECK-NEXT: br label [[IF_END]] | ||
; CHECK: if.end: | ||
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 | ||
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], 2 | ||
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[EXIT:%.*]] | ||
; CHECK: exit: | ||
; CHECK-NEXT: ret void | ||
; | ||
entry: | ||
%ptr = inttoptr i32 %ptr_i to ptr | ||
call void @llvm.assume(i1 true) [ "align"(ptr %ptr, i32 16), "dereferenceable"(ptr %ptr, i32 16) ] | ||
br i1 %cond, label %for.body.lr.ph, label %if0 | ||
|
||
if0: | ||
store i32 0, ptr %ptr2, align 4 | ||
br label %for.body.lr.ph | ||
|
||
for.body.lr.ph: ; preds = %entry | ||
br label %for.body | ||
|
||
for.body: ; preds = %for.body.lr.ph, %if.end | ||
%i.08 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %if.end ] | ||
br i1 %cond, label %if.end, label %if | ||
|
||
if: | ||
%0 = load i32, ptr %ptr, align 4, !invariant.load !{} | ||
store i32 %0, ptr %ptr2, align 4 | ||
br label %if.end | ||
|
||
if.end: ; preds = %for.body | ||
%inc = add nuw nsw i32 %i.08, 1 | ||
%cmp = icmp slt i32 %inc, 2 | ||
br i1 %cmp, label %for.body, label %exit | ||
|
||
exit: ; preds = %if.end, %entry | ||
ret void | ||
} | ||
|
||
define void @f_without_ptrtoint_and_with_nofree_nosync(ptr %ptr, ptr %ptr2, i1 %cond) nofree nosync { | ||
; CHECK-LABEL: @f_without_ptrtoint_and_with_nofree_nosync( | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[PTR:%.*]], i32 16), "dereferenceable"(ptr [[PTR]], i32 16) ] | ||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR_BODY_LR_PH:%.*]], label [[IF0:%.*]] | ||
; CHECK: if0: | ||
; CHECK-NEXT: store i32 0, ptr [[PTR2:%.*]], align 4 | ||
; CHECK-NEXT: br label [[FOR_BODY_LR_PH]] | ||
; CHECK: for.body.lr.ph: | ||
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[PTR]], align 4 | ||
; CHECK-NEXT: br label [[FOR_BODY:%.*]] | ||
; CHECK: for.body: | ||
; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH]] ], [ [[INC:%.*]], [[IF_END:%.*]] ] | ||
; CHECK-NEXT: br i1 [[COND]], label [[IF_END]], label [[IF:%.*]] | ||
; CHECK: if: | ||
; CHECK-NEXT: store i32 [[TMP0]], ptr [[PTR2]], align 4 | ||
; CHECK-NEXT: br label [[IF_END]] | ||
; CHECK: if.end: | ||
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 | ||
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], 2 | ||
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[EXIT:%.*]] | ||
; CHECK: exit: | ||
; CHECK-NEXT: ret void | ||
; | ||
entry: | ||
call void @llvm.assume(i1 true) [ "align"(ptr %ptr, i32 16), "dereferenceable"(ptr %ptr, i32 16) ] | ||
br i1 %cond, label %for.body.lr.ph, label %if0 | ||
|
||
if0: | ||
store i32 0, ptr %ptr2, align 4 | ||
br label %for.body.lr.ph | ||
|
||
for.body.lr.ph: ; preds = %entry | ||
br label %for.body | ||
|
||
for.body: ; preds = %for.body.lr.ph, %if.end | ||
%i.08 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %if.end ] | ||
br i1 %cond, label %if.end, label %if | ||
|
||
if: | ||
%0 = load i32, ptr %ptr, align 4, !invariant.load !{} | ||
store i32 %0, ptr %ptr2, align 4 | ||
br label %if.end | ||
|
||
if.end: ; preds = %for.body | ||
%inc = add nuw nsw i32 %i.08, 1 | ||
%cmp = icmp slt i32 %inc, 2 | ||
br i1 %cmp, label %for.body, label %exit | ||
|
||
exit: ; preds = %if.end, %entry | ||
ret void | ||
} | ||
|
||
declare void @llvm.assume(i1 noundef) |
Uh oh!
There was an error while loading. Please reload this page.