1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3; 4; Exercise folding of memcmp calls with constant arrays and nonconstant 5; sizes. 6 7declare i32 @memcmp(ptr, ptr, i64) 8 9@ax = external constant [8 x i8] 10@a01230123 = constant [8 x i8] c"01230123" 11@b01230123 = constant [8 x i8] c"01230123" 12@c01230129 = constant [8 x i8] c"01230129" 13@d9123012 = constant [7 x i8] c"9123012" 14 15 16; Exercise memcmp(A, B, N) folding of arrays with the same bytes. 17 18define void @fold_memcmp_a_b_n(ptr %pcmp, i64 %n) { 19; CHECK-LABEL: @fold_memcmp_a_b_n( 20; CHECK-NEXT: store i32 0, ptr [[PCMP:%.*]], align 4 21; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[N:%.*]], 0 22; CHECK-NEXT: [[C0_1:%.*]] = sext i1 [[TMP1]] to i32 23; CHECK-NEXT: [[S0_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4 24; CHECK-NEXT: store i32 [[C0_1]], ptr [[S0_1]], align 4 25; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[N]], 0 26; CHECK-NEXT: [[C0_2:%.*]] = sext i1 [[TMP2]] to i32 27; CHECK-NEXT: [[S0_2:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8 28; CHECK-NEXT: store i32 [[C0_2]], ptr [[S0_2]], align 4 29; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[N]], 0 30; CHECK-NEXT: [[C0_3:%.*]] = sext i1 [[TMP3]] to i32 31; CHECK-NEXT: [[S0_3:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12 32; CHECK-NEXT: store i32 [[C0_3]], ptr [[S0_3]], align 4 33; CHECK-NEXT: [[S0_4:%.*]] = getelementptr i8, ptr [[PCMP]], i64 16 34; CHECK-NEXT: store i32 0, ptr [[S0_4]], align 4 35; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[N]], 0 36; CHECK-NEXT: [[C0_5:%.*]] = sext i1 [[TMP4]] to i32 37; CHECK-NEXT: [[S0_5:%.*]] = getelementptr i8, ptr [[PCMP]], i64 20 38; CHECK-NEXT: store i32 [[C0_5]], ptr [[S0_5]], align 4 39; CHECK-NEXT: ret void 40; 41 42 43 %q1 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 1 44 %q2 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 2 45 %q3 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 3 46 %q4 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 4 47 %q5 = getelementptr [8 x i8], ptr @b01230123, i64 0, i64 5 48 49 ; Fold memcmp(a, b, n) to 0. 50 %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @b01230123, i64 %n) 51 store i32 %c0_0, ptr %pcmp 52 53 ; Fold memcmp(a, b + 1, n) to N != 0 ? -1 : 0. 54 %c0_1 = call i32 @memcmp(ptr @a01230123, ptr %q1, i64 %n) 55 %s0_1 = getelementptr i32, ptr %pcmp, i64 1 56 store i32 %c0_1, ptr %s0_1 57 58 ; Fold memcmp(a, b + 2, n) to N != 0 ? -1 : 0. 59 %c0_2 = call i32 @memcmp(ptr @a01230123, ptr %q2, i64 %n) 60 %s0_2 = getelementptr i32, ptr %pcmp, i64 2 61 store i32 %c0_2, ptr %s0_2 62 63 ; Fold memcmp(a, b + 3, n) to N != 0 ? -1 : 0. 64 %c0_3 = call i32 @memcmp(ptr @a01230123, ptr %q3, i64 %n) 65 %s0_3 = getelementptr i32, ptr %pcmp, i64 3 66 store i32 %c0_3, ptr %s0_3 67 68 ; Fold memcmp(a, b + 4, n) to 0. 69 %c0_4 = call i32 @memcmp(ptr @a01230123, ptr %q4, i64 %n) 70 %s0_4 = getelementptr i32, ptr %pcmp, i64 4 71 store i32 %c0_4, ptr %s0_4 72 73 ; Fold memcmp(a, b + 5, n) to N != 0 ? -1 : 0. 74 %c0_5 = call i32 @memcmp(ptr @a01230123, ptr %q5, i64 %n) 75 %s0_5 = getelementptr i32, ptr %pcmp, i64 5 76 store i32 %c0_5, ptr %s0_5 77 78 ret void 79} 80 81; Vefify that a memcmp() call involving a constant array with unknown 82; contents is not folded. 83 84define void @call_memcmp_a_ax_n(ptr %pcmp, i64 %n) { 85; CHECK-LABEL: @call_memcmp_a_ax_n( 86; CHECK-NEXT: [[C0_0:%.*]] = call i32 @memcmp(ptr nonnull @a01230123, ptr nonnull @ax, i64 [[N:%.*]]) 87; CHECK-NEXT: store i32 [[C0_0]], ptr [[PCMP:%.*]], align 4 88; CHECK-NEXT: ret void 89; 90 91 92 ; Do not fold memcmp(a, ax, n). 93 %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @ax, i64 %n) 94 store i32 %c0_0, ptr %pcmp 95 96 ret void 97} 98 99 100; Exercise memcmp(A, C, N) folding of arrays with the same leading bytes 101; but a difference in the trailing byte. 102 103define void @fold_memcmp_a_c_n(ptr %pcmp, i64 %n) { 104; CHECK-LABEL: @fold_memcmp_a_c_n( 105; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i64 [[N:%.*]], 7 106; CHECK-NEXT: [[C0_0:%.*]] = sext i1 [[TMP1]] to i32 107; CHECK-NEXT: store i32 [[C0_0]], ptr [[PCMP:%.*]], align 4 108; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[N]], 0 109; CHECK-NEXT: [[C0_1:%.*]] = sext i1 [[TMP2]] to i32 110; CHECK-NEXT: [[S0_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4 111; CHECK-NEXT: store i32 [[C0_1]], ptr [[S0_1]], align 4 112; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[N]], 0 113; CHECK-NEXT: [[C0_2:%.*]] = sext i1 [[TMP3]] to i32 114; CHECK-NEXT: [[S0_2:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8 115; CHECK-NEXT: store i32 [[C0_2]], ptr [[S0_2]], align 4 116; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[N]], 0 117; CHECK-NEXT: [[C0_3:%.*]] = sext i1 [[TMP4]] to i32 118; CHECK-NEXT: [[S0_3:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12 119; CHECK-NEXT: store i32 [[C0_3]], ptr [[S0_3]], align 4 120; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[N]], 3 121; CHECK-NEXT: [[C0_4:%.*]] = sext i1 [[TMP5]] to i32 122; CHECK-NEXT: [[S0_4:%.*]] = getelementptr i8, ptr [[PCMP]], i64 16 123; CHECK-NEXT: store i32 [[C0_4]], ptr [[S0_4]], align 4 124; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i64 [[N]], 3 125; CHECK-NEXT: [[C0_5:%.*]] = sext i1 [[TMP6]] to i32 126; CHECK-NEXT: [[S0_5:%.*]] = getelementptr i8, ptr [[PCMP]], i64 20 127; CHECK-NEXT: store i32 [[C0_5]], ptr [[S0_5]], align 4 128; CHECK-NEXT: ret void 129; 130 131 132 %q1 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 1 133 %q2 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 2 134 %q3 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 3 135 %q4 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 4 136 %q5 = getelementptr [8 x i8], ptr @c01230129, i64 0, i64 5 137 138 ; Fold memcmp(a, c, n) to N > 7 ? -1 : 0. 139 %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @c01230129, i64 %n) 140 store i32 %c0_0, ptr %pcmp 141 142 ; Fold memcmp(a, c + 1, n) to N != 0 ? -1 : 0. 143 %c0_1 = call i32 @memcmp(ptr @a01230123, ptr %q1, i64 %n) 144 %s0_1 = getelementptr i32, ptr %pcmp, i64 1 145 store i32 %c0_1, ptr %s0_1 146 147 ; Fold memcmp(a, c + 2, n) to N != 0 ? -1 : 0. 148 %c0_2 = call i32 @memcmp(ptr @a01230123, ptr %q2, i64 %n) 149 %s0_2 = getelementptr i32, ptr %pcmp, i64 2 150 store i32 %c0_2, ptr %s0_2 151 152 ; Fold memcmp(a, c + 3, n) to N != 0 ? -1 : 0. 153 %c0_3 = call i32 @memcmp(ptr @a01230123, ptr %q3, i64 %n) 154 %s0_3 = getelementptr i32, ptr %pcmp, i64 3 155 store i32 %c0_3, ptr %s0_3 156 157 ; Fold memcmp(a, c + 4, n) to N > 3 ? -1 : 0. 158 %c0_4 = call i32 @memcmp(ptr @a01230123, ptr %q4, i64 %n) 159 %s0_4 = getelementptr i32, ptr %pcmp, i64 4 160 store i32 %c0_4, ptr %s0_4 161 162 ; Fold memcmp(a, c + 5, n) to N != 0 ? -1 : 0. 163 %c0_5 = call i32 @memcmp(ptr @a01230123, ptr %q4, i64 %n) 164 %s0_5 = getelementptr i32, ptr %pcmp, i64 5 165 store i32 %c0_5, ptr %s0_5 166 167 ret void 168} 169 170 171; Exercise memcmp(A, D, N) folding of arrays of different sizes and 172; a difference in the leading byte. 173 174define void @fold_memcmp_a_d_n(ptr %pcmp, i64 %n) { 175; CHECK-LABEL: @fold_memcmp_a_d_n( 176; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[N:%.*]], 0 177; CHECK-NEXT: [[C0_0:%.*]] = sext i1 [[TMP1]] to i32 178; CHECK-NEXT: store i32 [[C0_0]], ptr [[PCMP:%.*]], align 4 179; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[N]], 0 180; CHECK-NEXT: [[C0_1:%.*]] = sext i1 [[TMP2]] to i32 181; CHECK-NEXT: [[S0_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 4 182; CHECK-NEXT: store i32 [[C0_1]], ptr [[S0_1]], align 4 183; CHECK-NEXT: [[S1_1:%.*]] = getelementptr i8, ptr [[PCMP]], i64 8 184; CHECK-NEXT: store i32 0, ptr [[S1_1]], align 4 185; CHECK-NEXT: [[S6_6:%.*]] = getelementptr i8, ptr [[PCMP]], i64 12 186; CHECK-NEXT: store i32 0, ptr [[S6_6]], align 4 187; CHECK-NEXT: ret void 188; 189 190 %p1 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 1 191 %p6 = getelementptr [8 x i8], ptr @a01230123, i64 0, i64 6 192 193 %q1 = getelementptr [7 x i8], ptr @d9123012, i64 0, i64 1 194 %q6 = getelementptr [7 x i8], ptr @d9123012, i64 0, i64 6 195 196 ; Fold memcmp(a, d, n) to N != 0 ? -1 : 0. 197 %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @d9123012, i64 %n) 198 store i32 %c0_0, ptr %pcmp 199 200 ; Fold memcmp(a, d + 1, n) to N != 0 -1 : 0. 201 %c0_1 = call i32 @memcmp(ptr @a01230123, ptr %q1, i64 %n) 202 %s0_1 = getelementptr i32, ptr %pcmp, i64 1 203 store i32 %c0_1, ptr %s0_1 204 205 ; Fold memcmp(a + 1, d + 1, n) to 0. 206 %c1_1 = call i32 @memcmp(ptr %p1, ptr %q1, i64 %n) 207 %s1_1 = getelementptr i32, ptr %pcmp, i64 2 208 store i32 %c1_1, ptr %s1_1 209 210 ; Fold memcmp(a + 6, d + 6, n) to 0. 211 %c6_6 = call i32 @memcmp(ptr %p6, ptr %q6, i64 %n) 212 %s6_6 = getelementptr i32, ptr %pcmp, i64 3 213 store i32 %c6_6, ptr %s6_6 214 215 ret void 216} 217 218 219; Exercise memcmp(A, D, N) folding of arrays with the same bytes and 220; a nonzero size. 221 222define void @fold_memcmp_a_d_nz(ptr %pcmp, i64 %n) { 223; CHECK-LABEL: @fold_memcmp_a_d_nz( 224; CHECK-NEXT: store i32 -1, ptr [[PCMP:%.*]], align 4 225; CHECK-NEXT: ret void 226; 227 228 %nz = or i64 %n, 1 229 230 %c0_0 = call i32 @memcmp(ptr @a01230123, ptr @d9123012, i64 %nz) 231 store i32 %c0_0, ptr %pcmp 232 233 ret void 234} 235