Skip to content

Commit b169302

Browse files
committed
[LV] Add additional tests for reasoning about dereferenceable loads.
Includes a test for the crash exposed by 08001cf.
1 parent be1e50f commit b169302

File tree

2 files changed

+109
-2
lines changed

2 files changed

+109
-2
lines changed

llvm/test/Transforms/LoopVectorize/single-early-exit-deref-assumptions.ll

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,62 @@ loop.end:
120120
ret i64 %retval
121121
}
122122

123-
define i64 @early_exit_alignment_and_deref_known_via_assumption(ptr noalias %p1, ptr noalias %p2, i64 %n) nofree nosync {
124-
; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_known_via_assumption(
123+
define i64 @early_exit_alignment_and_deref_known_via_assumption_n_not_zero(ptr noalias %p1, ptr noalias %p2, i64 %n) nofree nosync {
124+
; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_known_via_assumption_n_not_zero(
125+
; CHECK-SAME: ptr noalias [[P1:%.*]], ptr noalias [[P2:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {
126+
; CHECK-NEXT: entry:
127+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P1]], i64 4), "dereferenceable"(ptr [[P1]], i64 [[N]]) ]
128+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 4), "dereferenceable"(ptr [[P2]], i64 [[N]]) ]
129+
; CHECK-NEXT: [[C:%.*]] = icmp ne i64 [[N]], 0
130+
; CHECK-NEXT: br i1 [[C]], label [[LOOP_PREHEADER:%.*]], label [[LOOP_END:%.*]]
131+
; CHECK: loop.preheader:
132+
; CHECK-NEXT: br label [[LOOP:%.*]]
133+
; CHECK: loop:
134+
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
135+
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]
136+
; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
137+
; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]
138+
; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
139+
; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]]
140+
; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END_LOOPEXIT:%.*]]
141+
; CHECK: loop.inc:
142+
; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1
143+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], [[N]]
144+
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END_LOOPEXIT]]
145+
; CHECK: loop.end.loopexit:
146+
; CHECK-NEXT: [[RETVAL_PH:%.*]] = phi i64 [ -1, [[LOOP_INC]] ], [ [[INDEX]], [[LOOP]] ]
147+
; CHECK-NEXT: br label [[LOOP_END]]
148+
; CHECK: loop.end:
149+
; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[RETVAL_PH]], [[LOOP_END_LOOPEXIT]] ]
150+
; CHECK-NEXT: ret i64 [[RETVAL]]
151+
;
152+
entry:
153+
call void @llvm.assume(i1 true) [ "align"(ptr %p1, i64 4), "dereferenceable"(ptr %p1, i64 %n) ]
154+
call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 4), "dereferenceable"(ptr %p2, i64 %n) ]
155+
%c = icmp ne i64 %n, 0
156+
br i1 %c, label %loop, label %loop.end
157+
158+
loop:
159+
%index = phi i64 [ %index.next, %loop.inc ], [ 0, %entry ]
160+
%arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
161+
%ld1 = load i8, ptr %arrayidx, align 1
162+
%arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
163+
%ld2 = load i8, ptr %arrayidx1, align 1
164+
%cmp3 = icmp eq i8 %ld1, %ld2
165+
br i1 %cmp3, label %loop.inc, label %loop.end
166+
167+
loop.inc:
168+
%index.next = add i64 %index, 1
169+
%exitcond = icmp ne i64 %index.next, %n
170+
br i1 %exitcond, label %loop, label %loop.end
171+
172+
loop.end:
173+
%retval = phi i64 [ 0, %entry ], [ %index, %loop ], [ -1, %loop.inc ]
174+
ret i64 %retval
175+
}
176+
177+
define i64 @early_exit_alignment_and_deref_known_via_assumption_n_may_be_zero(ptr noalias %p1, ptr noalias %p2, i64 %n) nofree nosync {
178+
; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_known_via_assumption_n_may_be_zero(
125179
; CHECK-SAME: ptr noalias [[P1:%.*]], ptr noalias [[P2:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {
126180
; CHECK-NEXT: entry:
127181
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P1]], i64 4), "dereferenceable"(ptr [[P1]], i64 [[N]]) ]

llvm/test/Transforms/LoopVectorize/single_early_exit.ll

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,59 @@ exit:
514514

515515
declare i32 @llvm.smin.i32(i32, i32)
516516

517+
@A = external global [100 x {i32, i8} ]
518+
519+
define ptr @btc_and_max_btc_require_predicates(ptr noalias %start, i64 %offset) {
520+
; CHECK-LABEL: define ptr @btc_and_max_btc_require_predicates(
521+
; CHECK-SAME: ptr noalias [[START:%.*]], i64 [[OFFSET:%.*]]) {
522+
; CHECK-NEXT: entry:
523+
; CHECK-NEXT: [[END:%.*]] = getelementptr i32, ptr [[START]], i64 [[OFFSET]]
524+
; CHECK-NEXT: [[PRE_1:%.*]] = icmp ult i64 [[OFFSET]], 100
525+
; CHECK-NEXT: call void @llvm.assume(i1 [[PRE_1]])
526+
; CHECK-NEXT: [[PRE_2:%.*]] = icmp ugt i64 [[OFFSET]], 1
527+
; CHECK-NEXT: call void @llvm.assume(i1 [[PRE_2]])
528+
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
529+
; CHECK: loop.header:
530+
; CHECK-NEXT: [[IV_1:%.*]] = phi ptr [ @A, [[ENTRY:%.*]] ], [ [[IV_1_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
531+
; CHECK-NEXT: [[IV_2:%.*]] = phi ptr [ [[START]], [[ENTRY]] ], [ [[IV_2_NEXT:%.*]], [[LOOP_LATCH]] ]
532+
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[IV_1]], align 4
533+
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0
534+
; CHECK-NEXT: br i1 [[C]], label [[LOOP_LATCH]], label [[EXIT:%.*]]
535+
; CHECK: loop.latch:
536+
; CHECK-NEXT: [[IV_2_NEXT]] = getelementptr i8, ptr [[IV_2]], i64 40
537+
; CHECK-NEXT: [[IV_1_NEXT]] = getelementptr i8, ptr [[IV_1]], i64 40
538+
; CHECK-NEXT: [[EC:%.*]] = icmp eq ptr [[IV_2]], [[END]]
539+
; CHECK-NEXT: br i1 [[EC]], label [[EXIT]], label [[LOOP_HEADER]]
540+
; CHECK: exit:
541+
; CHECK-NEXT: [[RES:%.*]] = phi ptr [ [[IV_1]], [[LOOP_HEADER]] ], [ [[IV_2]], [[LOOP_LATCH]] ]
542+
; CHECK-NEXT: ret ptr [[RES]]
543+
;
544+
entry:
545+
%end = getelementptr i32, ptr %start, i64 %offset
546+
%pre.1 = icmp ult i64 %offset, 100
547+
call void @llvm.assume(i1 %pre.1)
548+
%pre.2 = icmp ugt i64 %offset, 1
549+
call void @llvm.assume(i1 %pre.2)
550+
br label %loop.header
551+
552+
loop.header:
553+
%iv.1 = phi ptr [ @A, %entry ], [ %iv.1.next, %loop.latch ]
554+
%iv.2 = phi ptr [ %start, %entry ], [ %iv.2.next, %loop.latch ]
555+
%l = load i32, ptr %iv.1, align 4
556+
%c = icmp eq i32 %l, 0
557+
br i1 %c, label %loop.latch, label %exit
558+
559+
loop.latch:
560+
%iv.2.next = getelementptr i8, ptr %iv.2, i64 40
561+
%iv.1.next = getelementptr i8, ptr %iv.1, i64 40
562+
%ec = icmp eq ptr %iv.2, %end
563+
br i1 %ec, label %exit, label %loop.header
564+
565+
exit:
566+
%res = phi ptr [ %iv.1, %loop.header ], [ %iv.2, %loop.latch ]
567+
ret ptr %res
568+
}
569+
517570
;.
518571
; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]}
519572
; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1}

0 commit comments

Comments
 (0)