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