Skip to content

Commit 6429549

Browse files
committed
[LV] Add early-exit tests, where deref assumes are not in preheader.
Test case for vectorizing std::find_if with builtin_assume_dereferenceable. Currently not vectorized. https://godbolt.org/z/6jbsd4EjT
1 parent 3d41cbb commit 6429549

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

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

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,3 +632,153 @@ loop.end:
632632
%retval = phi i64 [ %index, %loop ], [ -1, %loop.inc ]
633633
ret i64 %retval
634634
}
635+
636+
define i64 @find_if_pointer_distance_deref_via_assumption(ptr %vec) nofree nosync {
637+
; CHECK-LABEL: define i64 @find_if_pointer_distance_deref_via_assumption(
638+
; CHECK-SAME: ptr [[VEC:%.*]]) #[[ATTR0]] {
639+
; CHECK-NEXT: [[ENTRY:.*]]:
640+
; CHECK-NEXT: [[BEGIN:%.*]] = load ptr, ptr [[VEC]], align 8
641+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[BEGIN]], i64 2) ]
642+
; CHECK-NEXT: [[BEGIN_INT:%.*]] = ptrtoint ptr [[BEGIN]] to i64
643+
; CHECK-NEXT: [[END_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8
644+
; CHECK-NEXT: [[END:%.*]] = load ptr, ptr [[END_GEP]], align 8
645+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 2) ]
646+
; CHECK-NEXT: [[END_INT:%.*]] = ptrtoint ptr [[END]] to i64
647+
; CHECK-NEXT: [[DISTANCE:%.*]] = sub i64 [[END_INT]], [[BEGIN_INT]]
648+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[BEGIN]], i64 [[DISTANCE]]) ]
649+
; CHECK-NEXT: [[IS_EMPTY:%.*]] = icmp eq ptr [[BEGIN]], [[END]]
650+
; CHECK-NEXT: br i1 [[IS_EMPTY]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]]
651+
; CHECK: [[LOOP_PREHEADER]]:
652+
; CHECK-NEXT: [[END_PTR:%.*]] = getelementptr i8, ptr [[BEGIN]], i64 [[DISTANCE]]
653+
; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
654+
; CHECK: [[LOOP_HEADER]]:
655+
; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[PTR_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[BEGIN]], %[[LOOP_PREHEADER]] ]
656+
; CHECK-NEXT: [[VAL:%.*]] = load i16, ptr [[PTR]], align 2
657+
; CHECK-NEXT: [[FOUND:%.*]] = icmp eq i16 [[VAL]], 1
658+
; CHECK-NEXT: br i1 [[FOUND]], label %[[EXIT_LOOPEXIT:.*]], label %[[LOOP_LATCH]]
659+
; CHECK: [[LOOP_LATCH]]:
660+
; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 2
661+
; CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[PTR_NEXT]], [[END]]
662+
; CHECK-NEXT: br i1 [[DONE]], label %[[EXIT_LOOPEXIT]], label %[[LOOP_HEADER]]
663+
; CHECK: [[EXIT_LOOPEXIT]]:
664+
; CHECK-NEXT: [[RESULT_PH:%.*]] = phi ptr [ [[END_PTR]], %[[LOOP_LATCH]] ], [ [[PTR]], %[[LOOP_HEADER]] ]
665+
; CHECK-NEXT: [[DOTRESULT_INT:%.*]] = ptrtoint ptr [[RESULT_PH]] to i64
666+
; CHECK-NEXT: br label %[[EXIT]]
667+
; CHECK: [[EXIT]]:
668+
; CHECK-NEXT: [[RESULT_INT:%.*]] = phi i64 [ [[DOTRESULT_INT]], %[[EXIT_LOOPEXIT]] ], [ [[BEGIN_INT]], %[[ENTRY]] ]
669+
; CHECK-NEXT: ret i64 [[RESULT_INT]]
670+
;
671+
entry:
672+
%begin = load ptr, ptr %vec, align 8
673+
call void @llvm.assume(i1 true) [ "align"(ptr %begin, i64 2) ]
674+
%begin.int = ptrtoint ptr %begin to i64
675+
%end.gep = getelementptr inbounds nuw i8, ptr %vec, i64 8
676+
%end = load ptr, ptr %end.gep, align 8
677+
call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 2) ]
678+
%end.int = ptrtoint ptr %end to i64
679+
%distance = sub i64 %end.int, %begin.int
680+
call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %begin, i64 %distance) ]
681+
%is.empty = icmp eq ptr %begin, %end
682+
br i1 %is.empty, label %exit, label %loop.preheader
683+
684+
loop.preheader:
685+
%end.ptr = getelementptr i8, ptr %begin, i64 %distance
686+
br label %loop.header
687+
688+
loop.header:
689+
%ptr = phi ptr [ %ptr.next, %loop.latch ], [ %begin, %loop.preheader ]
690+
%val = load i16, ptr %ptr, align 2
691+
%found = icmp eq i16 %val, 1
692+
br i1 %found, label %exit.loopexit, label %loop.latch
693+
694+
loop.latch:
695+
%ptr.next = getelementptr inbounds nuw i8, ptr %ptr, i64 2
696+
%done = icmp eq ptr %ptr.next, %end
697+
br i1 %done, label %exit.loopexit, label %loop.header
698+
699+
exit.loopexit:
700+
%result.ph = phi ptr [ %end.ptr, %loop.latch ], [ %ptr, %loop.header ]
701+
%.result.int = ptrtoint ptr %result.ph to i64
702+
br label %exit
703+
704+
exit:
705+
%result.int = phi i64 [ %.result.int, %exit.loopexit ], [ %begin.int, %entry ]
706+
ret i64 %result.int
707+
}
708+
709+
declare void @may_free()
710+
711+
define i64 @find_if_pointer_distance_deref_via_assumption_mayfree_call(ptr %vec) nofree {
712+
; CHECK-LABEL: define i64 @find_if_pointer_distance_deref_via_assumption_mayfree_call(
713+
; CHECK-SAME: ptr [[VEC:%.*]]) #[[ATTR2:[0-9]+]] {
714+
; CHECK-NEXT: [[ENTRY:.*]]:
715+
; CHECK-NEXT: [[BEGIN:%.*]] = load ptr, ptr [[VEC]], align 8
716+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[BEGIN]], i64 2) ]
717+
; CHECK-NEXT: [[BEGIN_INT:%.*]] = ptrtoint ptr [[BEGIN]] to i64
718+
; CHECK-NEXT: [[END_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8
719+
; CHECK-NEXT: [[END:%.*]] = load ptr, ptr [[END_GEP]], align 8
720+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 2) ]
721+
; CHECK-NEXT: [[END_INT:%.*]] = ptrtoint ptr [[END]] to i64
722+
; CHECK-NEXT: [[DISTANCE:%.*]] = sub i64 [[END_INT]], [[BEGIN_INT]]
723+
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[BEGIN]], i64 [[DISTANCE]]) ]
724+
; CHECK-NEXT: [[IS_EMPTY:%.*]] = icmp eq ptr [[BEGIN]], [[END]]
725+
; CHECK-NEXT: br i1 [[IS_EMPTY]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]]
726+
; CHECK: [[LOOP_PREHEADER]]:
727+
; CHECK-NEXT: call void @may_free()
728+
; CHECK-NEXT: [[END_PTR:%.*]] = getelementptr i8, ptr [[BEGIN]], i64 [[DISTANCE]]
729+
; CHECK-NEXT: br label %[[LOOP:.*]]
730+
; CHECK: [[LOOP]]:
731+
; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[PTR_NEXT:%.*]], %[[LOOP_INC:.*]] ], [ [[BEGIN]], %[[LOOP_PREHEADER]] ]
732+
; CHECK-NEXT: [[VAL:%.*]] = load i16, ptr [[PTR]], align 2
733+
; CHECK-NEXT: [[FOUND:%.*]] = icmp eq i16 [[VAL]], 1
734+
; CHECK-NEXT: br i1 [[FOUND]], label %[[EXIT_LOOPEXIT:.*]], label %[[LOOP_INC]]
735+
; CHECK: [[LOOP_INC]]:
736+
; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 2
737+
; CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[PTR_NEXT]], [[END]]
738+
; CHECK-NEXT: br i1 [[DONE]], label %[[EXIT_LOOPEXIT]], label %[[LOOP]]
739+
; CHECK: [[EXIT_LOOPEXIT]]:
740+
; CHECK-NEXT: [[RESULT_PH:%.*]] = phi ptr [ [[END_PTR]], %[[LOOP_INC]] ], [ [[PTR]], %[[LOOP]] ]
741+
; CHECK-NEXT: [[DOTRESULT_INT:%.*]] = ptrtoint ptr [[RESULT_PH]] to i64
742+
; CHECK-NEXT: br label %[[EXIT]]
743+
; CHECK: [[EXIT]]:
744+
; CHECK-NEXT: [[RESULT_INT:%.*]] = phi i64 [ [[DOTRESULT_INT]], %[[EXIT_LOOPEXIT]] ], [ [[BEGIN_INT]], %[[ENTRY]] ]
745+
; CHECK-NEXT: ret i64 [[RESULT_INT]]
746+
;
747+
entry:
748+
%begin = load ptr, ptr %vec, align 8
749+
call void @llvm.assume(i1 true) [ "align"(ptr %begin, i64 2) ]
750+
%begin.int = ptrtoint ptr %begin to i64
751+
%end.gep = getelementptr inbounds nuw i8, ptr %vec, i64 8
752+
%end = load ptr, ptr %end.gep, align 8
753+
call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 2) ]
754+
%end.int = ptrtoint ptr %end to i64
755+
%distance = sub i64 %end.int, %begin.int
756+
call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %begin, i64 %distance) ]
757+
%is.empty = icmp eq ptr %begin, %end
758+
br i1 %is.empty, label %exit, label %loop.preheader
759+
760+
loop.preheader:
761+
call void @may_free()
762+
%end.ptr = getelementptr i8, ptr %begin, i64 %distance
763+
br label %loop
764+
765+
loop:
766+
%ptr = phi ptr [ %ptr.next, %loop.inc ], [ %begin, %loop.preheader ]
767+
%val = load i16, ptr %ptr, align 2
768+
%found = icmp eq i16 %val, 1
769+
br i1 %found, label %exit.loopexit, label %loop.inc
770+
771+
loop.inc:
772+
%ptr.next = getelementptr inbounds nuw i8, ptr %ptr, i64 2
773+
%done = icmp eq ptr %ptr.next, %end
774+
br i1 %done, label %exit.loopexit, label %loop
775+
776+
exit.loopexit:
777+
%result.ph = phi ptr [ %end.ptr, %loop.inc ], [ %ptr, %loop ]
778+
%.result.int = ptrtoint ptr %result.ph to i64
779+
br label %exit
780+
781+
exit:
782+
%result.int = phi i64 [ %.result.int, %exit.loopexit ], [ %begin.int, %entry ]
783+
ret i64 %result.int
784+
}

0 commit comments

Comments
 (0)