1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; Verify that equality tests of strnlen calls against zero are folded
5 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
7 declare i64 @strnlen(ptr, i64)
9 @ax = external global [0 x i8]
10 @a5 = external global [5 x i8]
11 @s5 = constant [6 x i8] c"12345\00"
14 ; Fold strnlen(ax, 0) == 0 to true.
16 define i1 @fold_strnlen_ax_0_eqz() {
17 ; CHECK-LABEL: @fold_strnlen_ax_0_eqz(
18 ; CHECK-NEXT: ret i1 true
21 %len = tail call i64 @strnlen(ptr @ax, i64 0)
22 %eqz = icmp eq i64 %len, 0
27 ; Fold strnlen(ax, 0) > 0 to false.
29 define i1 @fold_strnlen_ax_0_gtz() {
30 ; CHECK-LABEL: @fold_strnlen_ax_0_gtz(
31 ; CHECK-NEXT: ret i1 false
34 %len = tail call i64 @strnlen(ptr @ax, i64 0)
35 %gtz = icmp ugt i64 %len, 0
40 ; Fold strnlen(ax, 1) == 0 to *ax == 0.
42 define 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]]
49 %len = tail call i64 @strnlen(ptr @ax, i64 1)
50 %eqz = icmp eq i64 %len, 0
55 ; Likewise, fold strnlen(ax, 1) < 1 to *ax == 0.
57 define 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]]
64 %len = tail call i64 @strnlen(ptr @ax, i64 1)
65 %nez = icmp ult i64 %len, 1
70 ; Fold strnlen(ax, 1) != 0 to *ax != 0.
72 define 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]]
79 %len = tail call i64 @strnlen(ptr @ax, i64 1)
80 %nez = icmp ne i64 %len, 0
85 ; Likewise, fold strnlen(ax, 1) > 0 to *ax != 0.
87 define 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]]
94 %len = tail call i64 @strnlen(ptr @ax, i64 1)
95 %nez = icmp ugt i64 %len, 0
100 ; Fold strnlen(ax, 9) == 0 to *ax == 0.
102 define 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]]
109 %len = tail call i64 @strnlen(ptr @ax, i64 9)
110 %eqz = icmp eq i64 %len, 0
115 ; Do not fold strnlen(ax, n) == 0 for n that might be zero.
117 define 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]]
124 %len = tail call i64 @strnlen(ptr @ax, i64 %n)
125 %eqz = icmp eq i64 %len, 0
130 ; Fold strnlen(ax, n) == 0 to *ax == 0 for %0 that's not zero.
132 define 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]]
140 %len = tail call i64 @strnlen(ptr @ax, i64 %max)
141 %eqz = icmp eq i64 %len, 0
146 ; Fold strnlen(ax, n) > 0 to *ax != 0 for n that's not zero.
148 define 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]]
156 %len = tail call i64 @strnlen(ptr @ax, i64 %max)
157 %gtz = icmp ugt i64 %len, 0
162 ; Fold strnlen(a5 + i, n) == 0 to a5[i] == 0 for a nonconstant a5
165 define 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]]
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
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
185 define 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]]
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
199 ; Do not fold strnlen(s5 + i, n) for a constant s5 when n might be zero.
201 define 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]]
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