1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4@hello = private constant [11 x i8] c"helloworld\00", align 1 5@NoNulTerminator = private constant [10 x i8] c"helloworld", align 1 6@StopCharAfterNulTerminator = private constant [12 x i8] c"helloworld\00x", align 1 7@StringWithEOF = constant [14 x i8] c"helloworld\FFab\00", align 1 8 9declare ptr @memccpy(ptr, ptr, i32, i64) 10 11define ptr @memccpy_to_memcpy(ptr %dst) { 12; CHECK-LABEL: @memccpy_to_memcpy( 13; CHECK-NEXT: store i64 8245940763182785896, ptr [[DST:%.*]], align 1 14; CHECK-NEXT: [[CALL:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 8 15; CHECK-NEXT: ret ptr [[CALL]] 16; 17 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 114, i64 12) ; 114 is 'r' 18 ret ptr %call 19} 20 21define ptr @memccpy_to_memcpy2(ptr %dst) { 22; CHECK-LABEL: @memccpy_to_memcpy2( 23; CHECK-NEXT: store i64 8245940763182785896, ptr [[DST:%.*]], align 1 24; CHECK-NEXT: [[CALL:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 8 25; CHECK-NEXT: ret ptr [[CALL]] 26; 27 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 114, i64 8); ; 114 is 'r' 28 ret ptr %call 29} 30 31define void @memccpy_to_memcpy3(ptr %dst) { 32; CHECK-LABEL: @memccpy_to_memcpy3( 33; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(5) @hello, i64 5, i1 false) 34; CHECK-NEXT: ret void 35; 36 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 111, i64 10) ; 111 is 'o' 37 ret void 38} 39 40define void @memccpy_to_memcpy3_tail(ptr %dst) { 41; CHECK-LABEL: @memccpy_to_memcpy3_tail( 42; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(5) @hello, i64 5, i1 false) 43; CHECK-NEXT: ret void 44; 45 %call = tail call ptr @memccpy(ptr %dst, ptr @hello, i32 111, i64 10) ; 111 is 'o' 46 ret void 47} 48 49define ptr @memccpy_to_memcpy3_musttail(ptr %dst, ptr %x, i32 %y, i64 %z) { 50; CHECK-LABEL: @memccpy_to_memcpy3_musttail( 51; CHECK-NEXT: [[CALL:%.*]] = musttail call ptr @memccpy(ptr [[DST:%.*]], ptr nonnull @hello, i32 111, i64 10) 52; CHECK-NEXT: ret ptr [[CALL]] 53; 54 %call = musttail call ptr @memccpy(ptr %dst, ptr @hello, i32 111, i64 10) ; 111 is 'o' 55 ret ptr %call 56} 57 58 59define void @memccpy_to_memcpy4(ptr %dst) { 60; CHECK-LABEL: @memccpy_to_memcpy4( 61; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(11) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(11) @hello, i64 11, i1 false) 62; CHECK-NEXT: ret void 63; 64 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 0, i64 12) 65 ret void 66} 67 68define ptr @memccpy_to_memcpy5(ptr %dst) { 69; CHECK-LABEL: @memccpy_to_memcpy5( 70; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(7) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(7) @hello, i64 7, i1 false) 71; CHECK-NEXT: ret ptr null 72; 73 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 114, i64 7) 74 ret ptr %call 75} 76 77define ptr @memccpy_to_memcpy5_tail(ptr %dst) { 78; CHECK-LABEL: @memccpy_to_memcpy5_tail( 79; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(7) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(7) @hello, i64 7, i1 false) 80; CHECK-NEXT: ret ptr null 81; 82 %call = tail call ptr @memccpy(ptr %dst, ptr @hello, i32 114, i64 7) 83 ret ptr %call 84} 85 86define ptr @memccpy_to_memcpy5_musttail(ptr %dst, ptr %x, i32 %y, i64 %z) { 87; CHECK-LABEL: @memccpy_to_memcpy5_musttail( 88; CHECK-NEXT: [[CALL:%.*]] = musttail call ptr @memccpy(ptr [[DST:%.*]], ptr nonnull @hello, i32 114, i64 7) 89; CHECK-NEXT: ret ptr [[CALL]] 90; 91 %call = musttail call ptr @memccpy(ptr %dst, ptr @hello, i32 114, i64 7) 92 ret ptr %call 93} 94 95define ptr @memccpy_to_memcpy6(ptr %dst) { 96; CHECK-LABEL: @memccpy_to_memcpy6( 97; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(6) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i64 6, i1 false) 98; CHECK-NEXT: ret ptr null 99; 100 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 114, i64 6); 101 ret ptr %call 102} 103 104define ptr @memccpy_to_memcpy7(ptr %dst) { 105; CHECK-LABEL: @memccpy_to_memcpy7( 106; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(5) @hello, i64 5, i1 false) 107; CHECK-NEXT: ret ptr null 108; 109 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 115, i64 5) ; 115 is 's' 110 ret ptr %call 111} 112 113define ptr @memccpy_to_memcpy8(ptr %dst) { 114; CHECK-LABEL: @memccpy_to_memcpy8( 115; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(11) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(11) @hello, i64 11, i1 false) 116; CHECK-NEXT: ret ptr null 117; 118 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 115, i64 11) ; 115 is 's' 119 ret ptr %call 120} 121 122define ptr @memccpy_to_memcpy9(ptr %dst, i64 %n) { 123; CHECK-LABEL: @memccpy_to_memcpy9( 124; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(12) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(12) @StopCharAfterNulTerminator, i64 12, i1 false) 125; CHECK-NEXT: [[CALL:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 12 126; CHECK-NEXT: ret ptr [[CALL]] 127; 128 %call = call ptr @memccpy(ptr %dst, ptr @StopCharAfterNulTerminator, i32 120, i64 15) ; 120 is 'x' 129 ret ptr %call 130} 131 132define ptr @memccpy_to_memcpy10(ptr %dst, i64 %n) { 133; CHECK-LABEL: @memccpy_to_memcpy10( 134; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(11) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(11) @StringWithEOF, i64 11, i1 false) 135; CHECK-NEXT: [[CALL:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 11 136; CHECK-NEXT: ret ptr [[CALL]] 137; 138 %call = call ptr @memccpy(ptr %dst, ptr @StringWithEOF, i32 255, i64 15) 139 ret ptr %call 140} 141 142define ptr @memccpy_to_memcpy11(ptr %dst, i64 %n) { 143; CHECK-LABEL: @memccpy_to_memcpy11( 144; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(11) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(11) @StringWithEOF, i64 11, i1 false) 145; CHECK-NEXT: [[CALL:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 11 146; CHECK-NEXT: ret ptr [[CALL]] 147; 148 %call = call ptr @memccpy(ptr %dst, ptr @StringWithEOF, i32 -1, i64 15) 149 ret ptr %call 150} 151 152define ptr @memccpy_to_memcpy12(ptr %dst, i64 %n) { 153; CHECK-LABEL: @memccpy_to_memcpy12( 154; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(11) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(11) @StringWithEOF, i64 11, i1 false) 155; CHECK-NEXT: [[CALL:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i64 11 156; CHECK-NEXT: ret ptr [[CALL]] 157; 158 %call = call ptr @memccpy(ptr %dst, ptr @StringWithEOF, i32 1023, i64 15) 159 ret ptr %call 160} 161 162define ptr @memccpy_to_null(ptr %dst, ptr %src, i32 %c) { 163; CHECK-LABEL: @memccpy_to_null( 164; CHECK-NEXT: ret ptr null 165; 166 %call = call ptr @memccpy(ptr %dst, ptr %src, i32 %c, i64 0) 167 ret ptr %call 168} 169 170define void @memccpy_dst_src_same_retval_unused(ptr %dst, i32 %c, i64 %n) { 171; CHECK-LABEL: @memccpy_dst_src_same_retval_unused( 172; CHECK-NEXT: ret void 173; 174 %call = call ptr @memccpy(ptr %dst, ptr %dst, i32 %c, i64 %n) 175 ret void 176} 177 178; Negative tests 179define ptr @unknown_src(ptr %dst, ptr %src) { 180; CHECK-LABEL: @unknown_src( 181; CHECK-NEXT: [[CALL:%.*]] = call ptr @memccpy(ptr [[DST:%.*]], ptr [[SRC:%.*]], i32 114, i64 12) 182; CHECK-NEXT: ret ptr [[CALL]] 183; 184 %call = call ptr @memccpy(ptr %dst, ptr %src, i32 114, i64 12) 185 ret ptr %call 186} 187 188define ptr @unknown_stop_char(ptr %dst, i32 %c) { 189; CHECK-LABEL: @unknown_stop_char( 190; CHECK-NEXT: [[CALL:%.*]] = call ptr @memccpy(ptr [[DST:%.*]], ptr nonnull @hello, i32 [[C:%.*]], i64 12) 191; CHECK-NEXT: ret ptr [[CALL]] 192; 193 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 %c, i64 12) 194 ret ptr %call 195} 196 197define ptr @unknown_size_n(ptr %dst, i64 %n) { 198; CHECK-LABEL: @unknown_size_n( 199; CHECK-NEXT: [[CALL:%.*]] = call ptr @memccpy(ptr [[DST:%.*]], ptr nonnull @hello, i32 114, i64 [[N:%.*]]) 200; CHECK-NEXT: ret ptr [[CALL]] 201; 202 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 114, i64 %n) 203 ret ptr %call 204} 205 206define ptr @no_nul_terminator(ptr %dst, i64 %n) { 207; CHECK-LABEL: @no_nul_terminator( 208; CHECK-NEXT: [[CALL:%.*]] = call ptr @memccpy(ptr [[DST:%.*]], ptr nonnull @StopCharAfterNulTerminator, i32 120, i64 [[N:%.*]]) 209; CHECK-NEXT: ret ptr [[CALL]] 210; 211 %call = call ptr @memccpy(ptr %dst, ptr @StopCharAfterNulTerminator, i32 120, i64 %n) ; 120 is 'x' 212 ret ptr %call 213} 214 215define ptr @possibly_valid_data_after_array(ptr %dst, i64 %n) { 216; CHECK-LABEL: @possibly_valid_data_after_array( 217; CHECK-NEXT: [[CALL:%.*]] = call ptr @memccpy(ptr [[DST:%.*]], ptr nonnull @NoNulTerminator, i32 115, i64 [[N:%.*]]) 218; CHECK-NEXT: ret ptr [[CALL]] 219; 220 %call = call ptr @memccpy(ptr %dst, ptr @NoNulTerminator, i32 115, i64 %n) ; 115 is 's' 221 ret ptr %call 222} 223 224define ptr @possibly_valid_data_after_array2(ptr %dst, i64 %n) { 225; CHECK-LABEL: @possibly_valid_data_after_array2( 226; CHECK-NEXT: [[CALL:%.*]] = call ptr @memccpy(ptr [[DST:%.*]], ptr nonnull @hello, i32 115, i64 [[N:%.*]]) 227; CHECK-NEXT: ret ptr [[CALL]] 228; 229 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 115, i64 %n) ; 115 is 's' 230 ret ptr %call 231} 232 233define ptr @possibly_valid_data_after_array3(ptr %dst) { 234; CHECK-LABEL: @possibly_valid_data_after_array3( 235; CHECK-NEXT: [[CALL:%.*]] = call ptr @memccpy(ptr [[DST:%.*]], ptr nonnull @hello, i32 115, i64 12) 236; CHECK-NEXT: ret ptr [[CALL]] 237; 238 %call = call ptr @memccpy(ptr %dst, ptr @hello, i32 115, i64 12) ; 115 is 's' 239 ret ptr %call 240} 241 242define ptr @memccpy_dst_src_same_retval_used(ptr %dst, i32 %c, i64 %n) { 243; CHECK-LABEL: @memccpy_dst_src_same_retval_used( 244; CHECK-NEXT: [[CALL:%.*]] = call ptr @memccpy(ptr [[DST:%.*]], ptr [[DST]], i32 [[C:%.*]], i64 [[N:%.*]]) 245; CHECK-NEXT: ret ptr [[CALL]] 246; 247 %call = call ptr @memccpy(ptr %dst, ptr %dst, i32 %c, i64 %n) 248 ret ptr %call 249} 250 251define ptr @memccpy_to_memcpy_musttail(ptr %dst, ptr %x, i32 %y, i64 %z) { 252; CHECK-LABEL: @memccpy_to_memcpy_musttail( 253; CHECK-NEXT: [[CALL:%.*]] = musttail call ptr @memccpy(ptr [[DST:%.*]], ptr nonnull @hello, i32 114, i64 12) 254; CHECK-NEXT: ret ptr [[CALL]] 255; 256 %call = musttail call ptr @memccpy(ptr %dst, ptr @hello, i32 114, i64 12) ; 114 is 'r' 257 ret ptr %call 258} 259 260define ptr @memccpy_to_memcpy2_musttail(ptr %dst, ptr %x, i32 %y, i64 %z) { 261; CHECK-LABEL: @memccpy_to_memcpy2_musttail( 262; CHECK-NEXT: [[CALL:%.*]] = musttail call ptr @memccpy(ptr [[DST:%.*]], ptr nonnull @hello, i32 114, i64 8) 263; CHECK-NEXT: ret ptr [[CALL]] 264; 265 %call = musttail call ptr @memccpy(ptr %dst, ptr @hello, i32 114, i64 8) ; 114 is 'r' 266 ret ptr %call 267} 268 269