-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Loads] Respect UseDerefAtPointSemantics in isDerefAndAlignedPointer. #123196
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 |
---|---|---|
@@ -1,9 +1,9 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 | ||
; RUN: opt -p loop-vectorize -force-vector-width=2 -use-dereferenceable-at-point-semantics=1 -S %s | FileCheck %s | ||
; RUN: opt -p loop-vectorize -force-vector-width=2 -use-dereferenceable-at-point-semantics -S %s | FileCheck %s | ||
|
||
declare void @llvm.assume(i1) | ||
|
||
define void @deref_assumption_in_header_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_in_header_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
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. FWIW, I consider this a bug in our nofree semantics, and a large part of the reason why this never made progress :) Frontends often have knowledge that a certain pointer is not going to be freed in the function (including via synchronization), but they don't have knowledge about whether it may be involved in synchronization. The current semantics make it impossible to convey such facts. |
||
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1:[0-9]+]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -104,7 +104,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -181,7 +181,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_too_small_in_header_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_too_small_in_header_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_too_small_in_header_constant_trip_count( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -282,7 +282,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_in_header_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_in_header_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_1( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -383,7 +383,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_in_header_constant_trip_count_align_via_arg_attribute(ptr noalias align 4 %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_in_header_constant_trip_count_align_via_arg_attribute(ptr noalias align 4 %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_via_arg_attribute( | ||
; CHECK-SAME: ptr noalias align 4 [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -484,7 +484,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_in_header_constant_trip_count_align_not_known(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_in_header_constant_trip_count_align_not_known(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_in_header_constant_trip_count_align_not_known( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -585,7 +585,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_in_then_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_in_then_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_in_then_constant_trip_count( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -682,7 +682,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_in_latch_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_in_latch_constant_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_in_latch_constant_trip_count( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -785,7 +785,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_in_header_variable_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c, i64 %N) nofree { | ||
define void @deref_assumption_in_header_variable_trip_count(ptr noalias %a, ptr noalias %b, ptr noalias %c, i64 %N) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_in_header_variable_trip_count( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], i64 [[N:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -890,7 +890,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_in_preheader_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_in_preheader_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_1( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -968,7 +968,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_1(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_1( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -1063,7 +1063,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @align_and_deref_assumption_in_preheader_constant_trip_count_align_4(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @align_and_deref_assumption_in_preheader_constant_trip_count_align_4(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @align_and_deref_assumption_in_preheader_constant_trip_count_align_4( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -1142,7 +1142,7 @@ exit: | |
} | ||
|
||
|
||
define void @deref_assumption_in_preheader_constant_trip_count_align_4_known_via_argument_attr(ptr noalias align 4 %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_in_preheader_constant_trip_count_align_4_known_via_argument_attr(ptr noalias align 4 %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_4_known_via_argument_attr( | ||
; CHECK-SAME: ptr noalias align 4 [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -1220,7 +1220,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_in_preheader_constant_trip_count_align_4_not_known(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_in_preheader_constant_trip_count_align_4_not_known(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_in_preheader_constant_trip_count_align_4_not_known( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -1315,7 +1315,7 @@ exit: | |
ret void | ||
} | ||
|
||
define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_4(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree { | ||
define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_4(ptr noalias %a, ptr noalias %b, ptr noalias %c) nofree nosync{ | ||
; CHECK-LABEL: define void @deref_assumption_too_small_in_preheader_constant_trip_count_align_4( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
|
@@ -1410,8 +1410,8 @@ exit: | |
ret void | ||
} | ||
|
||
; %a may be freeed between the dereferenceable assumption and accesses. | ||
; FIXME: It is not safe to use with -use-dereferenceable-at-point-semantics. | ||
; %a may be freed between the dereferenceable assumption and accesses. | ||
; It is not safe to use with -use-dereferenceable-at-point-semantics. | ||
define void @may_free_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %a, ptr noalias %b, ptr noalias %c) { | ||
; CHECK-LABEL: define void @may_free_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr( | ||
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) { | ||
|
@@ -1422,16 +1422,29 @@ define void @may_free_align_deref_assumption_in_header_constant_trip_count_loop_ | |
; CHECK: [[VECTOR_PH]]: | ||
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] | ||
; CHECK: [[VECTOR_BODY]]: | ||
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] | ||
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ] | ||
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 | ||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]] | ||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 | ||
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4 | ||
; CHECK-NEXT: [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer | ||
; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[A]], align 4 | ||
; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true) | ||
; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0 | ||
; CHECK-NEXT: br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]] | ||
; CHECK: [[PRED_LOAD_IF]]: | ||
; CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[A]], align 4 | ||
; CHECK-NEXT: [[TMP13:%.*]] = insertelement <2 x i32> poison, i32 [[TMP5]], i32 0 | ||
; CHECK-NEXT: [[TMP11:%.*]] = insertelement <2 x i32> [[TMP13]], i32 [[TMP15]], i32 1 | ||
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x i32> poison, i32 [[TMP15]], i32 0 | ||
; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]] | ||
; CHECK: [[PRED_LOAD_CONTINUE]]: | ||
; CHECK-NEXT: [[TMP12:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP7]], %[[PRED_LOAD_IF]] ] | ||
; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1 | ||
; CHECK-NEXT: br i1 [[TMP13]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]] | ||
; CHECK: [[PRED_LOAD_IF1]]: | ||
; CHECK-NEXT: [[TMP14:%.*]] = load i32, ptr [[A]], align 4 | ||
; CHECK-NEXT: [[TMP16:%.*]] = insertelement <2 x i32> [[TMP12]], i32 [[TMP14]], i32 1 | ||
; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]] | ||
; CHECK: [[PRED_LOAD_CONTINUE2]]: | ||
; CHECK-NEXT: [[TMP11:%.*]] = phi <2 x i32> [ [[TMP12]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP16]], %[[PRED_LOAD_IF1]] ] | ||
; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP11]] | ||
; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]] | ||
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[TMP8]], i32 0 | ||
|
@@ -1491,6 +1504,103 @@ exit: | |
ret void | ||
} | ||
|
||
; %a may be freed between the dereferenceable assumption and accesses. | ||
; It is not safe to use with -use-dereferenceable-at-point-semantics. | ||
define void @may_free_local_ptr_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr(ptr noalias %b, ptr noalias %c) nofree nosync { | ||
; CHECK-LABEL: define void @may_free_local_ptr_align_deref_assumption_in_header_constant_trip_count_loop_invariant_ptr( | ||
; CHECK-SAME: ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR1]] { | ||
; CHECK-NEXT: [[ENTRY:.*]]: | ||
; CHECK-NEXT: [[A:%.*]] = call ptr @get_ptr() | ||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 4), "dereferenceable"(ptr [[A]], i64 4) ] | ||
; CHECK-NEXT: call void @may_free() | ||
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] | ||
; CHECK: [[VECTOR_PH]]: | ||
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] | ||
; CHECK: [[VECTOR_BODY]]: | ||
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE2:.*]] ] | ||
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 | ||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[TMP0]] | ||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i32 0 | ||
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP2]], align 4 | ||
; CHECK-NEXT: [[TMP3:%.*]] = icmp sge <2 x i32> [[WIDE_LOAD]], zeroinitializer | ||
; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i1> [[TMP3]], splat (i1 true) | ||
; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP4]], i32 0 | ||
; CHECK-NEXT: br i1 [[TMP5]], label %[[PRED_LOAD_IF:.*]], label %[[PRED_LOAD_CONTINUE:.*]] | ||
; CHECK: [[PRED_LOAD_IF]]: | ||
; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[A]], align 4 | ||
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x i32> poison, i32 [[TMP6]], i32 0 | ||
; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE]] | ||
; CHECK: [[PRED_LOAD_CONTINUE]]: | ||
; CHECK-NEXT: [[TMP8:%.*]] = phi <2 x i32> [ poison, %[[VECTOR_BODY]] ], [ [[TMP7]], %[[PRED_LOAD_IF]] ] | ||
; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i1> [[TMP4]], i32 1 | ||
; CHECK-NEXT: br i1 [[TMP9]], label %[[PRED_LOAD_IF1:.*]], label %[[PRED_LOAD_CONTINUE2]] | ||
; CHECK: [[PRED_LOAD_IF1]]: | ||
; CHECK-NEXT: [[TMP10:%.*]] = load i32, ptr [[A]], align 4 | ||
; CHECK-NEXT: [[TMP11:%.*]] = insertelement <2 x i32> [[TMP8]], i32 [[TMP10]], i32 1 | ||
; CHECK-NEXT: br label %[[PRED_LOAD_CONTINUE2]] | ||
; CHECK: [[PRED_LOAD_CONTINUE2]]: | ||
; CHECK-NEXT: [[TMP12:%.*]] = phi <2 x i32> [ [[TMP8]], %[[PRED_LOAD_CONTINUE]] ], [ [[TMP11]], %[[PRED_LOAD_IF1]] ] | ||
; CHECK-NEXT: [[PREDPHI:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[WIDE_LOAD]], <2 x i32> [[TMP12]] | ||
; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[TMP0]] | ||
; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i32 0 | ||
; CHECK-NEXT: store <2 x i32> [[PREDPHI]], ptr [[TMP14]], align 4 | ||
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 | ||
; CHECK-NEXT: [[TMP15:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000 | ||
; CHECK-NEXT: br i1 [[TMP15]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP34:![0-9]+]] | ||
; CHECK: [[MIDDLE_BLOCK]]: | ||
; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]] | ||
; CHECK: [[SCALAR_PH]]: | ||
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 1000, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ] | ||
; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] | ||
; CHECK: [[LOOP_HEADER]]: | ||
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] | ||
; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]] | ||
; CHECK-NEXT: [[L_B:%.*]] = load i32, ptr [[GEP_B]], align 4 | ||
; CHECK-NEXT: [[C_1:%.*]] = icmp sge i32 [[L_B]], 0 | ||
; CHECK-NEXT: br i1 [[C_1]], label %[[LOOP_LATCH]], label %[[LOOP_THEN:.*]] | ||
; CHECK: [[LOOP_THEN]]: | ||
; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[A]], align 4 | ||
; CHECK-NEXT: br label %[[LOOP_LATCH]] | ||
; CHECK: [[LOOP_LATCH]]: | ||
; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[L_A]], %[[LOOP_THEN]] ], [ [[L_B]], %[[LOOP_HEADER]] ] | ||
; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr inbounds i32, ptr [[C]], i64 [[IV]] | ||
; CHECK-NEXT: store i32 [[MERGE]], ptr [[GEP_C]], align 4 | ||
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 | ||
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 1000 | ||
; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP35:![0-9]+]] | ||
; CHECK: [[EXIT]]: | ||
; CHECK-NEXT: ret void | ||
; | ||
entry: | ||
%a = call ptr @get_ptr() | ||
call void @llvm.assume(i1 true) [ "align"(ptr %a, i64 4), "dereferenceable"(ptr %a, i64 4) ] | ||
call void @may_free() | ||
br label %loop.header | ||
|
||
loop.header: | ||
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] | ||
%gep.b = getelementptr inbounds i32, ptr %b, i64 %iv | ||
%l.b = load i32, ptr %gep.b, align 4 | ||
%c.1 = icmp sge i32 %l.b, 0 | ||
br i1 %c.1, label %loop.latch, label %loop.then | ||
|
||
loop.then: | ||
%l.a = load i32, ptr %a, align 4 | ||
br label %loop.latch | ||
|
||
loop.latch: | ||
%merge = phi i32 [ %l.a, %loop.then ], [ %l.b, %loop.header ] | ||
%gep.c = getelementptr inbounds i32, ptr %c, i64 %iv | ||
store i32 %merge, ptr %gep.c, align 4 | ||
%iv.next = add nuw nsw i64 %iv, 1 | ||
%ec = icmp eq i64 %iv.next, 1000 | ||
br i1 %ec, label %exit, label %loop.header | ||
|
||
exit: | ||
ret void | ||
} | ||
|
||
declare ptr @get_ptr() | ||
declare void @may_free() | ||
|
||
;. | ||
|
@@ -1528,4 +1638,6 @@ declare void @may_free() | |
; CHECK: [[LOOP31]] = distinct !{[[LOOP31]], [[META2]], [[META1]]} | ||
; CHECK: [[LOOP32]] = distinct !{[[LOOP32]], [[META1]], [[META2]]} | ||
; CHECK: [[LOOP33]] = distinct !{[[LOOP33]], [[META2]], [[META1]]} | ||
; CHECK: [[LOOP34]] = distinct !{[[LOOP34]], [[META1]], [[META2]]} | ||
; CHECK: [[LOOP35]] = distinct !{[[LOOP35]], [[META2]], [[META1]]} | ||
;. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this unconditional, regardless of the value of UseDerefAtPointSemantics? The way I'd view this is that UseDerefAtPointSemantics is for dereferenceable argument attributes. We can/should make assumptions always use at-point semantics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My plan was first making things correct with the flag, then change the behavior for the attribute in assumes + langref change separately.
I can also pull it in here, although I still need to inspect the other uses of dereferenceable assumptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, that's fin by me.