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.
169 lines
5.4 KiB
LLVM
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
|
|
}
|