xref: /llvm-project/llvm/test/Transforms/InstCombine/strnlen-1.ll (revision 2caaec65c04ea7d0e9568b7895b7a46d6100cb75)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Verify that strnlen calls with constant string arguments and offsets
3; and constant bounds are folded correctly.
4;
5; RUN: opt < %s -passes=instcombine -S | FileCheck %s
6
7declare i64 @strnlen(ptr, i64)
8
9@ax = external global [0 x i8]
10@s5 = constant [6 x i8] c"12345\00"
11@s5_3 = constant [9 x i8] c"12345\00xyz"
12
13
14; Verify that the strnlen pointer argument is not annotated nonnull when
15; nothing is known about the bound.
16
17define i64 @no_access_strnlen_p_n(ptr %ptr, i64 %n) {
18; CHECK-LABEL: @no_access_strnlen_p_n(
19; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr [[PTR:%.*]], i64 [[N:%.*]])
20; CHECK-NEXT:    ret i64 [[LEN]]
21;
22  %len = call i64 @strnlen(ptr %ptr, i64 %n)
23  ret i64 %len
24}
25
26
27; Verify that the strnlen pointer argument is annotated dereferenceable(1)
28; (and not more) when the constant bound is greater than 1.
29
30define i64 @access_strnlen_p_2(ptr %ptr) {
31; CHECK-LABEL: @access_strnlen_p_2(
32; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR:%.*]], i64 2)
33; CHECK-NEXT:    ret i64 [[LEN]]
34;
35  %len = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) %ptr, i64 2)
36  ret i64 %len
37}
38
39
40; Verify that the strnlen pointer argument is annotated nonnull etc.,
41; when the bound is known to be nonzero.
42
43define i64 @access_strnlen_p_nz(ptr %ptr, i64 %n) {
44; CHECK-LABEL: @access_strnlen_p_nz(
45; CHECK-NEXT:    [[NNZ:%.*]] = or i64 [[N:%.*]], 1
46; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR:%.*]], i64 [[NNZ]])
47; CHECK-NEXT:    ret i64 [[LEN]]
48;
49  %nnz = or i64 %n, 1
50  %len = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) %ptr, i64 %nnz)
51  ret i64 %len
52}
53
54
55; Fold strnlen(ax, 0) to 0.
56
57define i64 @fold_strnlen_ax_0() {
58; CHECK-LABEL: @fold_strnlen_ax_0(
59; CHECK-NEXT:    ret i64 0
60;
61  %len = call i64 @strnlen(ptr @ax, i64 0)
62  ret i64 %len
63}
64
65
66; Fold strnlen(ax, 1) to *ax ? 1 : 0.
67
68define i64 @fold_strnlen_ax_1() {
69; CHECK-LABEL: @fold_strnlen_ax_1(
70; CHECK-NEXT:    [[STRNLEN_CHAR0:%.*]] = load i8, ptr @ax, align 1
71; CHECK-NEXT:    [[STRNLEN_CHAR0CMP:%.*]] = icmp ne i8 [[STRNLEN_CHAR0]], 0
72; CHECK-NEXT:    [[LEN:%.*]] = zext i1 [[STRNLEN_CHAR0CMP]] to i64
73; CHECK-NEXT:    ret i64 [[LEN]]
74;
75  %len = call i64 @strnlen(ptr @ax, i64 1)
76  ret i64 %len
77}
78
79
80; Fold strnlen(s5, 0) to 0.
81
82define i64 @fold_strnlen_s5_0() {
83; CHECK-LABEL: @fold_strnlen_s5_0(
84; CHECK-NEXT:    ret i64 0
85;
86  %len = call i64 @strnlen(ptr @s5, i64 0)
87  ret i64 %len
88}
89
90
91; Fold strnlen(s5, 4) to 4.
92
93define i64 @fold_strnlen_s5_4() {
94; CHECK-LABEL: @fold_strnlen_s5_4(
95; CHECK-NEXT:    ret i64 4
96;
97  %len = call i64 @strnlen(ptr @s5, i64 4)
98  ret i64 %len
99}
100
101
102; Fold strnlen(s5, 5) to 5.
103
104define i64 @fold_strnlen_s5_5() {
105; CHECK-LABEL: @fold_strnlen_s5_5(
106; CHECK-NEXT:    ret i64 5
107;
108  %len = call i64 @strnlen(ptr @s5, i64 5)
109  ret i64 %len
110}
111
112
113; Fold strnlen(s5, (size_t)-1) to 5.
114
115define i64 @fold_strnlen_s5_m1() {
116; CHECK-LABEL: @fold_strnlen_s5_m1(
117; CHECK-NEXT:    ret i64 5
118;
119  %len = call i64 @strnlen(ptr @s5, i64 -1)
120  ret i64 %len
121}
122
123
124; Fold strnlen(s5_3 + 4, 5) to 1.
125
126define i64 @fold_strnlen_s5_3_p4_5() {
127; CHECK-LABEL: @fold_strnlen_s5_3_p4_5(
128; CHECK-NEXT:    ret i64 1
129;
130  %ptr = getelementptr [9 x i8], ptr @s5_3, i32 0, i32 4
131  %len = call i64 @strnlen(ptr %ptr, i64 5)
132  ret i64 %len
133}
134
135
136; Fold strnlen(s5_3 + 5, 5) to 0.
137
138define i64 @fold_strnlen_s5_3_p5_5() {
139; CHECK-LABEL: @fold_strnlen_s5_3_p5_5(
140; CHECK-NEXT:    ret i64 0
141;
142  %ptr = getelementptr [9 x i8], ptr @s5_3, i32 0, i32 5
143  %len = call i64 @strnlen(ptr %ptr, i64 5)
144  ret i64 %len
145}
146
147
148; Fold strnlen(s5_3 + 6, 3) to 3.
149
150define i64 @fold_strnlen_s5_3_p6_3() {
151; CHECK-LABEL: @fold_strnlen_s5_3_p6_3(
152; CHECK-NEXT:    ret i64 3
153;
154  %ptr = getelementptr [9 x i8], ptr @s5_3, i32 0, i32 6
155  %len = call i64 @strnlen(ptr %ptr, i64 3)
156  ret i64 %len
157}
158
159
160; Fold even the invalid strnlen(s5_3 + 6, 4) call where the bound exceeds
161; the number of characters in the array.  This is arguably safer than
162; making the library call (although the low bound makes it unlikely that
163; the call would misbehave).
164
165define i64 @call_strnlen_s5_3_p6_4() {
166; CHECK-LABEL: @call_strnlen_s5_3_p6_4(
167; CHECK-NEXT:    ret i64 3
168;
169  %ptr = getelementptr [9 x i8], ptr @s5_3, i32 0, i32 6
170  %len = call i64 @strnlen(ptr %ptr, i64 4)
171  ret i64 %len
172}
173