Skip to content

Commit e30d304

Browse files
[MemCpyOpt] Introduce test for PR101930 (NFC)
1 parent 46446bb commit e30d304

File tree

1 file changed

+183
-0
lines changed

1 file changed

+183
-0
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -passes=memcpyopt -S %s -verify-memoryssa | FileCheck %s
3+
4+
; Redundant memmove.
5+
define i32 @redundant_memmove() {
6+
; CHECK-LABEL: @redundant_memmove(
7+
; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 16
8+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 104, i1 false)
9+
; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 4
10+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 100, i1 false)
11+
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY]], align 16
12+
; CHECK-NEXT: ret i32 [[VAL]]
13+
;
14+
%array = alloca [26 x i32], align 16
15+
call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 104, i1 false)
16+
%array.idx = getelementptr inbounds i8, ptr %array, i64 4
17+
call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 100, i1 false)
18+
%val = load i32, ptr %array, align 16
19+
ret i32 %val
20+
}
21+
22+
; Used memmove, buffer is reset to zero.
23+
define i32 @used_memmove_1() {
24+
; CHECK-LABEL: @used_memmove_1(
25+
; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 16
26+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 104, i1 false)
27+
; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 4
28+
; CHECK-NEXT: store i32 1, ptr [[ARRAY_IDX]], align 4
29+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 100, i1 false)
30+
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY_IDX]], align 4
31+
; CHECK-NEXT: ret i32 [[VAL]]
32+
;
33+
%array = alloca [26 x i32], align 16
34+
call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 104, i1 false)
35+
%array.idx = getelementptr inbounds i8, ptr %array, i64 4
36+
store i32 1, ptr %array.idx
37+
call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 100, i1 false)
38+
%val = load i32, ptr %array.idx, align 4
39+
ret i32 %val
40+
}
41+
42+
; Used memmove.
43+
define i32 @used_memmove_2() {
44+
; CHECK-LABEL: @used_memmove_2(
45+
; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 16
46+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 104, i1 false)
47+
; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 4
48+
; CHECK-NEXT: store i32 1, ptr [[ARRAY]], align 4
49+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 100, i1 false)
50+
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY_IDX]], align 4
51+
; CHECK-NEXT: ret i32 [[VAL]]
52+
;
53+
%array = alloca [26 x i32], align 16
54+
call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 104, i1 false)
55+
%array.idx = getelementptr inbounds i8, ptr %array, i64 4
56+
store i32 1, ptr %array
57+
call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 100, i1 false)
58+
%val = load i32, ptr %array.idx, align 4
59+
ret i32 %val
60+
}
61+
62+
; Used memmove, buffer clobbered by opaque.
63+
define i32 @used_memmove_3() {
64+
; CHECK-LABEL: @used_memmove_3(
65+
; CHECK-NEXT: [[ARRAY:%.*]] = alloca [25 x i32], align 16
66+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 100, i1 false)
67+
; CHECK-NEXT: call void @opaque(ptr [[ARRAY]])
68+
; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 4
69+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 96, i1 false)
70+
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY]], align 16
71+
; CHECK-NEXT: ret i32 [[VAL]]
72+
;
73+
%array = alloca [25 x i32], align 16
74+
call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 100, i1 false)
75+
call void @opaque(ptr %array)
76+
%array.idx = getelementptr inbounds i8, ptr %array, i64 4
77+
call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 96, i1 false)
78+
%val = load i32, ptr %array, align 16
79+
ret i32 %val
80+
}
81+
82+
; Redundant memmove, not within the same basic block.
83+
define i32 @redundant_memmove_different_bbs() {
84+
; CHECK-LABEL: @redundant_memmove_different_bbs(
85+
; CHECK-NEXT: entry:
86+
; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 16
87+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 104, i1 false)
88+
; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 4
89+
; CHECK-NEXT: br label [[USE:%.*]]
90+
; CHECK: use:
91+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 100, i1 false)
92+
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY]], align 16
93+
; CHECK-NEXT: ret i32 [[VAL]]
94+
;
95+
entry:
96+
%array = alloca [26 x i32], align 16
97+
call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 104, i1 false)
98+
%array.idx = getelementptr inbounds i8, ptr %array, i64 4
99+
br label %use
100+
101+
use: ; preds = %entry
102+
call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 100, i1 false)
103+
%val = load i32, ptr %array, align 16
104+
ret i32 %val
105+
}
106+
107+
@g_var = global [26 x i32] zeroinitializer, align 16
108+
109+
; Redundant memmove on a global variable.
110+
define ptr @redundant_memmove_memset_global_variable() {
111+
; CHECK-LABEL: @redundant_memmove_memset_global_variable(
112+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 @g_var, i8 0, i64 104, i1 false)
113+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 @g_var, ptr align 4 getelementptr inbounds nuw (i8, ptr @g_var, i64 4), i64 100, i1 false)
114+
; CHECK-NEXT: ret ptr @g_var
115+
;
116+
call void @llvm.memset.p0.i64(ptr align 16 @g_var, i8 0, i64 104, i1 false)
117+
call void @llvm.memmove.p0.p0.i64(ptr align 16 @g_var, ptr align 4 getelementptr inbounds nuw (i8, ptr @g_var, i64 4), i64 100, i1 false)
118+
ret ptr @g_var
119+
}
120+
121+
; Memset only partial.
122+
define i32 @partial_memset() {
123+
; CHECK-LABEL: @partial_memset(
124+
; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 16
125+
; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 92
126+
; CHECK-NEXT: store i32 1, ptr [[ARRAY_IDX]], align 4
127+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 26, i1 false)
128+
; CHECK-NEXT: [[ARRAY_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 4
129+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX_2]], i64 100, i1 false)
130+
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY_IDX]], align 4
131+
; CHECK-NEXT: ret i32 [[VAL]]
132+
;
133+
%array = alloca [26 x i32], align 16
134+
%array.idx = getelementptr inbounds i8, ptr %array, i64 92
135+
store i32 1, ptr %array.idx
136+
call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 26, i1 false)
137+
%array.idx.2 = getelementptr inbounds i8, ptr %array, i64 4
138+
call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx.2, i64 100, i1 false)
139+
%val = load i32, ptr %array.idx, align 4
140+
ret i32 %val
141+
}
142+
143+
; Memset length not constant.
144+
define i32 @memset_length_not_constant(i64 %size) {
145+
; CHECK-LABEL: @memset_length_not_constant(
146+
; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 16
147+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 [[SIZE:%.*]], i1 false)
148+
; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 4
149+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 100, i1 false)
150+
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY]], align 16
151+
; CHECK-NEXT: ret i32 [[VAL]]
152+
;
153+
%array = alloca [26 x i32], align 16
154+
call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 %size, i1 false)
155+
%array.idx = getelementptr inbounds i8, ptr %array, i64 4
156+
call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 100, i1 false)
157+
%val = load i32, ptr %array, align 16
158+
ret i32 %val
159+
}
160+
161+
; Memmove buffer not memset'd, different buffers.
162+
define i32 @memset_memmove_dest_buffers_not_alias() {
163+
; CHECK-LABEL: @memset_memmove_dest_buffers_not_alias(
164+
; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 16
165+
; CHECK-NEXT: [[ARRAY2:%.*]] = alloca [26 x i32], align 16
166+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 104, i1 false)
167+
; CHECK-NEXT: [[ARRAY2_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY2]], i64 4
168+
; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY2]], ptr align 4 [[ARRAY2_IDX]], i64 100, i1 false)
169+
; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY2]], align 16
170+
; CHECK-NEXT: ret i32 [[VAL]]
171+
;
172+
%array = alloca [26 x i32], align 16
173+
%array2 = alloca [26 x i32], align 16
174+
call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 104, i1 false)
175+
%array2.idx = getelementptr inbounds i8, ptr %array2, i64 4
176+
call void @llvm.memmove.p0.p0.i64(ptr align 16 %array2, ptr align 4 %array2.idx, i64 100, i1 false)
177+
%val = load i32, ptr %array2, align 16
178+
ret i32 %val
179+
}
180+
181+
declare void @opaque(ptr)
182+
declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1)
183+
declare void @llvm.memmove.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1)

0 commit comments

Comments
 (0)