xref: /llvm-project/llvm/test/Transforms/InstCombine/strnlen-5.ll (revision dc2b66b8d6032dbc5e5dd7ee86e4fa7dd9cf0b9b)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Verify that equality tests of strnlen calls against zero are folded
3; 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@a5 = external global [5 x i8]
11@s5 = constant [6 x i8] c"12345\00"
12
13
14; Fold strnlen(ax, 0) == 0 to true.
15
16define i1 @fold_strnlen_ax_0_eqz() {
17; CHECK-LABEL: @fold_strnlen_ax_0_eqz(
18; CHECK-NEXT:    ret i1 true
19;
20
21  %len = tail call i64 @strnlen(ptr @ax, i64 0)
22  %eqz = icmp eq i64 %len, 0
23  ret i1 %eqz
24}
25
26
27; Fold strnlen(ax, 0) > 0 to false.
28
29define i1 @fold_strnlen_ax_0_gtz() {
30; CHECK-LABEL: @fold_strnlen_ax_0_gtz(
31; CHECK-NEXT:    ret i1 false
32;
33
34  %len = tail call i64 @strnlen(ptr @ax, i64 0)
35  %gtz = icmp ugt i64 %len, 0
36  ret i1 %gtz
37}
38
39
40; Fold strnlen(ax, 1) == 0 to *ax == 0.
41
42define i1 @fold_strnlen_ax_1_eqz() {
43; CHECK-LABEL: @fold_strnlen_ax_1_eqz(
44; CHECK-NEXT:    [[CHAR0:%.*]] = load i8, ptr @ax, align 1
45; CHECK-NEXT:    [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0
46; CHECK-NEXT:    ret i1 [[EQZ]]
47;
48
49  %len = tail call i64 @strnlen(ptr @ax, i64 1)
50  %eqz = icmp eq i64 %len, 0
51  ret i1 %eqz
52}
53
54
55; Likewise, fold strnlen(ax, 1) < 1 to *ax == 0.
56
57define i1 @fold_strnlen_ax_1_lt1() {
58; CHECK-LABEL: @fold_strnlen_ax_1_lt1(
59; CHECK-NEXT:    [[STRNLEN_CHAR0:%.*]] = load i8, ptr @ax, align 1
60; CHECK-NEXT:    [[STRNLEN_CHAR0CMP_NOT:%.*]] = icmp eq i8 [[STRNLEN_CHAR0]], 0
61; CHECK-NEXT:    ret i1 [[STRNLEN_CHAR0CMP_NOT]]
62;
63
64  %len = tail call i64 @strnlen(ptr @ax, i64 1)
65  %nez = icmp ult i64 %len, 1
66  ret i1 %nez
67}
68
69
70; Fold strnlen(ax, 1) != 0 to *ax != 0.
71
72define i1 @fold_strnlen_ax_1_neqz() {
73; CHECK-LABEL: @fold_strnlen_ax_1_neqz(
74; CHECK-NEXT:    [[CHAR0:%.*]] = load i8, ptr @ax, align 1
75; CHECK-NEXT:    [[NEZ:%.*]] = icmp ne i8 [[CHAR0]], 0
76; CHECK-NEXT:    ret i1 [[NEZ]]
77;
78
79  %len = tail call i64 @strnlen(ptr @ax, i64 1)
80  %nez = icmp ne i64 %len, 0
81  ret i1 %nez
82}
83
84
85; Likewise, fold strnlen(ax, 1) > 0 to *ax != 0.
86
87define i1 @fold_strnlen_ax_1_gtz() {
88; CHECK-LABEL: @fold_strnlen_ax_1_gtz(
89; CHECK-NEXT:    [[STRNLEN_CHAR0:%.*]] = load i8, ptr @ax, align 1
90; CHECK-NEXT:    [[STRNLEN_CHAR0CMP:%.*]] = icmp ne i8 [[STRNLEN_CHAR0]], 0
91; CHECK-NEXT:    ret i1 [[STRNLEN_CHAR0CMP]]
92;
93
94  %len = tail call i64 @strnlen(ptr @ax, i64 1)
95  %nez = icmp ugt i64 %len, 0
96  ret i1 %nez
97}
98
99
100; Fold strnlen(ax, 9) == 0 to *ax == 0.
101
102define i1 @fold_strnlen_ax_9_eqz() {
103; CHECK-LABEL: @fold_strnlen_ax_9_eqz(
104; CHECK-NEXT:    [[CHAR0:%.*]] = load i8, ptr @ax, align 1
105; CHECK-NEXT:    [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0
106; CHECK-NEXT:    ret i1 [[EQZ]]
107;
108
109  %len = tail call i64 @strnlen(ptr @ax, i64 9)
110  %eqz = icmp eq i64 %len, 0
111  ret i1 %eqz
112}
113
114
115; Do not fold strnlen(ax, n) == 0 for n that might be zero.
116
117define i1 @call_strnlen_ax_n_eqz(i64 %n) {
118; CHECK-LABEL: @call_strnlen_ax_n_eqz(
119; CHECK-NEXT:    [[LEN:%.*]] = tail call i64 @strnlen(ptr nonnull @ax, i64 [[N:%.*]])
120; CHECK-NEXT:    [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0
121; CHECK-NEXT:    ret i1 [[EQZ]]
122;
123
124  %len = tail call i64 @strnlen(ptr @ax, i64 %n)
125  %eqz = icmp eq i64 %len, 0
126  ret i1 %eqz
127}
128
129
130; Fold strnlen(ax, n) == 0 to *ax == 0 for %0 that's not zero.
131
132define i1 @fold_strnlen_ax_nz_eqz(i64 %n) {
133; CHECK-LABEL: @fold_strnlen_ax_nz_eqz(
134; CHECK-NEXT:    [[CHAR0:%.*]] = load i8, ptr @ax, align 1
135; CHECK-NEXT:    [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0
136; CHECK-NEXT:    ret i1 [[EQZ]]
137;
138
139  %max = or i64 %n, 1
140  %len = tail call i64 @strnlen(ptr @ax, i64 %max)
141  %eqz = icmp eq i64 %len, 0
142  ret i1 %eqz
143}
144
145
146; Fold strnlen(ax, n) > 0 to *ax != 0 for n that's not zero.
147
148define i1 @fold_strnlen_ax_nz_gtz(i64 %n) {
149; CHECK-LABEL: @fold_strnlen_ax_nz_gtz(
150; CHECK-NEXT:    [[CHAR0:%.*]] = load i8, ptr @ax, align 1
151; CHECK-NEXT:    [[GTZ:%.*]] = icmp ne i8 [[CHAR0]], 0
152; CHECK-NEXT:    ret i1 [[GTZ]]
153;
154
155  %max = or i64 %n, 1
156  %len = tail call i64 @strnlen(ptr @ax, i64 %max)
157  %gtz = icmp ugt i64 %len, 0
158  ret i1 %gtz
159}
160
161
162; Fold strnlen(a5 + i, n) == 0 to a5[i] == 0 for a nonconstant a5
163; and a nonzero n.
164
165define i1 @fold_strnlen_a5_pi_nz_eqz(i64 %i, i64 %n) {
166; CHECK-LABEL: @fold_strnlen_a5_pi_nz_eqz(
167; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [5 x i8], ptr @a5, i64 0, i64 [[I:%.*]]
168; CHECK-NEXT:    [[CHAR0:%.*]] = load i8, ptr [[PTR]], align 1
169; CHECK-NEXT:    [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0
170; CHECK-NEXT:    ret i1 [[EQZ]]
171;
172
173  %nz = or i64 %n, 1
174  %ptr = getelementptr inbounds [5 x i8], ptr @a5, i64 0, i64 %i
175  %len = call i64 @strnlen(ptr %ptr, i64 %nz)
176  %eqz = icmp eq i64 %len, 0
177  ret i1 %eqz
178}
179
180
181; Fold strnlen(s5 + i, n) == 0 for a constant s5 and nonzero n.
182; This is first folded to s5[i] == 0 like the above and then finally
183; to %0 == 5.
184
185define i1 @fold_strnlen_s5_pi_nz_eqz(i64 %i, i64 %n) {
186; CHECK-LABEL: @fold_strnlen_s5_pi_nz_eqz(
187; CHECK-NEXT:    [[EQZ:%.*]] = icmp eq i64 [[I:%.*]], 5
188; CHECK-NEXT:    ret i1 [[EQZ]]
189;
190
191  %nz = or i64 %n, 1
192  %ptr = getelementptr inbounds [6 x i8], ptr @s5, i64 0, i64 %i
193  %len = call i64 @strnlen(ptr %ptr, i64 %nz)
194  %eqz = icmp eq i64 %len, 0
195  ret i1 %eqz
196}
197
198
199; Do not fold strnlen(s5 + i, n) for a constant s5 when n might be zero.
200
201define i1 @call_strnlen_s5_pi_n_eqz(i64 %i, i64 %n) {
202; CHECK-LABEL: @call_strnlen_s5_pi_n_eqz(
203; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds [6 x i8], ptr @s5, i64 0, i64 [[I:%.*]]
204; CHECK-NEXT:    [[LEN:%.*]] = call i64 @strnlen(ptr nonnull [[PTR]], i64 [[N:%.*]])
205; CHECK-NEXT:    [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0
206; CHECK-NEXT:    ret i1 [[EQZ]]
207;
208
209  %ptr = getelementptr inbounds [6 x i8], ptr @s5, i64 0, i64 %i
210  %len = call i64 @strnlen(ptr %ptr, i64 %n)
211  %eqz = icmp eq i64 %len, 0
212  ret i1 %eqz
213}
214