311 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; Verify that calls to atoi and related conversion functions with members3; of constant structs as arguments are folded to constants as expected.4; RUN: opt < %s -passes=instcombine -S | FileCheck %s5 6declare i32 @atoi(ptr)7declare i64 @atol(ptr)8declare i64 @atoll(ptr)9 10declare i64 @strtol(ptr, ptr, i32)11declare i64 @strtoll(ptr, ptr, i32)12 13%struct.A = type { [4 x i8], [5 x i8], [7 x i8] }14 15@a = constant [2 x %struct.A] [%struct.A { [4 x i8] c"1\00\00\00", [5 x i8] c"12\00\00\00", [7 x i8] c"56789\00\00" }, %struct.A { [4 x i8] c"123\00", [5 x i8] c"1234\00", [7 x i8] c"67890\00\00" }]16 17 18; Fold atoi(a[I].M) for constant I in [0, 1] and member M in [a, b]19; to a constant.20 21define void @fold_atoi_member(ptr %pi) {22; CHECK-LABEL: @fold_atoi_member(23; CHECK-NEXT: store i32 1, ptr [[PI:%.*]], align 424; CHECK-NEXT: [[PIA0B:%.*]] = getelementptr i8, ptr [[PI]], i64 425; CHECK-NEXT: store i32 12, ptr [[PIA0B]], align 426; CHECK-NEXT: [[PIA1A:%.*]] = getelementptr i8, ptr [[PI]], i64 827; CHECK-NEXT: store i32 123, ptr [[PIA1A]], align 428; CHECK-NEXT: [[PIA1B:%.*]] = getelementptr i8, ptr [[PI]], i64 1229; CHECK-NEXT: store i32 1234, ptr [[PIA1B]], align 430; CHECK-NEXT: ret void31;32; Fold atoi(a[0].a) to 1.33 %ia0a = call i32 @atoi(ptr @a)34 store i32 %ia0a, ptr %pi35 36; Fold atoi(a[0].b) to 12.37 %pa0b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 038 %ia0b = call i32 @atoi(ptr %pa0b)39 %pia0b = getelementptr i32, ptr %pi, i32 140 store i32 %ia0b, ptr %pia0b41 42; Fold atoi(a[1].a) to 123.43 %pa1a = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 044 %ia1a = call i32 @atoi(ptr %pa1a)45 %pia1a = getelementptr i32, ptr %pi, i32 246 store i32 %ia1a, ptr %pia1a47 48; Fold atoi(a[1].b) to 1234.49 %pa1b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 050 %ia1b = call i32 @atoi(ptr %pa1b)51 %pia1b = getelementptr i32, ptr %pi, i32 352 store i32 %ia1b, ptr %pia1b53 54 ret void55}56 57 58; TODO: Fold atoi with an excessive offset. It's undefined so folding it59; to zero is valid and might prevent crashes or returning a bogus value,60; even though it prevents detecting the bug by sanitizers.61; This is not fully implemented because the out-of-bounds offset results62; in the empty string which atoi (via strtol) is required to interpret as63; a zero but for which it may set errno to EINVAL. To fold only64; the undefined calls the folder would have to differentiate between65; the empty string an out-of-bounds pointer.66 67define void @fold_atoi_offset_out_of_bounds(ptr %pi) {68; CHECK-LABEL: @fold_atoi_offset_out_of_bounds(69; CHECK-NEXT: [[IA_0_0_32:%.*]] = call i32 @atoi(ptr nonnull getelementptr inbounds nuw (i8, ptr @a, i64 32))70; CHECK-NEXT: store i32 [[IA_0_0_32]], ptr [[PI:%.*]], align 471; CHECK-NEXT: [[IA_0_0_33:%.*]] = call i32 @atoi(ptr getelementptr (i8, ptr @a, i64 33))72; CHECK-NEXT: store i32 [[IA_0_0_33]], ptr [[PI]], align 473; CHECK-NEXT: ret void74;75; TODO: Check folding.76; Fold atoi((const char*)a + sizeof a) to zero.77 %ia_0_0_32 = call i32 @atoi(ptr getelementptr inbounds ([2 x %struct.A], ptr @a, i64 1, i64 0, i32 0, i64 0))78 store i32 %ia_0_0_32, ptr %pi79 80; Likewise, fold atoi((const char*)a + sizeof a + 1) to zero.81 %pa_0_0_33 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 3382 %ia_0_0_33 = call i32 @atoi(ptr %pa_0_0_33)83 store i32 %ia_0_0_33, ptr %pi84 85 ret void86}87 88 89; Fold atol(a[I].M) for constant I in [0, 1] and member M in [a, b, c]90; to a constant.91 92define void @fold_atol_member(ptr %pi) {93; CHECK-LABEL: @fold_atol_member(94; CHECK-NEXT: store i64 1, ptr [[PI:%.*]], align 495; CHECK-NEXT: [[PIA0B:%.*]] = getelementptr i8, ptr [[PI]], i64 896; CHECK-NEXT: store i64 12, ptr [[PIA0B]], align 497; CHECK-NEXT: [[PIA0C:%.*]] = getelementptr i8, ptr [[PI]], i64 1698; CHECK-NEXT: store i64 56789, ptr [[PIA0C]], align 499; CHECK-NEXT: [[PIA1A:%.*]] = getelementptr i8, ptr [[PI]], i64 24100; CHECK-NEXT: store i64 123, ptr [[PIA1A]], align 4101; CHECK-NEXT: [[PIA1B:%.*]] = getelementptr i8, ptr [[PI]], i64 32102; CHECK-NEXT: store i64 1234, ptr [[PIA1B]], align 4103; CHECK-NEXT: [[PIA1C:%.*]] = getelementptr i8, ptr [[PI]], i64 40104; CHECK-NEXT: store i64 67890, ptr [[PIA1C]], align 4105; CHECK-NEXT: ret void106;107; Fold atol(a[0].a) to 1.108 %ia0a = call i64 @atol(ptr @a)109 store i64 %ia0a, ptr %pi110 111; Fold atol(a[0].b) to 12.112 %pa0b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 0113 %ia0b = call i64 @atol(ptr %pa0b)114 %pia0b = getelementptr i64, ptr %pi, i32 1115 store i64 %ia0b, ptr %pia0b116 117; Fold atol(a[0].c) to 56789.118 %pa0c = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 2, i64 0119 %ia0c = call i64 @atol(ptr %pa0c)120 %pia0c = getelementptr i64, ptr %pi, i32 2121 store i64 %ia0c, ptr %pia0c122 123; Fold atol(a[1].a) to 123.124 %pa1a = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 0125 %ia1a = call i64 @atol(ptr %pa1a)126 %pia1a = getelementptr i64, ptr %pi, i32 3127 store i64 %ia1a, ptr %pia1a128 129; Fold atol(a[1].b) to 1234.130 %pa1b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 0131 %ia1b = call i64 @atol(ptr %pa1b)132 %pia1b = getelementptr i64, ptr %pi, i32 4133 store i64 %ia1b, ptr %pia1b134 135; Fold atol(a[1].c) to 67890.136 %pa1c = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 2, i64 0137 %ia1c = call i64 @atol(ptr %pa1c)138 %pia1c = getelementptr i64, ptr %pi, i32 5139 store i64 %ia1c, ptr %pia1c140 141 ret void142}143 144 145; Fold atoll(a[I].M + C) for constant I in [0, 1], member M in [a, b, c],146; and C in a valid range to a constant.147 148define void @fold_atoll_member_pC(ptr %pi) {149; CHECK-LABEL: @fold_atoll_member_pC(150; CHECK-NEXT: store i64 1, ptr [[PI:%.*]], align 4151; CHECK-NEXT: [[PIA0BP1:%.*]] = getelementptr i8, ptr [[PI]], i64 8152; CHECK-NEXT: store i64 2, ptr [[PIA0BP1]], align 4153; CHECK-NEXT: [[PIA0CP3:%.*]] = getelementptr i8, ptr [[PI]], i64 16154; CHECK-NEXT: store i64 89, ptr [[PIA0CP3]], align 4155; CHECK-NEXT: [[PIA1AP2:%.*]] = getelementptr i8, ptr [[PI]], i64 24156; CHECK-NEXT: store i64 3, ptr [[PIA1AP2]], align 4157; CHECK-NEXT: [[PIA1BP3:%.*]] = getelementptr i8, ptr [[PI]], i64 32158; CHECK-NEXT: store i64 4, ptr [[PIA1BP3]], align 4159; CHECK-NEXT: [[PIA1CP4:%.*]] = getelementptr i8, ptr [[PI]], i64 40160; CHECK-NEXT: store i64 0, ptr [[PIA1CP4]], align 4161; CHECK-NEXT: ret void162;163; Fold atoll(a[0].a) to 1.164 %ia0a = call i64 @atol(ptr @a)165 store i64 %ia0a, ptr %pi166 167; Fold atoll(a[0].b + 1) to 2.168 %pa0bp1 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 1169 %ia0bp1 = call i64 @atol(ptr %pa0bp1)170 %pia0bp1 = getelementptr i64, ptr %pi, i32 1171 store i64 %ia0bp1, ptr %pia0bp1172 173; Fold atoll(a[0].c + 3) to 89.174 %pa0cp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 2, i64 3175 %ia0cp3 = call i64 @atol(ptr %pa0cp3)176 %pia0cp3 = getelementptr i64, ptr %pi, i32 2177 store i64 %ia0cp3, ptr %pia0cp3178 179; Fold atoll(a[1].a + 2) to 3.180 %pa1ap2 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 2181 %ia1ap2 = call i64 @atol(ptr %pa1ap2)182 %pia1ap2 = getelementptr i64, ptr %pi, i32 3183 store i64 %ia1ap2, ptr %pia1ap2184 185; Fold atoll(a[1].b + 3) to 4.186 %pa1bp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 3187 %ia1bp3 = call i64 @atol(ptr %pa1bp3)188 %pia1bp3 = getelementptr i64, ptr %pi, i32 4189 store i64 %ia1bp3, ptr %pia1bp3190 191; Fold atoll(a[1].c + 4) to 0.192 %pa1cp4 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 2, i64 4193 %ia1cp4 = call i64 @atol(ptr %pa1cp4)194 %pia1cp4 = getelementptr i64, ptr %pi, i32 5195 store i64 %ia1cp4, ptr %pia1cp4196 197 ret void198}199 200 201; Fold strtol(a[I].M + C, 0, 0) for constant I in [0, 1], member M in [a, b, c],202; and C in a valid range to a constant.203 204define void @fold_strtol_member_pC(ptr %pi) {205; CHECK-LABEL: @fold_strtol_member_pC(206; CHECK-NEXT: store i64 1, ptr [[PI:%.*]], align 4207; CHECK-NEXT: [[PIA0BP1:%.*]] = getelementptr i8, ptr [[PI]], i64 8208; CHECK-NEXT: store i64 2, ptr [[PIA0BP1]], align 4209; CHECK-NEXT: [[PIA0CP3:%.*]] = getelementptr i8, ptr [[PI]], i64 16210; CHECK-NEXT: store i64 89, ptr [[PIA0CP3]], align 4211; CHECK-NEXT: [[PIA1AP2:%.*]] = getelementptr i8, ptr [[PI]], i64 24212; CHECK-NEXT: store i64 3, ptr [[PIA1AP2]], align 4213; CHECK-NEXT: [[PIA1BP3:%.*]] = getelementptr i8, ptr [[PI]], i64 32214; CHECK-NEXT: store i64 4, ptr [[PIA1BP3]], align 4215; CHECK-NEXT: [[PIA1CP4:%.*]] = getelementptr i8, ptr [[PI]], i64 40216; CHECK-NEXT: store i64 0, ptr [[PIA1CP4]], align 4217; CHECK-NEXT: ret void218;219; Fold strtol(a[0].a, 0, 0) to 1.220 %ia0a = call i64 @strtol(ptr @a, ptr null, i32 0)221 store i64 %ia0a, ptr %pi222 223; Fold strtol(a[0].b + 1, 0, 0, ptr null, i32 0) to 2.224 %pa0bp1 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 1225 %ia0bp1 = call i64 @strtol(ptr %pa0bp1, ptr null, i32 0)226 %pia0bp1 = getelementptr i64, ptr %pi, i32 1227 store i64 %ia0bp1, ptr %pia0bp1228 229; Fold strtol(a[0].c + 3, 0, 0, ptr null, i32 0) to 89.230 %pa0cp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 2, i64 3231 %ia0cp3 = call i64 @strtol(ptr %pa0cp3, ptr null, i32 0)232 %pia0cp3 = getelementptr i64, ptr %pi, i32 2233 store i64 %ia0cp3, ptr %pia0cp3234 235; Fold strtol(a[1].a + 2, 0, 0, ptr null, i32 0) to 3.236 %pa1ap2 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 2237 %ia1ap2 = call i64 @strtol(ptr %pa1ap2, ptr null, i32 0)238 %pia1ap2 = getelementptr i64, ptr %pi, i32 3239 store i64 %ia1ap2, ptr %pia1ap2240 241; Fold strtol(a[1].b + 3, 0, 0, ptr null, i32 0) to 4.242 %pa1bp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 3243 %ia1bp3 = call i64 @strtol(ptr %pa1bp3, ptr null, i32 0)244 %pia1bp3 = getelementptr i64, ptr %pi, i32 4245 store i64 %ia1bp3, ptr %pia1bp3246 247; Fold strtol(a[1].c + 4, 0, 0, ptr null, i32 0) to 0.248 %pa1cp4 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 2, i64 4249 %ia1cp4 = call i64 @strtol(ptr %pa1cp4, ptr null, i32 0)250 %pia1cp4 = getelementptr i64, ptr %pi, i32 5251 store i64 %ia1cp4, ptr %pia1cp4252 253 ret void254}255 256 257; Fold strtoll(a[I].M + C, 0, 0) for constant I in [0, 1], member M258; in [a, b, c], and C in a valid range to a constant.259 260define void @fold_strtoll_member_pC(ptr %pi) {261; CHECK-LABEL: @fold_strtoll_member_pC(262; CHECK-NEXT: store i64 1, ptr [[PI:%.*]], align 4263; CHECK-NEXT: [[PIA0BP1:%.*]] = getelementptr i8, ptr [[PI]], i64 8264; CHECK-NEXT: store i64 2, ptr [[PIA0BP1]], align 4265; CHECK-NEXT: [[PIA0CP3:%.*]] = getelementptr i8, ptr [[PI]], i64 16266; CHECK-NEXT: store i64 89, ptr [[PIA0CP3]], align 4267; CHECK-NEXT: [[PIA1AP2:%.*]] = getelementptr i8, ptr [[PI]], i64 24268; CHECK-NEXT: store i64 3, ptr [[PIA1AP2]], align 4269; CHECK-NEXT: [[PIA1BP3:%.*]] = getelementptr i8, ptr [[PI]], i64 32270; CHECK-NEXT: store i64 4, ptr [[PIA1BP3]], align 4271; CHECK-NEXT: [[PIA1CP4:%.*]] = getelementptr i8, ptr [[PI]], i64 40272; CHECK-NEXT: store i64 0, ptr [[PIA1CP4]], align 4273; CHECK-NEXT: ret void274;275; Fold strtoll(a[0].a, 0, 0) to 1.276 %ia0a = call i64 @strtoll(ptr @a, ptr null, i32 0)277 store i64 %ia0a, ptr %pi278 279; Fold strtoll(a[0].b + 1, 0, 0, ptr null, i32 0) to 2.280 %pa0bp1 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 1281 %ia0bp1 = call i64 @strtoll(ptr %pa0bp1, ptr null, i32 0)282 %pia0bp1 = getelementptr i64, ptr %pi, i32 1283 store i64 %ia0bp1, ptr %pia0bp1284 285; Fold strtoll(a[0].c + 3, 0, 0, ptr null, i32 0) to 89.286 %pa0cp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 2, i64 3287 %ia0cp3 = call i64 @strtoll(ptr %pa0cp3, ptr null, i32 0)288 %pia0cp3 = getelementptr i64, ptr %pi, i32 2289 store i64 %ia0cp3, ptr %pia0cp3290 291; Fold strtoll(a[1].a + 2, 0, 0, ptr null, i32 0) to 3.292 %pa1ap2 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 2293 %ia1ap2 = call i64 @strtoll(ptr %pa1ap2, ptr null, i32 0)294 %pia1ap2 = getelementptr i64, ptr %pi, i32 3295 store i64 %ia1ap2, ptr %pia1ap2296 297; Fold strtoll(a[1].b + 3, 0, 0, ptr null, i32 0) to 4.298 %pa1bp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 3299 %ia1bp3 = call i64 @strtoll(ptr %pa1bp3, ptr null, i32 0)300 %pia1bp3 = getelementptr i64, ptr %pi, i32 4301 store i64 %ia1bp3, ptr %pia1bp3302 303; Fold strtoll(a[1].c + 4, 0, 0, ptr null, i32 0) to 0.304 %pa1cp4 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 2, i64 4305 %ia1cp4 = call i64 @strtoll(ptr %pa1cp4, ptr null, i32 0)306 %pia1cp4 = getelementptr i64, ptr %pi, i32 5307 store i64 %ia1cp4, ptr %pia1cp4308 309 ret void310}311