1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -instcombine -S < %s | FileCheck %s 3 4declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) 5declare i8* @memcpy(i8* nocapture, i8* nocapture, i64) 6declare i8* @memmove(i8* nocapture, i8* nocapture, i64) 7declare i8* @memset(i8* nocapture, i8, i64) 8declare i8* @memchr(i8* nocapture, i32, i64) 9declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) 10declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) 11declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) 12 13define i32 @memcmp_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { 14; CHECK-LABEL: @memcmp_const_size_set_deref( 15; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(16) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) 16; CHECK-NEXT: ret i32 [[CALL]] 17; 18 %call = tail call i32 @memcmp(i8* %d, i8* %s, i64 16) 19 ret i32 %call 20} 21 22define i32 @memcmp_const_size_update_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { 23; CHECK-LABEL: @memcmp_const_size_update_deref( 24; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(16) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) 25; CHECK-NEXT: ret i32 [[CALL]] 26; 27 %call = tail call i32 @memcmp(i8* dereferenceable(4) %d, i8* dereferenceable(8) %s, i64 16) 28 ret i32 %call 29} 30 31define i32 @memcmp_const_size_update_deref2(i8* nocapture readonly %d, i8* nocapture readonly %s) { 32; CHECK-LABEL: @memcmp_const_size_update_deref2( 33; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(16) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) 34; CHECK-NEXT: ret i32 [[CALL]] 35; 36 %call = tail call i32 @memcmp(i8* %d, i8* dereferenceable_or_null(8) %s, i64 16) 37 ret i32 %call 38} 39 40define i32 @memcmp_const_size_update_deref3(i8* nocapture readonly %d, i8* nocapture readonly %s) { 41; CHECK-LABEL: @memcmp_const_size_update_deref3( 42; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(40) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) 43; CHECK-NEXT: ret i32 [[CALL]] 44; 45 %call = tail call i32 @memcmp(i8* dereferenceable(40) %d, i8* %s, i64 16) 46 ret i32 %call 47} 48 49define i32 @memcmp_const_size_update_deref4(i8* nocapture readonly %d, i8* nocapture readonly %s) { 50; CHECK-LABEL: @memcmp_const_size_update_deref4( 51; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(16) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) 52; CHECK-NEXT: ret i32 [[CALL]] 53; 54 %call = tail call i32 @memcmp(i8* dereferenceable_or_null(16) %d, i8* %s, i64 16) 55 ret i32 %call 56} 57 58define i32 @memcmp_const_size_update_deref5(i8* nocapture readonly %d, i8* nocapture readonly %s) { 59; CHECK-LABEL: @memcmp_const_size_update_deref5( 60; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(40) [[D:%.*]], i8* nonnull dereferenceable(16) [[S:%.*]], i64 16) 61; CHECK-NEXT: ret i32 [[CALL]] 62; 63 %call = tail call i32 @memcmp(i8* dereferenceable_or_null(40) %d, i8* %s, i64 16) 64 ret i32 %call 65} 66 67define i32 @memcmp_const_size_update_deref6(i8* nocapture readonly %d, i8* nocapture readonly %s) null_pointer_is_valid { 68; CHECK-LABEL: @memcmp_const_size_update_deref6( 69; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(16) dereferenceable_or_null(40) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) 70; CHECK-NEXT: ret i32 [[CALL]] 71; 72 %call = tail call i32 @memcmp(i8* dereferenceable_or_null(40) %d, i8* %s, i64 16) 73 ret i32 %call 74} 75 76define i32 @memcmp_const_size_update_deref7(i8* nocapture readonly %d, i8* nocapture readonly %s) null_pointer_is_valid { 77; CHECK-LABEL: @memcmp_const_size_update_deref7( 78; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(40) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) 79; CHECK-NEXT: ret i32 [[CALL]] 80; 81 %call = tail call i32 @memcmp(i8* nonnull dereferenceable_or_null(40) %d, i8* %s, i64 16) 82 ret i32 %call 83} 84 85define i32 @memcmp_const_size_no_update_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { 86; CHECK-LABEL: @memcmp_const_size_no_update_deref( 87; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* nonnull dereferenceable(40) [[D:%.*]], i8* nonnull dereferenceable(20) [[S:%.*]], i64 16) 88; CHECK-NEXT: ret i32 [[CALL]] 89; 90 %call = tail call i32 @memcmp(i8* dereferenceable(40) %d, i8* dereferenceable(20) %s, i64 16) 91 ret i32 %call 92} 93 94define i32 @memcmp_nonconst_size(i8* nocapture readonly %d, i8* nocapture readonly %s, i64 %n) { 95; CHECK-LABEL: @memcmp_nonconst_size( 96; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @memcmp(i8* [[D:%.*]], i8* [[S:%.*]], i64 [[N:%.*]]) 97; CHECK-NEXT: ret i32 [[CALL]] 98; 99 %call = tail call i32 @memcmp(i8* %d, i8* %s, i64 %n) 100 ret i32 %call 101} 102 103define i8* @memcpy_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { 104; CHECK-LABEL: @memcpy_const_size_set_deref( 105; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(64) [[D:%.*]], i8* nonnull align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false) 106; CHECK-NEXT: ret i8* [[D]] 107; 108 %call = tail call i8* @memcpy(i8* %d, i8* %s, i64 64) 109 ret i8* %call 110} 111 112define i8* @memmove_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { 113; CHECK-LABEL: @memmove_const_size_set_deref( 114; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(64) [[D:%.*]], i8* nonnull align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false) 115; CHECK-NEXT: ret i8* [[D]] 116; 117 %call = tail call i8* @memmove(i8* %d, i8* %s, i64 64) 118 ret i8* %call 119} 120 121define i8* @memset_const_size_set_deref(i8* nocapture readonly %s, i8 %c) { 122; CHECK-LABEL: @memset_const_size_set_deref( 123; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 1 dereferenceable(64) [[S:%.*]], i8 [[C:%.*]], i64 64, i1 false) 124; CHECK-NEXT: ret i8* [[S]] 125; 126 %call = tail call i8* @memset(i8* %s, i8 %c, i64 64) 127 ret i8* %call 128} 129 130define i8* @memchr_const_size_set_deref(i8* nocapture readonly %s, i32 %c) { 131; CHECK-LABEL: @memchr_const_size_set_deref( 132; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @memchr(i8* nonnull dereferenceable(64) [[S:%.*]], i32 [[C:%.*]], i64 64) 133; CHECK-NEXT: ret i8* [[CALL]] 134; 135 %call = tail call i8* @memchr(i8* %s, i32 %c, i64 64) 136 ret i8* %call 137} 138 139define i8* @llvm_memcpy_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { 140; CHECK-LABEL: @llvm_memcpy_const_size_set_deref( 141; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[D:%.*]], i8* nonnull align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false) 142; CHECK-NEXT: ret i8* [[D]] 143; 144 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %d, i8* align 1 %s, i64 16, i1 false) 145 ret i8* %d 146} 147 148define i8* @llvm_memmove_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { 149; CHECK-LABEL: @llvm_memmove_const_size_set_deref( 150; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[D:%.*]], i8* nonnull align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false) 151; CHECK-NEXT: ret i8* [[D]] 152; 153 call void @llvm.memmove.p0i8.p0i8.i64(i8* align 1 %d, i8* align 1 %s, i64 16, i1 false) 154 ret i8* %d 155} 156define i8* @llvm_memset_const_size_set_deref(i8* nocapture readonly %s, i8 %c) { 157; CHECK-LABEL: @llvm_memset_const_size_set_deref( 158; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[S:%.*]], i8 [[C:%.*]], i64 16, i1 false) 159; CHECK-NEXT: ret i8* [[S]] 160; 161 call void @llvm.memset.p0i8.i64(i8* align 1 %s, i8 %c, i64 16, i1 false) 162 ret i8* %s 163} 164