Skip to content

Commit ab6bd94

Browse files
committed
[ConstraintElim] Add tests for additional SGT->UGT transfer.
Test cases inspired by #63126.
1 parent 8efaf7a commit ab6bd94

File tree

2 files changed

+289
-6
lines changed

2 files changed

+289
-6
lines changed

llvm/test/Transforms/ConstraintElimination/transfer-signed-facts-to-unsigned.ll

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,3 +730,201 @@ entry:
730730
%res.2 = xor i1 %res.1, %c.1
731731
ret i1 %res.2
732732
}
733+
734+
declare void @use(i1)
735+
736+
define i8 @iv_known_non_negative_constant_trip_count(ptr %dst, i8 %N) {
737+
; CHECK-LABEL: @iv_known_non_negative_constant_trip_count(
738+
; CHECK-NEXT: entry:
739+
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
740+
; CHECK: loop.header:
741+
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
742+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IV]], 2
743+
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_LATCH]], label [[EXIT_1:%.*]]
744+
; CHECK: loop.latch:
745+
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[N:%.*]], [[IV]]
746+
; CHECK-NEXT: call void @use(i1 [[T_1]])
747+
; CHECK-NEXT: [[T_2:%.*]] = icmp sgt i8 [[N]], [[IV]]
748+
; CHECK-NEXT: call void @use(i1 [[T_2]])
749+
; CHECK-NEXT: [[F_1:%.*]] = icmp ule i8 [[N]], [[IV]]
750+
; CHECK-NEXT: call void @use(i1 [[F_1]])
751+
; CHECK-NEXT: [[F_2:%.*]] = icmp sle i8 [[N]], [[IV]]
752+
; CHECK-NEXT: call void @use(i1 [[F_2]])
753+
; CHECK-NEXT: [[C_0:%.*]] = icmp ugt i8 [[IV]], 2
754+
; CHECK-NEXT: call void @use(i1 [[C_0]])
755+
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
756+
; CHECK-NEXT: br label [[LOOP_HEADER]]
757+
; CHECK: exit.1:
758+
; CHECK-NEXT: ret i8 10
759+
;
760+
entry:
761+
br label %loop.header
762+
763+
loop.header:
764+
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop.latch ]
765+
%cmp = icmp slt i8 %iv, 2
766+
br i1 %cmp, label %loop.latch, label %exit.1
767+
768+
loop.latch:
769+
%t.1 = icmp ugt i8 %N, %iv
770+
call void @use(i1 %t.1)
771+
%t.2 = icmp sgt i8 %N, %iv
772+
call void @use(i1 %t.2)
773+
%f.1 = icmp ule i8 %N, %iv
774+
call void @use(i1 %f.1)
775+
%f.2 = icmp sle i8 %N, %iv
776+
call void @use(i1 %f.2)
777+
%c.0 = icmp ugt i8 %iv, 2
778+
call void @use(i1 %c.0)
779+
%iv.next = add nuw nsw i8 %iv, 1
780+
br label %loop.header
781+
782+
exit.1:
783+
ret i8 10
784+
}
785+
786+
define i8 @iv_known_non_negative_constant_trip_count_no_nsw_flag(ptr %dst, i8 %N) {
787+
; CHECK-LABEL: @iv_known_non_negative_constant_trip_count_no_nsw_flag(
788+
; CHECK-NEXT: entry:
789+
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
790+
; CHECK: loop.header:
791+
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
792+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IV]], 2
793+
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_LATCH]], label [[EXIT_1:%.*]]
794+
; CHECK: loop.latch:
795+
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[N:%.*]], [[IV]]
796+
; CHECK-NEXT: call void @use(i1 [[T_1]])
797+
; CHECK-NEXT: [[T_2:%.*]] = icmp sgt i8 [[N]], [[IV]]
798+
; CHECK-NEXT: call void @use(i1 [[T_2]])
799+
; CHECK-NEXT: [[F_1:%.*]] = icmp ule i8 [[N]], [[IV]]
800+
; CHECK-NEXT: call void @use(i1 [[F_1]])
801+
; CHECK-NEXT: [[F_2:%.*]] = icmp sle i8 [[N]], [[IV]]
802+
; CHECK-NEXT: call void @use(i1 [[F_2]])
803+
; CHECK-NEXT: [[C_0:%.*]] = icmp ugt i8 [[IV]], 2
804+
; CHECK-NEXT: call void @use(i1 [[C_0]])
805+
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
806+
; CHECK-NEXT: br label [[LOOP_HEADER]]
807+
; CHECK: exit.1:
808+
; CHECK-NEXT: ret i8 10
809+
;
810+
entry:
811+
br label %loop.header
812+
813+
loop.header:
814+
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop.latch ]
815+
%cmp = icmp slt i8 %iv, 2
816+
br i1 %cmp, label %loop.latch, label %exit.1
817+
818+
loop.latch:
819+
%t.1 = icmp ugt i8 %N, %iv
820+
call void @use(i1 %t.1)
821+
%t.2 = icmp sgt i8 %N, %iv
822+
call void @use(i1 %t.2)
823+
%f.1 = icmp ule i8 %N, %iv
824+
call void @use(i1 %f.1)
825+
%f.2 = icmp sle i8 %N, %iv
826+
call void @use(i1 %f.2)
827+
%c.0 = icmp ugt i8 %iv, 2
828+
call void @use(i1 %c.0)
829+
%iv.next = add nuw i8 %iv, 1
830+
br label %loop.header
831+
832+
exit.1:
833+
ret i8 10
834+
}
835+
836+
define i8 @iv_known_non_negative_variable_trip_count(ptr %dst, i8 %N) {
837+
; CHECK-LABEL: @iv_known_non_negative_variable_trip_count(
838+
; CHECK-NEXT: entry:
839+
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
840+
; CHECK: loop.header:
841+
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
842+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IV]], [[N:%.*]]
843+
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_LATCH]], label [[EXIT_1:%.*]]
844+
; CHECK: loop.latch:
845+
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[N]], [[IV]]
846+
; CHECK-NEXT: call void @use(i1 [[T_1]])
847+
; CHECK-NEXT: call void @use(i1 true)
848+
; CHECK-NEXT: [[F_1:%.*]] = icmp ule i8 [[N]], [[IV]]
849+
; CHECK-NEXT: call void @use(i1 [[F_1]])
850+
; CHECK-NEXT: call void @use(i1 false)
851+
; CHECK-NEXT: [[C_0:%.*]] = icmp ugt i8 [[IV]], 2
852+
; CHECK-NEXT: call void @use(i1 [[C_0]])
853+
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
854+
; CHECK-NEXT: br label [[LOOP_HEADER]]
855+
; CHECK: exit.1:
856+
; CHECK-NEXT: ret i8 10
857+
;
858+
entry:
859+
br label %loop.header
860+
861+
loop.header:
862+
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop.latch ]
863+
%cmp = icmp slt i8 %iv, %N
864+
br i1 %cmp, label %loop.latch, label %exit.1
865+
866+
loop.latch:
867+
%t.1 = icmp ugt i8 %N, %iv
868+
call void @use(i1 %t.1)
869+
%t.2 = icmp sgt i8 %N, %iv
870+
call void @use(i1 %t.2)
871+
%f.1 = icmp ule i8 %N, %iv
872+
call void @use(i1 %f.1)
873+
%f.2 = icmp sle i8 %N, %iv
874+
call void @use(i1 %f.2)
875+
%c.0 = icmp ugt i8 %iv, 2
876+
call void @use(i1 %c.0)
877+
%iv.next = add nuw nsw i8 %iv, 1
878+
br label %loop.header
879+
880+
exit.1:
881+
ret i8 10
882+
}
883+
884+
define i8 @iv_may_signed_wrap_variable_trip_count(ptr %dst, i8 %N) {
885+
; CHECK-LABEL: @iv_may_signed_wrap_variable_trip_count(
886+
; CHECK-NEXT: entry:
887+
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
888+
; CHECK: loop.header:
889+
; CHECK-NEXT: [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
890+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IV]], [[N:%.*]]
891+
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_LATCH]], label [[EXIT_1:%.*]]
892+
; CHECK: loop.latch:
893+
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[N]], [[IV]]
894+
; CHECK-NEXT: call void @use(i1 [[T_1]])
895+
; CHECK-NEXT: call void @use(i1 true)
896+
; CHECK-NEXT: [[F_1:%.*]] = icmp ule i8 [[N]], [[IV]]
897+
; CHECK-NEXT: call void @use(i1 [[F_1]])
898+
; CHECK-NEXT: call void @use(i1 false)
899+
; CHECK-NEXT: [[C_0:%.*]] = icmp ugt i8 [[IV]], 2
900+
; CHECK-NEXT: call void @use(i1 [[C_0]])
901+
; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1
902+
; CHECK-NEXT: br label [[LOOP_HEADER]]
903+
; CHECK: exit.1:
904+
; CHECK-NEXT: ret i8 10
905+
;
906+
entry:
907+
br label %loop.header
908+
909+
loop.header:
910+
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop.latch ]
911+
%cmp = icmp slt i8 %iv, %N
912+
br i1 %cmp, label %loop.latch, label %exit.1
913+
914+
loop.latch:
915+
%t.1 = icmp ugt i8 %N, %iv
916+
call void @use(i1 %t.1)
917+
%t.2 = icmp sgt i8 %N, %iv
918+
call void @use(i1 %t.2)
919+
%f.1 = icmp ule i8 %N, %iv
920+
call void @use(i1 %f.1)
921+
%f.2 = icmp sle i8 %N, %iv
922+
call void @use(i1 %f.2)
923+
%c.0 = icmp ugt i8 %iv, 2
924+
call void @use(i1 %c.0)
925+
%iv.next = add nuw i8 %iv, 1
926+
br label %loop.header
927+
928+
exit.1:
929+
ret i8 10
930+
}

