@@ -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