brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · 0e1f800 Raw
169 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2;3; Test that strncpy(D, S, N) calls with the empty string S as a source4; are simplified for all values of N.5;6; RUN: opt < %s -passes=instcombine -S | FileCheck %s7 8declare ptr @strncpy(ptr, ptr, i64)9 10; A string of length 4 but size 9 to also verify that characters after11; the nul don't affect the transformation.12@s4 = constant [9 x i8] c"1234\00567\00"13 14declare void @sink(ptr, ptr)15 16 17; Verify that exactly overlapping strncpy(D, D, N) calls are simplified18; only when N < 2.19 20define void @fold_strncpy_overlap(ptr %dst, i64 %n) {21; CHECK-LABEL: @fold_strncpy_overlap(22; CHECK-NEXT:    call void @sink(ptr [[DST:%.*]], ptr [[DST]])23; CHECK-NEXT:    call void @sink(ptr [[DST]], ptr [[DST]])24; CHECK-NEXT:    ret void25;26; Fold strncpy(D, D, 0) to D.27  %ed_0 = call ptr @strncpy(ptr %dst, ptr %dst, i64 0)28  call void @sink(ptr %dst, ptr %ed_0)29 30; Fold strncpy(D, D, 1) to D.31  %ed_1 = call ptr @strncpy(ptr %dst, ptr %dst, i64 1)32  call void @sink(ptr %dst, ptr %ed_1)33 34  ret void35}36 37 38; Verify that exactly overlapping strncpy(D, D, N) calls are left alone39; when N >= 2.40; Such calls are undefined and although they're benign and could be41; simplified to42;   memset(D + strnlen(D, N), D, N - strnlen(D, N))43; there is little to gain from it.44 45define void @call_strncpy_overlap(ptr %dst, i64 %n) {46; CHECK-LABEL: @call_strncpy_overlap(47; CHECK-NEXT:    [[ED_2:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[DST]], i64 2)48; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr [[ED_2]])49; CHECK-NEXT:    [[ED_3:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[DST]], i64 3)50; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr [[ED_3]])51; CHECK-NEXT:    [[ED_N:%.*]] = call ptr @strncpy(ptr nonnull [[DST]], ptr nonnull [[DST]], i64 [[N:%.*]])52; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr [[ED_N]])53; CHECK-NEXT:    ret void54;55 56; Do not transform strncpy(D, D, 2).57  %ed_2 = call ptr @strncpy(ptr %dst, ptr %dst, i64 2)58  call void @sink(ptr %dst, ptr %ed_2)59 60; Do not transform strncpy(D, D, 3).61  %ed_3 = call ptr @strncpy(ptr %dst, ptr %dst, i64 3)62  call void @sink(ptr %dst, ptr %ed_3)63 64; Do not transform strncpy(D, D, N).65  %ed_n = call ptr @strncpy(ptr %dst, ptr %dst, i64 %n)66  call void @sink(ptr %dst, ptr %ed_n)67 68  ret void69}70 71 72; Verify that strncpy(D, "", N) calls are transformed to memset(D, 0, N).73 74define void @fold_strncpy_s0(ptr %dst, i64 %n) {75; CHECK-LABEL: @fold_strncpy_s0(76; CHECK-NEXT:    call void @sink(ptr [[DST:%.*]], ptr [[DST]])77; CHECK-NEXT:    store i8 0, ptr [[DST]], align 178; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr nonnull [[DST]])79; CHECK-NEXT:    store i16 0, ptr [[DST]], align 180; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr nonnull [[DST]])81; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(9) [[DST]], i8 0, i64 9, i1 false)82; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr nonnull [[DST]])83; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr nonnull align 1 [[DST]], i8 0, i64 [[N:%.*]], i1 false)84; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr nonnull [[DST]])85; CHECK-NEXT:    ret void86;87  %ps0 = getelementptr [9 x i8], ptr @s4, i32 0, i32 488 89; Fold strncpy(D, "", 0) to just D.90  %es0_0 = call ptr @strncpy(ptr %dst, ptr %ps0, i64 0)91  call void @sink(ptr %dst, ptr %es0_0)92 93; Transform strncpy(D, "", 1) to *D = '\0, D.94  %es0_1 = call ptr @strncpy(ptr %dst, ptr %ps0, i64 1)95  call void @sink(ptr %dst, ptr %es0_1)96 97; Transform strncpy(D, "", 2) to memset(D, 0, 2), D.98  %es0_2 = call ptr @strncpy(ptr %dst, ptr %ps0, i64 2)99  call void @sink(ptr %dst, ptr %es0_2)100 101; Transform strncpy(D, "", 9) to memset(D, 0, 9), D.102  %es0_9 = call ptr @strncpy(ptr %dst, ptr %ps0, i64 9)103  call void @sink(ptr %dst, ptr %es0_9)104 105; Transform strncpy(D, "", n) to memset(D, 0, n), D.106  %es0_n = call ptr @strncpy(ptr %dst, ptr %ps0, i64 %n)107  call void @sink(ptr %dst, ptr %es0_n)108 109  ret void110}111 112 113; Verify that strncpy(D, S, N) calls with nonconstant source S and constant114; size are simplified when N < 2.115 116define void @fold_strncpy_s(ptr %dst, ptr %src, i64 %n) {117; CHECK-LABEL: @fold_strncpy_s(118; CHECK-NEXT:    call void @sink(ptr [[DST:%.*]], ptr [[DST]])119; CHECK-NEXT:    [[STXNCPY_CHAR0:%.*]] = load i8, ptr [[SRC:%.*]], align 1120; CHECK-NEXT:    store i8 [[STXNCPY_CHAR0]], ptr [[DST]], align 1121; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr nonnull [[DST]])122; CHECK-NEXT:    ret void123;124; Fold strncpy(D, S, 0) to just D.125  %ed_0 = call ptr @strncpy(ptr %dst, ptr %src, i64 0)126  call void @sink(ptr %dst, ptr %ed_0)127 128; Transform strncpy(D, S, 1) to *D = '\0, D.129  %ed_1 = call ptr @strncpy(ptr %dst, ptr %src, i64 1)130  call void @sink(ptr %dst, ptr %ed_1)131 132  ret void133}134 135 136; Verify that strncpy(D, S, N) calls with nonconstant source S and constant137; size are not transformed when N is either unknown or greater than one.138; Also verify that the arguments of the call are annotated with the right139; attributes.140 141define void @call_strncpy_s(ptr %dst, ptr %src, i64 %n) {142; CHECK-LABEL: @call_strncpy_s(143; CHECK-NEXT:    [[ED_2:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[SRC:%.*]], i64 2)144; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr [[ED_2]])145; CHECK-NEXT:    [[ED_9:%.*]] = call ptr @strncpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[SRC]], i64 9)146; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr [[ED_9]])147; CHECK-NEXT:    [[ED_N:%.*]] = call ptr @strncpy(ptr nonnull [[DST]], ptr nonnull [[SRC]], i64 [[N:%.*]])148; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr [[ED_N]])149; CHECK-NEXT:    ret void150;151; Do not transform strncpy(D, S, 2) when S is unknown.  Both *D and *S must152; be derefernceable but neither D[1] nor S[1] need be.153  %ed_2 = call ptr @strncpy(ptr %dst, ptr %src, i64 2)154  call void @sink(ptr %dst, ptr %ed_2)155 156; Do not transform strncpy(D, S, 9) when S is unknown..157  %ed_9 = call ptr @strncpy(ptr %dst, ptr %src, i64 9)158  call void @sink(ptr %dst, ptr %ed_9)159 160; Do not transform strncpy(D, S, N) when all arguments are unknown.  Both161; D and S must be nonnull but neither *D nor *S need be dereferenceable.162; TODO: Both D and S should be annotated nonnull and noundef regardless163; of the value of N.  See https://reviews.llvm.org/D124633.164  %ed_n = call ptr @strncpy(ptr %dst, ptr %src, i64 %n)165  call void @sink(ptr %dst, ptr %ed_n)166 167  ret void168}169