brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.8 KiB · ad53825 Raw
345 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; Assertions have been autogenerated by utils/update_test_checks.py3;4; RUN: opt < %s -data-layout="E" -passes=instcombine -S | FileCheck %s --check-prefixes=ANY,BE5; RUN: opt < %s -data-layout="e" -passes=instcombine -S | FileCheck %s --check-prefixes=ANY,LE6;7; Test that the strncpy library call simplifier works correctly.8 9declare i64 @strlcpy(ptr, ptr, i64)10 11declare void @sink(ptr, i64)12 13 14@s4 = constant [5 x i8] c"1234\00"15 16 17; Verify that strlcpy(D, "", N) calls are transformed to a nul store18; to *D for nonzero N and folded to zero for all values of N.19 20define void @fold_strlcpy_s0(ptr %dst) {21; ANY-LABEL: @fold_strlcpy_s0(22; ANY-NEXT:    call void @sink(ptr [[DST:%.*]], i64 0)23; ANY-NEXT:    store i8 0, ptr [[DST]], align 124; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 0)25; ANY-NEXT:    store i8 0, ptr [[DST]], align 126; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 0)27; ANY-NEXT:    ret void28;29  %ps0 = getelementptr [5 x i8], ptr @s4, i32 0, i32 430 31; Fold strlcpy(D, "", 0) to just 0.32  %ns0_0 = call i64 @strlcpy(ptr %dst, ptr %ps0, i64 0)33  call void @sink(ptr %dst, i64 %ns0_0)34 35; Transform strlcpy(D, "", 1) to *D = '\0, 0.36  %ns0_1 = call i64 @strlcpy(ptr %dst, ptr %ps0, i64 1)37  call void @sink(ptr %dst, i64 %ns0_1)38 39; Transform strlcpy(D, "", SIZE_MAX) to *D = '\0, 0.40  %ns0_m1 = call i64 @strlcpy(ptr %dst, ptr %ps0, i64 -1)41  call void @sink(ptr %dst, i64 %ns0_m1)42 43  ret void44}45 46 47; Verify that strlcpy(D, "4", N) calls are transformed to a store to48; D[0] for nonzero N (and a nul store to D[1] for N greater than 1)49; and folded to 1 for all values of N.50 51define void @fold_strlcpy_s1(ptr %dst) {52; BE-LABEL: @fold_strlcpy_s1(53; BE-NEXT:    call void @sink(ptr [[DST:%.*]], i64 1)54; BE-NEXT:    store i8 0, ptr [[DST]], align 155; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 1)56; BE-NEXT:    store i16 13312, ptr [[DST]], align 157; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 1)58; BE-NEXT:    store i16 13312, ptr [[DST]], align 159; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 1)60; BE-NEXT:    store i16 13312, ptr [[DST]], align 161; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 1)62; BE-NEXT:    ret void63;64; LE-LABEL: @fold_strlcpy_s1(65; LE-NEXT:    call void @sink(ptr [[DST:%.*]], i64 1)66; LE-NEXT:    store i8 0, ptr [[DST]], align 167; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 1)68; LE-NEXT:    store i16 52, ptr [[DST]], align 169; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 1)70; LE-NEXT:    store i16 52, ptr [[DST]], align 171; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 1)72; LE-NEXT:    store i16 52, ptr [[DST]], align 173; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 1)74; LE-NEXT:    ret void75;76  %ps1 = getelementptr [5 x i8], ptr @s4, i32 0, i32 377 78; Fold strlcpy(D, "4", 0) to 1.79  %ns1_0 = call i64 @strlcpy(ptr %dst, ptr %ps1, i64 0)80  call void @sink(ptr %dst, i64 %ns1_0)81 82; Transform strlcpy(D, "4", 1) to *D = '\0', 1.83  %ns1_1 = call i64 @strlcpy(ptr %dst, ptr %ps1, i64 1)84  call void @sink(ptr %dst, i64 %ns1_1)85 86; Transform strlcpy(D, "4", 2) to D[0] = '\4, D[1] = '\0', 1.87  %ns1_2 = call i64 @strlcpy(ptr %dst, ptr %ps1, i64 2)88  call void @sink(ptr %dst, i64 %ns1_2)89 90; Transform strlcpy(D, "4", 3) to D[0] = '\4, D[1] = '\0', 1..91  %ns1_3 = call i64 @strlcpy(ptr %dst, ptr %ps1, i64 3)92  call void @sink(ptr %dst, i64 %ns1_3)93 94; Transform strlcpy(D, "4", SIZE_MAX) to D[0] = '\4, D[1] = '\0', 1.95  %ns1_m1 = call i64 @strlcpy(ptr %dst, ptr %ps1, i64 -1)96  call void @sink(ptr %dst, i64 %ns1_m1)97 98  ret void99}100 101 102; Verify that strlcpy(D, "1234", N) calls are transformed to a copy of103; the N - 1 leading characters of the string to D and folded to 4 for104; all values of N.105 106define void @fold_strlcpy_s5(ptr %dst) {107; BE-LABEL: @fold_strlcpy_s5(108; BE-NEXT:    call void @sink(ptr [[DST:%.*]], i64 4)109; BE-NEXT:    store i8 0, ptr [[DST]], align 1110; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)111; BE-NEXT:    store i8 49, ptr [[DST]], align 1112; BE-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 1113; BE-NEXT:    store i8 0, ptr [[TMP1]], align 1114; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)115; BE-NEXT:    store i16 12594, ptr [[DST]], align 1116; BE-NEXT:    [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 2117; BE-NEXT:    store i8 0, ptr [[TMP2]], align 1118; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)119; BE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(3) [[DST]], ptr noundef nonnull align 1 dereferenceable(3) @s4, i64 3, i1 false)120; BE-NEXT:    [[TMP3:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 3121; BE-NEXT:    store i8 0, ptr [[TMP3]], align 1122; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)123; BE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST]], ptr noundef nonnull align 1 dereferenceable(5) @s4, i64 5, i1 false)124; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)125; BE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST]], ptr noundef nonnull align 1 dereferenceable(5) @s4, i64 5, i1 false)126; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)127; BE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST]], ptr noundef nonnull align 1 dereferenceable(5) @s4, i64 5, i1 false)128; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)129; BE-NEXT:    ret void130;131; LE-LABEL: @fold_strlcpy_s5(132; LE-NEXT:    call void @sink(ptr [[DST:%.*]], i64 4)133; LE-NEXT:    store i8 0, ptr [[DST]], align 1134; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)135; LE-NEXT:    store i8 49, ptr [[DST]], align 1136; LE-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 1137; LE-NEXT:    store i8 0, ptr [[TMP1]], align 1138; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)139; LE-NEXT:    store i16 12849, ptr [[DST]], align 1140; LE-NEXT:    [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 2141; LE-NEXT:    store i8 0, ptr [[TMP2]], align 1142; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)143; LE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(3) [[DST]], ptr noundef nonnull align 1 dereferenceable(3) @s4, i64 3, i1 false)144; LE-NEXT:    [[TMP3:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 3145; LE-NEXT:    store i8 0, ptr [[TMP3]], align 1146; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)147; LE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST]], ptr noundef nonnull align 1 dereferenceable(5) @s4, i64 5, i1 false)148; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)149; LE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST]], ptr noundef nonnull align 1 dereferenceable(5) @s4, i64 5, i1 false)150; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)151; LE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST]], ptr noundef nonnull align 1 dereferenceable(5) @s4, i64 5, i1 false)152; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 4)153; LE-NEXT:    ret void154;155 156; Fold strlcpy(D, "1234", 0) to 4.157  %ns4_0 = call i64 @strlcpy(ptr %dst, ptr @s4, i64 0)158  call void @sink(ptr %dst, i64 %ns4_0)159 160; Transform strlcpy(D, "1234", 1) to *D = '\0', 4.161  %ns4_1 = call i64 @strlcpy(ptr %dst, ptr @s4, i64 1)162  call void @sink(ptr %dst, i64 %ns4_1)163 164; Transform strlcpy(D, "1234", 2) to D[0] = '1', D[1] = '\0', 4.165  %ns4_2 = call i64 @strlcpy(ptr %dst, ptr @s4, i64 2)166  call void @sink(ptr %dst, i64 %ns4_2)167 168; Transform strlcpy(D, S="1234", 3) to memcpy(D, S, 2), D[2] = '\0', 4.169  %ns4_3 = call i64 @strlcpy(ptr %dst, ptr @s4, i64 3)170  call void @sink(ptr %dst, i64 %ns4_3)171 172; Transform strlcpy(D, S="1234", 4) to memcpy(D, S, 3), D[3] = '\0', 4.173  %ns4_4 = call i64 @strlcpy(ptr %dst, ptr @s4, i64 4)174  call void @sink(ptr %dst, i64 %ns4_4)175 176; Transform strlcpy(D, S="1234", 5) to memcpy(D, S, 5), 4.177  %ns4_5 = call i64 @strlcpy(ptr %dst, ptr @s4, i64 5)178  call void @sink(ptr %dst, i64 %ns4_5)179 180; Transform strlcpy(D, S="1234", 9) to memcpy(D, S, 5), 4.181  %ns4_9 = call i64 @strlcpy(ptr %dst, ptr @s4, i64 5)182  call void @sink(ptr %dst, i64 %ns4_9)183 184; Transform strlcpy(D, S="1234", SIZE_MAX) to memcpy(D, S, 5), 4.185  %ns4_m1 = call i64 @strlcpy(ptr %dst, ptr @s4, i64 -1)186  call void @sink(ptr %dst, i64 %ns4_m1)187 188  ret void189}190 191; Verify that strlcpy(D, S, 1) calls are transformed into a nul store192; to *D, strlcpy(D, S, 0) to a no-op, and the result of both folded193; to strlen(S).194 195define void @fold_strlcpy_s_0(ptr %dst, ptr %s, i64 %n) {196; ANY-LABEL: @fold_strlcpy_s_0(197; ANY-NEXT:    store i8 0, ptr [[DST:%.*]], align 1198; ANY-NEXT:    [[STRLEN:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[S:%.*]])199; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 [[STRLEN]])200; ANY-NEXT:    [[STRLEN1:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[S]])201; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 [[STRLEN1]])202; ANY-NEXT:    [[STRLEN2:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[S]])203; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 [[STRLEN2]])204; ANY-NEXT:    ret void205;206; Transform strlcpy(D, S, 1) to *D = '\0', strlen(S).207  %ns_1 = call i64 @strlcpy(ptr %dst, ptr %s, i64 1)208  call void @sink(ptr %dst, i64 %ns_1)209 210; For strlcpy(D, S, 0) to strlen(S).211  %ns_0 = call i64 @strlcpy(ptr %dst, ptr %s, i64 0)212  call void @sink(ptr %dst, i64 %ns_0)213 214  ; Verify that calling strlcpy with a null destination is also folded215  ; (to match a possible extension of some implementations that emulate216  ; snprintf(0, 0, "%s", S)).217  %n0_s_0 = call i64 @strlcpy(ptr null, ptr %s, i64 0)218  call void @sink(ptr %dst, i64 %n0_s_0)219 220  ret void221}222 223 224; Verify that strlcpy(D, S, N) calls are left alone when S and/or N are225; not known (except for the cases handled above).  Also verify that they226; annotate the destination argument with the dereferenceable attribute227; only with nonzero N.228 229define void @call_strlcpy_s0_n(ptr %dst, ptr %s, i64 %n) {230; ANY-LABEL: @call_strlcpy_s0_n(231; ANY-NEXT:    [[NS_2:%.*]] = call i64 @strlcpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[S:%.*]], i64 2)232; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 [[NS_2]])233; ANY-NEXT:    [[NS_N:%.*]] = call i64 @strlcpy(ptr nonnull [[DST]], ptr noundef nonnull dereferenceable(1) [[S]], i64 [[N:%.*]])234; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 [[NS_N]])235; ANY-NEXT:    [[NZ:%.*]] = or i64 [[N]], 1236; ANY-NEXT:    [[NS_NZ:%.*]] = call i64 @strlcpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[S]], i64 [[NZ]])237; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 [[NS_NZ]])238; ANY-NEXT:    [[NS0_N:%.*]] = call i64 @strlcpy(ptr nonnull [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds nuw (i8, ptr @s4, i64 4), i64 [[N]])239; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 [[NS0_N]])240; ANY-NEXT:    [[NS1_N:%.*]] = call i64 @strlcpy(ptr nonnull [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds nuw (i8, ptr @s4, i64 3), i64 [[N]])241; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 [[NS1_N]])242; ANY-NEXT:    [[NS4_N:%.*]] = call i64 @strlcpy(ptr nonnull [[DST]], ptr noundef nonnull dereferenceable(1) @s4, i64 [[N]])243; ANY-NEXT:    call void @sink(ptr nonnull [[DST]], i64 [[NS4_N]])244; ANY-NEXT:    ret void245;246  %ns_2 = call i64 @strlcpy(ptr %dst, ptr %s, i64 2)247  call void @sink(ptr %dst, i64 %ns_2)248 249  %ns_n = call i64 @strlcpy(ptr %dst, ptr %s, i64 %n)250  call void @sink(ptr %dst, i64 %ns_n)251 252  %nz = or i64 %n, 1253  %ns_nz = call i64 @strlcpy(ptr %dst, ptr %s, i64 %nz)254  call void @sink(ptr %dst, i64 %ns_nz)255 256 257  %ps0 = getelementptr [5 x i8], ptr @s4, i32 0, i32 4258  %ns0_n = call i64 @strlcpy(ptr %dst, ptr %ps0, i64 %n)259  call void @sink(ptr %dst, i64 %ns0_n)260 261  %ps1 = getelementptr [5 x i8], ptr @s4, i32 0, i32 3262  %ns1_n = call i64 @strlcpy(ptr %dst, ptr %ps1, i64 %n)263  call void @sink(ptr %dst, i64 %ns1_n)264 265  %ns4_n = call i64 @strlcpy(ptr %dst, ptr @s4, i64 %n)266  call void @sink(ptr %dst, i64 %ns4_n)267 268  ret void269}270 271 272@a5 = constant [5 x i8] c"12345"273 274; Verify that the transformation behaves reasonably even when the source275; array is not a nul-terminated string as it's required to be (and doesn't276; for example attempt to read past its end).  All the calls below are277; undefined so technically reading past the end would be fine but it's278; easy to avoid.279 280define void @fold_strlcpy_a5(ptr %dst, i64 %n) {281; BE-LABEL: @fold_strlcpy_a5(282; BE-NEXT:    call void @sink(ptr [[DST:%.*]], i64 5)283; BE-NEXT:    store i8 0, ptr [[DST]], align 1284; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 5)285; BE-NEXT:    store i8 49, ptr [[DST]], align 1286; BE-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 1287; BE-NEXT:    store i8 0, ptr [[TMP1]], align 1288; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 5)289; BE-NEXT:    store i32 825373492, ptr [[DST]], align 1290; BE-NEXT:    [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 4291; BE-NEXT:    store i8 0, ptr [[TMP2]], align 1292; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 5)293; BE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST]], ptr noundef nonnull align 1 dereferenceable(5) @a5, i64 5, i1 false)294; BE-NEXT:    [[TMP3:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 5295; BE-NEXT:    store i8 0, ptr [[TMP3]], align 1296; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 5)297; BE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST]], ptr noundef nonnull align 1 dereferenceable(5) @a5, i64 5, i1 false)298; BE-NEXT:    [[TMP4:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 5299; BE-NEXT:    store i8 0, ptr [[TMP4]], align 1300; BE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 5)301; BE-NEXT:    ret void302;303; LE-LABEL: @fold_strlcpy_a5(304; LE-NEXT:    call void @sink(ptr [[DST:%.*]], i64 5)305; LE-NEXT:    store i8 0, ptr [[DST]], align 1306; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 5)307; LE-NEXT:    store i8 49, ptr [[DST]], align 1308; LE-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 1309; LE-NEXT:    store i8 0, ptr [[TMP1]], align 1310; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 5)311; LE-NEXT:    store i32 875770417, ptr [[DST]], align 1312; LE-NEXT:    [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 4313; LE-NEXT:    store i8 0, ptr [[TMP2]], align 1314; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 5)315; LE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST]], ptr noundef nonnull align 1 dereferenceable(5) @a5, i64 5, i1 false)316; LE-NEXT:    [[TMP3:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 5317; LE-NEXT:    store i8 0, ptr [[TMP3]], align 1318; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 5)319; LE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST]], ptr noundef nonnull align 1 dereferenceable(5) @a5, i64 5, i1 false)320; LE-NEXT:    [[TMP4:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 5321; LE-NEXT:    store i8 0, ptr [[TMP4]], align 1322; LE-NEXT:    call void @sink(ptr nonnull [[DST]], i64 5)323; LE-NEXT:    ret void324;325  %na5_0 = call i64 @strlcpy(ptr %dst, ptr @a5, i64 0)326  call void @sink(ptr %dst, i64 %na5_0)327 328  %na5_1 = call i64 @strlcpy(ptr %dst, ptr @a5, i64 1)329  call void @sink(ptr %dst, i64 %na5_1)330 331  %na5_2 = call i64 @strlcpy(ptr %dst, ptr @a5, i64 2)332  call void @sink(ptr %dst, i64 %na5_2)333 334  %na5_5 = call i64 @strlcpy(ptr %dst, ptr @a5, i64 5)335  call void @sink(ptr %dst, i64 %na5_5)336 337  %na5_6 = call i64 @strlcpy(ptr %dst, ptr @a5, i64 6)338  call void @sink(ptr %dst, i64 %na5_6)339 340  %na5_9 = call i64 @strlcpy(ptr %dst, ptr @a5, i64 9)341  call void @sink(ptr %dst, i64 %na5_9)342 343  ret void344}345