[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / InstCombine / strncpy-4.ll
blobaa70e76e20ed9097bccc7d8133b7d656ced49f7e
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
3 ; Test that strncpy(D, S, N) calls with the empty string S as a source
4 ; are simplified for all values of N.
6 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
8 declare ptr @strncpy(ptr, ptr, i64)
10 ; A string of length 4 but size 9 to also verify that characters after
11 ; the nul don't affect the transformation.
12 @s4 = constant [9 x i8] c"1234\00567\00"
14 declare void @sink(ptr, ptr)
17 ; Verify that exactly overlapping strncpy(D, D, N) calls are simplified
18 ; only when N < 2.
20 define 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 void
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)
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)
34   ret void
38 ; Verify that exactly overlapping strncpy(D, D, N) calls are left alone
39 ; when N >= 2.
40 ; Such calls are undefined and although they're benign and could be
41 ; simplified to
42 ;   memset(D + strnlen(D, N), D, N - strnlen(D, N))
43 ; there is little to gain from it.
45 define 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 [[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 [[DST]], ptr [[ED_3]])
51 ; CHECK-NEXT:    [[ED_N:%.*]] = call ptr @strncpy(ptr [[DST]], ptr [[DST]], i64 [[N:%.*]])
52 ; CHECK-NEXT:    call void @sink(ptr [[DST]], ptr [[ED_N]])
53 ; CHECK-NEXT:    ret void
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)
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)
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)
68   ret void
72 ; Verify that strncpy(D, "", N) calls are transformed to memset(D, 0, N).
74 define 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 1
78 ; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr nonnull [[DST]])
79 ; CHECK-NEXT:    store i16 0, ptr [[DST]], align 1
80 ; 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 void
87   %ps0 = getelementptr [9 x i8], ptr @s4, i32 0, i32 4
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)
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)
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)
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)
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)
109   ret void
113 ; Verify that strncpy(D, S, N) calls with nonconstant source S and constant
114 ; size are simplified when N < 2.
116 define 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 1
120 ; CHECK-NEXT:    store i8 [[STXNCPY_CHAR0]], ptr [[DST]], align 1
121 ; CHECK-NEXT:    call void @sink(ptr nonnull [[DST]], ptr nonnull [[DST]])
122 ; CHECK-NEXT:    ret void
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)
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)
132   ret void
136 ; Verify that strncpy(D, S, N) calls with nonconstant source S and constant
137 ; 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 right
139 ; attributes.
141 define 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 [[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 [[DST]], ptr [[ED_9]])
147 ; CHECK-NEXT:    [[ED_N:%.*]] = call ptr @strncpy(ptr [[DST]], ptr [[SRC]], i64 [[N:%.*]])
148 ; CHECK-NEXT:    call void @sink(ptr [[DST]], ptr [[ED_N]])
149 ; CHECK-NEXT:    ret void
151 ; Do not transform strncpy(D, S, 2) when S is unknown.  Both *D and *S must
152 ; 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)
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)
160 ; Do not transform strncpy(D, S, N) when all arguments are unknown.  Both
161 ; 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 regardless
163 ; 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)
167   ret void