llvm/test/Transforms/PhaseOrdering/loop-access-checks.ll

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ define void @foo(ptr noundef nonnull align 8 dereferenceable(24) noalias %vec) #
134134
; CHECK-SAME: (ptr noalias nocapture noundef nonnull readonly align 8 dereferenceable(24) [[VEC:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
135135
; CHECK-NEXT: entry:
136136
; CHECK-NEXT: [[_M_FINISH_I_I:%.*]] = getelementptr inbounds [[VECTOR_IMPL_DATA:%.*]], ptr [[VEC]], i64 0, i32 1
137-
; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[_M_FINISH_I_I]], align 8
138-
; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC]], align 8
137+
; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[_M_FINISH_I_I]], align 8, !tbaa [[TBAA0:![0-9]+]]
138+
; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC]], align 8, !tbaa [[TBAA5:![0-9]+]]
139139
; CHECK-NEXT: [[SUB_PTR_LHS_CAST_I_I:%.*]] = ptrtoint ptr [[TMP0]] to i64
140140
; CHECK-NEXT: [[SUB_PTR_RHS_CAST_I_I:%.*]] = ptrtoint ptr [[TMP1]] to i64
141141
; CHECK-NEXT: [[SUB_PTR_SUB_I_I:%.*]] = sub i64 [[SUB_PTR_LHS_CAST_I_I]], [[SUB_PTR_RHS_CAST_I_I]]
@@ -237,8 +237,8 @@ do.cond:
237237
do.end:
238238
%_M_impl = getelementptr inbounds %Vector_base, ptr %this1, i32 0, i32 0
239239
%_M_start = getelementptr inbounds %Vector_impl_data, ptr %_M_impl, i32 0, i32 0
240-
%1 = load ptr, ptr %_M_start, align 8
241-
%2 = load i64, ptr %__n.addr, align 8
240+
%1 = load ptr, ptr %_M_start, align 8, !tbaa !0
241+
%2 = load i64, ptr %__n.addr, align 8, !tbaa !5
242242
%add.ptr = getelementptr inbounds double, ptr %1, i64 %2
243243
ret ptr %add.ptr
244244
}
@@ -250,10 +250,10 @@ entry:
250250
%this1 = load ptr, ptr %this.addr, align 8
251251
%_M_impl = getelementptr inbounds %Vector_base, ptr %this1, i32 0, i32 0
252252
%_M_finish = getelementptr inbounds %Vector_impl_data, ptr %_M_impl, i32 0, i32 1
253-
%0 = load ptr, ptr %_M_finish, align 8
253+
%0 = load ptr, ptr %_M_finish, align 8, !tbaa !7
254254
%_M_impl2 = getelementptr inbounds %Vector_base, ptr %this1, i32 0, i32 0
255255
%_M_start = getelementptr inbounds %Vector_impl_data, ptr %_M_impl2, i32 0, i32 0
256-
%1 = load ptr, ptr %_M_start, align 8
256+
%1 = load ptr, ptr %_M_start, align 8, !tbaa !0
257257
%sub.ptr.lhs.cast = ptrtoint ptr %0 to i64
258258
%sub.ptr.rhs.cast = ptrtoint ptr %1 to i64
259259
%sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
@@ -263,6 +263,79 @@ entry:
263263

