Files
clang-p2996/llvm/test/Transforms/InstCombine/strnlen-2.ll
Nikita Popov 635f93dff7 [SimplifyLibCalls] Place deref attr even if nonnull already set
If nonnull is already set, we currently skip setting both nonnull
and dereferenceable. Make these independent, to avoid regressions
when additional nonnull attributes are inferred earlier.
2022-10-04 11:26:15 +02:00

169 lines
5.4 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Verify that strnlen calls with conditional expressions involving constant
; string arguments and constant bounds are folded correctly.
;
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
declare i64 @strnlen(ptr, i64)
@s3 = constant [4 x i8] c"123\00"
@s5 = constant [6 x i8] c"12345\00"
@s5_3 = constant [10 x i8] c"12345\00678\00"
@s6 = constant [7 x i8] c"123456\00"
@s7 = constant [8 x i8] c"1234567\00"
; Fold strnlen (C ? s3 : s5, 0) to 0.
define i64 @fold_strnlen_s3_s5_0(i1 %C) {
; CHECK-LABEL: @fold_strnlen_s3_s5_0(
; CHECK-NEXT: ret i64 0
;
%ptr = select i1 %C, ptr @s3, ptr @s6
%len = call i64 @strnlen(ptr %ptr, i64 0)
ret i64 %len
}
; Fold strnlen (C ? s3 : s5, 1) to 1.
define i64 @fold_strnlen_s3_s5_1(i1 %C) {
; CHECK-LABEL: @fold_strnlen_s3_s5_1(
; CHECK-NEXT: ret i64 1
;
%ptr = select i1 %C, ptr @s3, ptr @s6
%len = call i64 @strnlen(ptr %ptr, i64 1)
ret i64 %len
}
; Fold strnlen (C ? s3 : s5, 3) to 3.
define i64 @fold_strnlen_s3_s5_3(i1 %C) {
; CHECK-LABEL: @fold_strnlen_s3_s5_3(
; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], ptr @s3, ptr @s6
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR]], i64 3)
; CHECK-NEXT: ret i64 [[LEN]]
;
%ptr = select i1 %C, ptr @s3, ptr @s6
%len = call i64 @strnlen(ptr %ptr, i64 3)
ret i64 %len
}
; Fold strnlen (C ? s3 : s5, 4) to C ? 3 : 4.
define i64 @fold_strnlen_s3_s5_4(i1 %C) {
; CHECK-LABEL: @fold_strnlen_s3_s5_4(
; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], ptr @s3, ptr @s6
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR]], i64 4)
; CHECK-NEXT: ret i64 [[LEN]]
;
%ptr = select i1 %C, ptr @s3, ptr @s6
%len = call i64 @strnlen(ptr %ptr, i64 4)
ret i64 %len
}
; Fold strnlen (C ? s3 : s5, 5) to C ? 3 : 5.
define i64 @fold_strnlen_s3_s5_5(i1 %C) {
; CHECK-LABEL: @fold_strnlen_s3_s5_5(
; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], ptr @s3, ptr @s6
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR]], i64 5)
; CHECK-NEXT: ret i64 [[LEN]]
;
%ptr = select i1 %C, ptr @s3, ptr @s6
%len = call i64 @strnlen(ptr %ptr, i64 5)
ret i64 %len
}
; Fold strnlen (C ? s3 : s5, 6) to C ? 3 : 5.
define i64 @fold_strnlen_s5_6(i1 %C) {
; CHECK-LABEL: @fold_strnlen_s5_6(
; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], ptr @s5, ptr @s6
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR]], i64 6)
; CHECK-NEXT: ret i64 [[LEN]]
;
%ptr = select i1 %C, ptr @s5, ptr @s6
%len = call i64 @strnlen(ptr %ptr, i64 6)
ret i64 %len
}
; Fold strnlen(E, N) with E being two conditional expressions:
; strlen (x == 3 ? s3 : x == 5 ? s5 : s7, 4) to x == 3 ? 3 : 4.
define i64 @fold_strnlen_s3_s5_s7_4(i32 %X) {
; CHECK-LABEL: @fold_strnlen_s3_s5_s7_4(
; CHECK-NEXT: [[X_EQ_3:%.*]] = icmp eq i32 [[X:%.*]], 3
; CHECK-NEXT: [[X_EQ_5:%.*]] = icmp eq i32 [[X]], 5
; CHECK-NEXT: [[SEL_X_EQ_5:%.*]] = select i1 [[X_EQ_5]], ptr @s5, ptr @s7
; CHECK-NEXT: [[SEL_X_EQ_3:%.*]] = select i1 [[X_EQ_3]], ptr @s3, ptr [[SEL_X_EQ_5]]
; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[SEL_X_EQ_3]], i64 4)
; CHECK-NEXT: ret i64 [[LEN]]
;
%x_eq_3 = icmp eq i32 %X, 3
%x_eq_5 = icmp eq i32 %X, 5
%sel_x_eq_5 = select i1 %x_eq_5, ptr @s5, ptr @s7
%sel_x_eq_3 = select i1 %x_eq_3, ptr @s3, ptr %sel_x_eq_5
%len = tail call i64 @strnlen(ptr %sel_x_eq_3, i64 4)
ret i64 %len
}
; As above, fold strnlen(E, N) with E being two conditional expressions
; but with N == 6:
; strlen (x == 3 ? s3 : x == 5 ? s5 : s7, 6) to x == 3 ? 3 : x == 5 ? 5 : 6.
define i64 @fold_strnlen_s3_s5_s7_6(i32 %X) {
; CHECK-LABEL: @fold_strnlen_s3_s5_s7_6(
; CHECK-NEXT: [[X_EQ_3:%.*]] = icmp eq i32 [[X:%.*]], 3
; CHECK-NEXT: [[X_EQ_5:%.*]] = icmp eq i32 [[X]], 5
; CHECK-NEXT: [[SEL_X_EQ_5:%.*]] = select i1 [[X_EQ_5]], ptr @s5, ptr @s7
; CHECK-NEXT: [[SEL_X_EQ_3:%.*]] = select i1 [[X_EQ_3]], ptr @s3, ptr [[SEL_X_EQ_5]]
; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[SEL_X_EQ_3]], i64 6)
; CHECK-NEXT: ret i64 [[LEN]]
;
%x_eq_3 = icmp eq i32 %X, 3
%x_eq_5 = icmp eq i32 %X, 5
%sel_x_eq_5 = select i1 %x_eq_5, ptr @s5, ptr @s7
%sel_x_eq_3 = select i1 %x_eq_3, ptr @s3, ptr %sel_x_eq_5
%len = tail call i64 @strnlen(ptr %sel_x_eq_3, i64 6)
ret i64 %len
}
; And again, fold strnlen(E, N) with E being two conditional expressions
; but with N == 8:
; strlen (x == 3 ? s3 : x == 5 ? s5 : s7, 8) to x == 3 ? 3 : x == 5 ? 5 : 7.
define i64 @fold_strnlen_s3_s5_s7_8(i32 %X) {
; CHECK-LABEL: @fold_strnlen_s3_s5_s7_8(
; CHECK-NEXT: [[X_EQ_3:%.*]] = icmp eq i32 [[X:%.*]], 3
; CHECK-NEXT: [[X_EQ_5:%.*]] = icmp eq i32 [[X]], 5
; CHECK-NEXT: [[SEL_X_EQ_5:%.*]] = select i1 [[X_EQ_5]], ptr @s5, ptr @s7
; CHECK-NEXT: [[SEL_X_EQ_3:%.*]] = select i1 [[X_EQ_3]], ptr @s3, ptr [[SEL_X_EQ_5]]
; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[SEL_X_EQ_3]], i64 8)
; CHECK-NEXT: ret i64 [[LEN]]
;
%x_eq_3 = icmp eq i32 %X, 3
%x_eq_5 = icmp eq i32 %X, 5
%sel_x_eq_5 = select i1 %x_eq_5, ptr @s5, ptr @s7
%sel_x_eq_3 = select i1 %x_eq_3, ptr @s3, ptr %sel_x_eq_5
%len = tail call i64 @strnlen(ptr %sel_x_eq_3, i64 8)
ret i64 %len
}