280 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; Verify that strlen calls with members of constant structs are folded.3;4; RUN: opt < %s -passes=instcombine -S | FileCheck %s5 6; struct A_a4 { char a[4]; };7%struct.A_a4 = type { [4 x i8] }8 9; struct A_a4_a5 { char a[4], b[5]; };10%struct.A_a4_a5 = type { [4 x i8], [5 x i8] }11 12; struct A_a4_i32_a5 { char a[4]; int32_t i; char b[5]; };13%struct.A_a4_i32_a5 = type { [4 x i8], i32, [5 x i8] }14 15@a_s3 = constant %struct.A_a4 { [4 x i8 ] c"123\00" }16@a_s3_s4 = constant %struct.A_a4_a5 { [4 x i8 ] c"123\00", [5 x i8] c"1234\00" }17@a_s3_i32_s4 = constant %struct.A_a4_i32_a5 { [4 x i8 ] c"123\00", i32 -1, [5 x i8] c"1234\00" }18 19; Structs with flexible array members.20@ax_s3 = constant { i8, [4 x i8] } { i8 3, [4 x i8] c"123\00" }21@ax_s5 = constant { i16, [6 x i8] } { i16 5, [6 x i8] c"12345\00" }22@ax_s7 = constant { i32, i32, [8 x i8] } { i32 7, i32 0, [8 x i8] c"1234567\00" }23 24@ax = external global [0 x i64]25 26 27declare i64 @strlen(ptr)28 29 30; Fold strlen(a_s3.a) to 3.31 32define i64 @fold_strlen_a_S3_to_3() {33; CHECK-LABEL: @fold_strlen_a_S3_to_3(34; CHECK-NEXT: ret i64 335;36 %len = call i64 @strlen(ptr @a_s3)37 ret i64 %len38}39 40 41; Fold strlen(&a_s3.a[1]) to 2.42 43define i64 @fold_strlen_a_S3_p1_to_2() {44; CHECK-LABEL: @fold_strlen_a_S3_p1_to_2(45; CHECK-NEXT: ret i64 246;47 %ptr = getelementptr %struct.A_a4, ptr @a_s3, i32 0, i32 0, i32 148 %len = call i64 @strlen(ptr %ptr)49 ret i64 %len50}51 52 53; Fold strlen(&a_s3.a[2]) to 1.54 55define i64 @fold_strlen_a_S3_p2_to_1() {56; CHECK-LABEL: @fold_strlen_a_S3_p2_to_1(57; CHECK-NEXT: ret i64 158;59 %ptr = getelementptr %struct.A_a4, ptr @a_s3, i32 0, i32 0, i32 260 %len = call i64 @strlen(ptr %ptr)61 ret i64 %len62}63 64 65; Fold strlen(&a_s3.a[3]) to 0.66 67define i64 @fold_strlen_a_S3_p3_to_0() {68; CHECK-LABEL: @fold_strlen_a_S3_p3_to_0(69; CHECK-NEXT: ret i64 070;71 %ptr = getelementptr %struct.A_a4, ptr @a_s3, i32 0, i32 0, i32 372 %len = call i64 @strlen(ptr %ptr)73 ret i64 %len74}75 76 77; Fold strlen(a_s3_s4.a) to 3.78 79define i64 @fold_strlen_a_S3_s4_to_3() {80; CHECK-LABEL: @fold_strlen_a_S3_s4_to_3(81; CHECK-NEXT: ret i64 382;83 %len = call i64 @strlen(ptr @a_s3_s4)84 ret i64 %len85}86 87 88; Fold strlen(&a_s3_s4.a[2]) to 1.89 90define i64 @fold_strlen_a_S3_p2_s4_to_1() {91; CHECK-LABEL: @fold_strlen_a_S3_p2_s4_to_1(92; CHECK-NEXT: ret i64 193;94 %ptr = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 0, i32 295 %len = call i64 @strlen(ptr %ptr)96 ret i64 %len97}98 99 100; Fold strlen(a_s3_s4.b) to 4.101; Exercise both variants of the GEP index.102 103define void @fold_strlen_a_s3_S4_to_4() {104; CHECK-LABEL: @fold_strlen_a_s3_S4_to_4(105; CHECK-NEXT: store i64 4, ptr @ax, align 4106; CHECK-NEXT: store i64 4, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4107; CHECK-NEXT: ret void108;109 %p1 = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 0, i32 4110 %len1 = call i64 @strlen(ptr %p1)111 store i64 %len1, ptr @ax112 113 %p2 = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 1, i32 0114 %len2 = call i64 @strlen(ptr %p2)115 %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1116 store i64 %len1, ptr %pax1117 118 ret void119}120 121 122; Fold strlen(&a_s3_s4.b[1]) to 3.123; Exercise both variants of the GEP index.124 125define void @fold_strlen_a_s3_S4_p1_to_3() {126; CHECK-LABEL: @fold_strlen_a_s3_S4_p1_to_3(127; CHECK-NEXT: store i64 3, ptr @ax, align 4128; CHECK-NEXT: store i64 3, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4129; CHECK-NEXT: ret void130;131 %p1 = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 0, i32 5132 %len1 = call i64 @strlen(ptr %p1)133 store i64 %len1, ptr @ax134 135 %p2 = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 1, i32 1136 %len2 = call i64 @strlen(ptr %p2)137 %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1138 store i64 %len1, ptr %pax1139 140 ret void141}142 143 144; Fold strlen(a_s3_i32_s4.b) to 4.145; Exercise both variants of the GEP index.146 147define void @fold_strlen_a_s3_i32_S4_to_4() {148; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_to_4(149; CHECK-NEXT: store i64 4, ptr @ax, align 4150; CHECK-NEXT: store i64 4, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4151; CHECK-NEXT: ret void152;153 %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 8154 %len1 = call i64 @strlen(ptr %p1)155 store i64 %len1, ptr @ax156 157 %p2 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 2, i32 0158 %len2 = call i64 @strlen(ptr %p2)159 %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1160 store i64 %len1, ptr %pax1161 162 ret void163}164 165 166; Fold strlen(&a_s3_i32_s4.b[1]) to 3.167; Exercise both variants of the GEP index.168 169define void @fold_strlen_a_s3_i32_S4_p1_to_3() {170; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p1_to_3(171; CHECK-NEXT: store i64 3, ptr @ax, align 4172; CHECK-NEXT: store i64 3, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4173; CHECK-NEXT: ret void174;175 %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 9176 %len1 = call i64 @strlen(ptr %p1)177 store i64 %len1, ptr @ax178 179 %p2 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 2, i32 0180 %len2 = call i64 @strlen(ptr %p2)181 %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1182 store i64 %len1, ptr %pax1183 184 ret void185}186 187 188; Fold strlen(&a_s3_i32_s4.b[2]) to 2.189; Exercise both variants of the GEP index.190 191define void @fold_strlen_a_s3_i32_S4_p2_to_2() {192; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p2_to_2(193; CHECK-NEXT: store i64 2, ptr @ax, align 4194; CHECK-NEXT: store i64 2, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4195; CHECK-NEXT: ret void196;197 %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 10198 %len1 = call i64 @strlen(ptr %p1)199 store i64 %len1, ptr @ax200 201 %p2 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 2, i32 2202 %len2 = call i64 @strlen(ptr %p2)203 %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1204 store i64 %len1, ptr %pax1205 206 ret void207}208 209 210; Fold strlen(&a_s3_i32_s4.b[3]) to 1.211; Exercise both variants of the GEP index.212 213define void @fold_strlen_a_s3_i32_S4_p3_to_1() {214; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p3_to_1(215; CHECK-NEXT: store i64 1, ptr @ax, align 4216; CHECK-NEXT: store i64 1, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4217; CHECK-NEXT: ret void218;219 %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 11220 %len1 = call i64 @strlen(ptr %p1)221 store i64 %len1, ptr @ax222 223 %p2 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 2, i32 3224 %len2 = call i64 @strlen(ptr %p2)225 %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1226 store i64 %len1, ptr %pax1227 228 ret void229}230 231 232; Fold strlen(&a_s3_i32_s4.b[4]) to 0.233; Exercise both variants of the GEP index.234 235define void @fold_strlen_a_s3_i32_S4_p4_to_0() {236; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p4_to_0(237; CHECK-NEXT: store i64 0, ptr @ax, align 4238; CHECK-NEXT: store i64 0, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4239; CHECK-NEXT: ret void240;241 %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 12242 %len1 = call i64 @strlen(ptr %p1)243 store i64 %len1, ptr @ax244 245 %p2 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 2, i32 4246 %len2 = call i64 @strlen(ptr %p2)247 %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1248 store i64 %len1, ptr %pax1249 250 ret void251}252 253 254; Fold strlen(ax_sN.a) of an constant initialized flexible array member255; to N for N in { 3, 5, 7 }.256 257define void @fold_strlen_ax_s() {258; CHECK-LABEL: @fold_strlen_ax_s(259; CHECK-NEXT: store i64 3, ptr @ax, align 4260; CHECK-NEXT: store i64 5, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4261; CHECK-NEXT: store i64 7, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 16), align 4262; CHECK-NEXT: ret void263;264 %pax_s3 = getelementptr { i8, [4 x i8] }, ptr @ax_s3, i64 0, i32 1, i64 0265 %len3 = call i64 @strlen(ptr %pax_s3)266 store i64 %len3, ptr @ax267 268 %pax_s5 = getelementptr { i16, [6 x i8] }, ptr @ax_s5, i64 0, i32 1, i64 0269 %len5 = call i64 @strlen(ptr %pax_s5)270 %pax2 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1271 store i64 %len5, ptr %pax2272 273 %pax_s7 = getelementptr { i32, i32, [8 x i8] }, ptr @ax_s7, i64 0, i32 2, i64 0274 %len7 = call i64 @strlen(ptr %pax_s7)275 %pax3 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 2276 store i64 %len7, ptr %pax3277 278 ret void279}280