264264
declare void @abort()
265265

266+
; -------------------------------------------------------------------------
267+
; Test case for runtime check removal when accessing vector elements with
268+
; hardened glibc++ and a signed induction variable.
269+
; https://github.com/llvm/llvm-project/issues/63126
270+
271+
define void @loop_with_signed_induction(ptr noundef nonnull align 8 dereferenceable(24) %vec) {
272+
; CHECK-LABEL: define void @loop_with_signed_induction
273+
; CHECK-SAME: (ptr nocapture noundef nonnull readonly align 8 dereferenceable(24) [[VEC:%.*]]) local_unnamed_addr #[[ATTR0]] {
274+
; CHECK-NEXT: entry:
275+
; CHECK-NEXT: [[_M_FINISH_I_I:%.*]] = getelementptr inbounds [[VECTOR_IMPL_DATA:%.*]], ptr [[VEC]], i64 0, i32 1
276+
; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[_M_FINISH_I_I]], align 8, !tbaa [[TBAA0]]
277+
; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VEC]], align 8, !tbaa [[TBAA5]]
278+
; CHECK-NEXT: [[SUB_PTR_LHS_CAST_I_I:%.*]] = ptrtoint ptr [[TMP0]] to i64
279+
; CHECK-NEXT: [[SUB_PTR_RHS_CAST_I_I:%.*]] = ptrtoint ptr [[TMP1]] to i64
280+
; CHECK-NEXT: [[SUB_PTR_SUB_I_I:%.*]] = sub i64 [[SUB_PTR_LHS_CAST_I_I]], [[SUB_PTR_RHS_CAST_I_I]]
281+
; CHECK-NEXT: [[SUB_PTR_DIV_I_I:%.*]] = ashr exact i64 [[SUB_PTR_SUB_I_I]], 3
282+
; CHECK-NEXT: [[CMP9:%.*]] = icmp sgt i64 [[SUB_PTR_DIV_I_I]], 0
283+
; CHECK-NEXT: br i1 [[CMP9]], label [[OPERATOR_ACC_EXIT:%.*]], label [[FOR_COND_CLEANUP:%.*]]
284+
; CHECK: for.cond.cleanup:
285+
; CHECK-NEXT: ret void
286+
; CHECK: operator_acc.exit:
287+
; CHECK-NEXT: [[I_010:%.*]] = phi i64 [ [[INC:%.*]], [[OPERATOR_ACC_EXIT]] ], [ 0, [[ENTRY:%.*]] ]
288+
; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds double, ptr [[TMP1]], i64 [[I_010]]
289+
; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr [[ADD_PTR_I]], align 8, !tbaa [[TBAA6:![0-9]+]]
290+
; CHECK-NEXT: [[ADD:%.*]] = fadd double [[TMP2]], 1.000000e+00
291+
; CHECK-NEXT: store double [[ADD]], ptr [[ADD_PTR_I]], align 8, !tbaa [[TBAA6]]
292+
; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_010]], 1
293+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INC]], [[SUB_PTR_DIV_I_I]]
294+
; CHECK-NEXT: br i1 [[CMP]], label [[OPERATOR_ACC_EXIT]], label [[FOR_COND_CLEANUP]]
295+
;
296+
entry:
297+
%vec.addr = alloca ptr, align 8
298+
%count = alloca i64, align 8
299+
%i = alloca i64, align 8
300+
store ptr %vec, ptr %vec.addr, align 8
301+
call void @llvm.lifetime.start.p0(i64 8, ptr %count)
302+
%0 = load ptr, ptr %vec.addr, align 8
303+
%call = call noundef i64 @alloc(ptr noundef nonnull align 8 dereferenceable(24) %0)
304+
store i64 %call, ptr %count, align 8
305+
call void @llvm.lifetime.start.p0(i64 8, ptr %i)
306+
store i64 0, ptr %i, align 8
307+
br label %for.cond
308+
309+
for.cond:
310+
%1 = load i64, ptr %i, align 8
311+
%2 = load i64, ptr %count, align 8
312+
%cmp = icmp slt i64 %1, %2
313+
br i1 %cmp, label %for.body, label %for.cond.cleanup
314+
315+
for.cond.cleanup:
316+
call void @llvm.lifetime.end.p0(i64 8, ptr %i)
317+
br label %for.end
318+
319+
for.body:
320+
%3 = load ptr, ptr %vec.addr, align 8
321+
%4 = load i64, ptr %i, align 8
322+
%call1 = call noundef nonnull align 8 dereferenceable(8) ptr @operator_acc(ptr noundef nonnull align 8 dereferenceable(24) %3, i64 noundef %4)
323+
%5 = load double, ptr %call1, align 8, !tbaa !8
324+
%add = fadd double %5, 1.000000e+00
325+
store double %add, ptr %call1, align 8, !tbaa !8
326+
br label %for.inc
327+
328+
for.inc:
329+
%6 = load i64, ptr %i, align 8
330+
%inc = add nsw i64 %6, 1
331+
store i64 %inc, ptr %i, align 8
332+
br label %for.cond
333+
334+
for.end:
335+
call void @llvm.lifetime.end.p0(i64 8, ptr %count)
336+
ret void
337+
}
338+
266339
; -------------------------------------------------------------------------
267340
; Test case for runtime check removal when accessing elements in a nested loop
268341
; (PR64881)
@@ -386,3 +459,15 @@ if.end: ; preds = %entry
386459
%add.ptr = getelementptr inbounds i32, ptr %2, i64 %idx.ext
387460
ret ptr %add.ptr
388461
}
462+
463+
464+
!0 = !{!1, !2, i64 0}
465+
!1 = !{!"_ZTSNSt12_Vector_baseIdSaIdEE17_Vector_impl_dataE", !2, i64 0, !2, i64 8, !2, i64 16}
466+
!2 = !{!"any pointer", !3, i64 0}
467+
!3 = !{!"omnipotent char", !4, i64 0}
468+
!4 = !{!"Simple C++ TBAA"}
469+
!5 = !{!6, !6, i64 0}
470+
!6 = !{!"long", !3, i64 0}
471+
!7 = !{!1, !2, i64 8}
472+
!8 = !{!9, !9, i64 0}
473+
!9 = !{!"double", !3, i64 0}

0 commit comments

Comments
 (0)