xref: /llvm-project/llvm/test/Transforms/InstCombine/strnlen-3.ll (revision 2caaec65c04ea7d0e9568b7895b7a46d6100cb75)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Verify that strnlen calls with conditional expressions involving constant
3; string arguments with nonconstant offsets and constant bounds or constant
4; offsets and nonconstant bounds are folded correctly.
5;
6; RUN: opt < %s -passes=instcombine -S | FileCheck %s
7
8declare i64 @strnlen(ptr, i64)
9
10@sx = external global [0 x i8]
11@a3 = constant [3 x i8] c"123"
12@s3 = constant [4 x i8] c"123\00"
13@s5 = constant [6 x i8] c"12345\00"
14@s5_3 = constant [10 x i8] c"12345\00abc\00"
15
16
17; Fold strnlen(sx + i, 0) to 0.
18
19define i64 @fold_strnlen_sx_pi_0(i64 %i) {
20; CHECK-LABEL: @fold_strnlen_sx_pi_0(
21; CHECK-NEXT:    ret i64 0
22;
23
24  %ptr = getelementptr [0 x i8], ptr @sx, i64 0, i64 %i
25  %len = call i64 @strnlen(ptr %ptr, i64 0)
26  ret i64 %len
27}
28
29
30; Do not fold strnlen(sx + i, n).
31
32define i64 @call_strnlen_sx_pi_n(i64 %i, i64 %n) {
33; CHECK-LABEL: @call_strnlen_sx_pi_n(
34; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [0 x i8], ptr @sx, i64 0, i64 [[I:%.*]]
35; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr nonnull [[PTR]], i64 [[N:%.*]])
36; CHECK-NEXT:    ret i64 [[LEN]]
37;
38
39  %ptr = getelementptr inbounds [0 x i8], ptr @sx, i64 0, i64 %i
40  %len = call i64 @strnlen(ptr %ptr, i64 %n)
41  ret i64 %len
42}
43
44
45; Fold strnlen(a3 + i, 2) to min(3 - i, 2).
46
47define i64 @call_strnlen_a3_pi_2(i64 %i) {
48; CHECK-LABEL: @call_strnlen_a3_pi_2(
49; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [3 x i8], ptr @a3, i64 0, i64 [[I:%.*]]
50; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR]], i64 2)
51; CHECK-NEXT:    ret i64 [[LEN]]
52;
53
54  %ptr = getelementptr inbounds [3 x i8], ptr @a3, i64 0, i64 %i
55  %len = call i64 @strnlen(ptr %ptr, i64 2)
56  ret i64 %len
57}
58
59
60; Fold strnlen(a3 + i, 3) to min(3 - i, 3).
61
62define i64 @call_strnlen_a3_pi_3(i64 %i) {
63; CHECK-LABEL: @call_strnlen_a3_pi_3(
64; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [3 x i8], ptr @a3, i64 0, i64 [[I:%.*]]
65; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR]], i64 3)
66; CHECK-NEXT:    ret i64 [[LEN]]
67;
68
69  %ptr = getelementptr inbounds [3 x i8], ptr @a3, i64 0, i64 %i
70  %len = call i64 @strnlen(ptr %ptr, i64 3)
71  ret i64 %len
72}
73
74
75; Fold strnlen(s3 + i, 0) to 0.
76
77define i64 @fold_strnlen_s3_pi_0(i64 %i) {
78; CHECK-LABEL: @fold_strnlen_s3_pi_0(
79; CHECK-NEXT:    ret i64 0
80;
81  %ptr = getelementptr inbounds [4 x i8], ptr @s3, i64 0, i64 %i
82  %len = call i64 @strnlen(ptr %ptr, i64 0)
83  ret i64 %len
84}
85
86
87; Fold strnlen(s5 + i, 0) to 0.
88
89define i64 @call_strnlen_s5_pi_0(i64 zeroext %i) {
90; CHECK-LABEL: @call_strnlen_s5_pi_0(
91; CHECK-NEXT:    ret i64 0
92;
93  %len = call i64 @strnlen(ptr @s5, i64 0)
94  ret i64 %len
95}
96
97
98; Fold strnlen(s5_3 + i, 0) to 0.
99
100define i64 @fold_strnlen_s5_3_pi_0(i64 zeroext %i) {
101; CHECK-LABEL: @fold_strnlen_s5_3_pi_0(
102; CHECK-NEXT:    ret i64 0
103;
104  %ptr = getelementptr [10 x i8], ptr @s5_3, i32 0, i64 %i
105  %len = call i64 @strnlen(ptr %ptr, i64 0)
106  ret i64 %len
107}
108
109
110; Do not fold strnlen(s5_3 + i, n).
111
112define i64 @call_strnlen_s5_3_pi_n(i64 zeroext %i, i64 %n) {
113; CHECK-LABEL: @call_strnlen_s5_3_pi_n(
114; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [10 x i8], ptr @s5_3, i64 0, i64 [[I:%.*]]
115; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr nonnull [[PTR]], i64 [[N:%.*]])
116; CHECK-NEXT:    ret i64 [[LEN]]
117;
118  %ptr = getelementptr inbounds [10 x i8], ptr @s5_3, i32 0, i64 %i
119  %len = call i64 @strnlen(ptr %ptr, i64 %n)
120  ret i64 %len
121}
122
123
124; Fold strnlen(a3, n) to min(sizeof(a3), n)
125
126define i64 @fold_strnlen_a3_n(i64 %n) {
127; CHECK-LABEL: @fold_strnlen_a3_n(
128; CHECK-NEXT:    [[LEN:%.*]] = call i64 @llvm.umin.i64(i64 [[N:%.*]], i64 3)
129; CHECK-NEXT:    ret i64 [[LEN]]
130;
131
132  %len = call i64 @strnlen(ptr @a3, i64 %n)
133  ret i64 %len
134}
135
136
137; Fold strnlen(s3, n) to min(strlen(s3), n)
138
139define i64 @fold_strnlen_s3_n(i64 %n) {
140; CHECK-LABEL: @fold_strnlen_s3_n(
141; CHECK-NEXT:    [[LEN:%.*]] = call i64 @llvm.umin.i64(i64 [[N:%.*]], i64 3)
142; CHECK-NEXT:    ret i64 [[LEN]]
143;
144
145  %len = call i64 @strnlen(ptr @s3, i64 %n)
146  ret i64 %len
147}
148
149
150; Fold strnlen(a3 + i, 2) to min(sizeof(a3) - i, 2)
151
152define i64 @fold_strnlen_a3_pi_2(i64 %i) {
153; CHECK-LABEL: @fold_strnlen_a3_pi_2(
154; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [3 x i8], ptr @a3, i64 0, i64 [[I:%.*]]
155; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR]], i64 2)
156; CHECK-NEXT:    ret i64 [[LEN]]
157;
158
159  %ptr = getelementptr inbounds [3 x i8], ptr @a3, i64 0, i64 %i
160  %len = call i64 @strnlen(ptr %ptr, i64 2)
161  ret i64 %len
162}
163
164
165; Fold strnlen(s3 + i, 2) to min(strlen(s3) - i, 2)
166
167define i64 @fold_strnlen_s3_pi_2(i64 %i) {
168; CHECK-LABEL: @fold_strnlen_s3_pi_2(
169; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [4 x i8], ptr @s3, i64 0, i64 [[I:%.*]]
170; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR]], i64 2)
171; CHECK-NEXT:    ret i64 [[LEN]]
172;
173
174  %ptr = getelementptr inbounds [4 x i8], ptr @s3, i64 0, i64 %i
175  %len = call i64 @strnlen(ptr %ptr, i64 2)
176  ret i64 %len
177}
178
179
180; Fold strnlen(s3 + i, 3) to min(strlen(s3) - i, 3)
181
182define i64 @fold_strnlen_s3_pi_3(i64 %i) {
183; CHECK-LABEL: @fold_strnlen_s3_pi_3(
184; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [4 x i8], ptr @s3, i64 0, i64 [[I:%.*]]
185; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR]], i64 3)
186; CHECK-NEXT:    ret i64 [[LEN]]
187;
188
189  %ptr = getelementptr inbounds [4 x i8], ptr @s3, i64 0, i64 %i
190  %len = call i64 @strnlen(ptr %ptr, i64 3)
191  ret i64 %len
192}
193
194
195; Fold strnlen(s3 + i, n) to min(strlen(s3) - i, n)
196
197define i64 @fold_strnlen_s3_pi_n(i64 %i, i64 %n) {
198; CHECK-LABEL: @fold_strnlen_s3_pi_n(
199; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [4 x i8], ptr @s3, i64 0, i64 [[I:%.*]]
200; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr nonnull [[PTR]], i64 [[N:%.*]])
201; CHECK-NEXT:    ret i64 [[LEN]]
202;
203
204  %ptr = getelementptr inbounds [4 x i8], ptr @s3, i64 0, i64 %i
205  %len = call i64 @strnlen(ptr %ptr, i64 %n)
206  ret i64 %len
207}
208
209
210; Do not fold strnlen(s5_3 + i, 2).  The result is in [0, 2] but there's
211; no simple way to derive its lower bound from the offset.
212
213define i64 @call_strnlen_s5_3_pi_2(i64 %i) {
214; CHECK-LABEL: @call_strnlen_s5_3_pi_2(
215; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [10 x i8], ptr @s5_3, i64 0, i64 [[I:%.*]]
216; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) [[PTR]], i64 2)
217; CHECK-NEXT:    ret i64 [[LEN]]
218;
219
220  %ptr = getelementptr inbounds [10 x i8], ptr @s5_3, i64 0, i64 %i
221  %len = call i64 @strnlen(ptr %ptr, i64 2)
222  ret i64 %len
223}
224