xref: /llvm-project/llvm/test/Transforms/MemCpyOpt/form-memset.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=memcpyopt -S -verify-memoryssa | FileCheck %s
3
4; All the stores in this example should be merged into a single memset.
5
6target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
7target triple = "i386-apple-darwin8"
8
9define void @test1(i8 signext  %c) nounwind  {
10; CHECK-LABEL: @test1(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    [[X:%.*]] = alloca [19 x i8], align 1
13; CHECK-NEXT:    [[TMP:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 0
14; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 1
15; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 2
16; CHECK-NEXT:    [[TMP13:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 3
17; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 4
18; CHECK-NEXT:    [[TMP21:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 5
19; CHECK-NEXT:    [[TMP25:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 6
20; CHECK-NEXT:    [[TMP29:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 7
21; CHECK-NEXT:    [[TMP33:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 8
22; CHECK-NEXT:    [[TMP37:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 9
23; CHECK-NEXT:    [[TMP41:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 10
24; CHECK-NEXT:    [[TMP45:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 11
25; CHECK-NEXT:    [[TMP49:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 12
26; CHECK-NEXT:    [[TMP53:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 13
27; CHECK-NEXT:    [[TMP57:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 14
28; CHECK-NEXT:    [[TMP61:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 15
29; CHECK-NEXT:    [[TMP65:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 16
30; CHECK-NEXT:    [[TMP69:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 17
31; CHECK-NEXT:    [[TMP73:%.*]] = getelementptr [19 x i8], ptr [[X]], i32 0, i32 18
32; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP]], i8 [[C:%.*]], i64 19, i1 false)
33; CHECK-NEXT:    [[TMP76:%.*]] = call i32 (...) @bar(ptr [[X]]) #[[ATTR0:[0-9]+]]
34; CHECK-NEXT:    ret void
35;
36entry:
37  %x = alloca [19 x i8]		; <ptr> [#uses=20]
38  %tmp = getelementptr [19 x i8], ptr %x, i32 0, i32 0		; <ptr> [#uses=1]
39  store i8 %c, ptr %tmp, align 1
40  %tmp5 = getelementptr [19 x i8], ptr %x, i32 0, i32 1		; <ptr> [#uses=1]
41  store i8 %c, ptr %tmp5, align 1
42  %tmp9 = getelementptr [19 x i8], ptr %x, i32 0, i32 2		; <ptr> [#uses=1]
43  store i8 %c, ptr %tmp9, align 1
44  %tmp13 = getelementptr [19 x i8], ptr %x, i32 0, i32 3		; <ptr> [#uses=1]
45  store i8 %c, ptr %tmp13, align 1
46  %tmp17 = getelementptr [19 x i8], ptr %x, i32 0, i32 4		; <ptr> [#uses=1]
47  store i8 %c, ptr %tmp17, align 1
48  %tmp21 = getelementptr [19 x i8], ptr %x, i32 0, i32 5		; <ptr> [#uses=1]
49  store i8 %c, ptr %tmp21, align 1
50  %tmp25 = getelementptr [19 x i8], ptr %x, i32 0, i32 6		; <ptr> [#uses=1]
51  store i8 %c, ptr %tmp25, align 1
52  %tmp29 = getelementptr [19 x i8], ptr %x, i32 0, i32 7		; <ptr> [#uses=1]
53  store i8 %c, ptr %tmp29, align 1
54  %tmp33 = getelementptr [19 x i8], ptr %x, i32 0, i32 8		; <ptr> [#uses=1]
55  store i8 %c, ptr %tmp33, align 1
56  %tmp37 = getelementptr [19 x i8], ptr %x, i32 0, i32 9		; <ptr> [#uses=1]
57  store i8 %c, ptr %tmp37, align 1
58  %tmp41 = getelementptr [19 x i8], ptr %x, i32 0, i32 10		; <ptr> [#uses=1]
59  store i8 %c, ptr %tmp41, align 1
60  %tmp45 = getelementptr [19 x i8], ptr %x, i32 0, i32 11		; <ptr> [#uses=1]
61  store i8 %c, ptr %tmp45, align 1
62  %tmp49 = getelementptr [19 x i8], ptr %x, i32 0, i32 12		; <ptr> [#uses=1]
63  store i8 %c, ptr %tmp49, align 1
64  %tmp53 = getelementptr [19 x i8], ptr %x, i32 0, i32 13		; <ptr> [#uses=1]
65  store i8 %c, ptr %tmp53, align 1
66  %tmp57 = getelementptr [19 x i8], ptr %x, i32 0, i32 14		; <ptr> [#uses=1]
67  store i8 %c, ptr %tmp57, align 1
68  %tmp61 = getelementptr [19 x i8], ptr %x, i32 0, i32 15		; <ptr> [#uses=1]
69  store i8 %c, ptr %tmp61, align 1
70  %tmp65 = getelementptr [19 x i8], ptr %x, i32 0, i32 16		; <ptr> [#uses=1]
71  store i8 %c, ptr %tmp65, align 1
72  %tmp69 = getelementptr [19 x i8], ptr %x, i32 0, i32 17		; <ptr> [#uses=1]
73  store i8 %c, ptr %tmp69, align 1
74  %tmp73 = getelementptr [19 x i8], ptr %x, i32 0, i32 18		; <ptr> [#uses=1]
75  store i8 %c, ptr %tmp73, align 1
76  %tmp76 = call i32 (...) @bar( ptr %x ) nounwind
77  ret void
78}
79
80declare i32 @bar(...)
81
82%struct.MV = type { i16, i16 }
83
84
85define void @test2() nounwind  {
86; CHECK-LABEL: @test2(
87; CHECK-NEXT:  entry:
88; CHECK-NEXT:    [[REF_IDX:%.*]] = alloca [8 x i8], align 1
89; CHECK-NEXT:    [[LEFT_MVD:%.*]] = alloca [8 x %struct.MV], align 8
90; CHECK-NEXT:    [[UP_MVD:%.*]] = alloca [8 x %struct.MV], align 8
91; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr [8 x i8], ptr [[REF_IDX]], i32 0, i32 7
92; CHECK-NEXT:    [[TMP23:%.*]] = getelementptr [8 x i8], ptr [[REF_IDX]], i32 0, i32 6
93; CHECK-NEXT:    [[TMP26:%.*]] = getelementptr [8 x i8], ptr [[REF_IDX]], i32 0, i32 5
94; CHECK-NEXT:    [[TMP29:%.*]] = getelementptr [8 x i8], ptr [[REF_IDX]], i32 0, i32 4
95; CHECK-NEXT:    [[TMP32:%.*]] = getelementptr [8 x i8], ptr [[REF_IDX]], i32 0, i32 3
96; CHECK-NEXT:    [[TMP35:%.*]] = getelementptr [8 x i8], ptr [[REF_IDX]], i32 0, i32 2
97; CHECK-NEXT:    [[TMP38:%.*]] = getelementptr [8 x i8], ptr [[REF_IDX]], i32 0, i32 1
98; CHECK-NEXT:    [[TMP41:%.*]] = getelementptr [8 x i8], ptr [[REF_IDX]], i32 0, i32 0
99; CHECK-NEXT:    [[TMP43:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 7, i32 0
100; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP41]], i8 -1, i64 8, i1 false)
101; CHECK-NEXT:    [[TMP46:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 7, i32 1
102; CHECK-NEXT:    [[TMP57:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 6, i32 0
103; CHECK-NEXT:    [[TMP60:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 6, i32 1
104; CHECK-NEXT:    [[TMP71:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 5, i32 0
105; CHECK-NEXT:    [[TMP74:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 5, i32 1
106; CHECK-NEXT:    [[TMP85:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 4, i32 0
107; CHECK-NEXT:    [[TMP88:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 4, i32 1
108; CHECK-NEXT:    [[TMP99:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 3, i32 0
109; CHECK-NEXT:    [[TMP102:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 3, i32 1
110; CHECK-NEXT:    [[TMP113:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 2, i32 0
111; CHECK-NEXT:    [[TMP116:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 2, i32 1
112; CHECK-NEXT:    [[TMP127:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 1, i32 0
113; CHECK-NEXT:    [[TMP130:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 1, i32 1
114; CHECK-NEXT:    [[TMP141:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 0, i32 0
115; CHECK-NEXT:    [[TMP144:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 0, i32 1
116; CHECK-NEXT:    [[TMP148:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 7, i32 0
117; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[TMP141]], i8 0, i64 32, i1 false)
118; CHECK-NEXT:    [[TMP151:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 7, i32 1
119; CHECK-NEXT:    [[TMP162:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 6, i32 0
120; CHECK-NEXT:    [[TMP165:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 6, i32 1
121; CHECK-NEXT:    [[TMP176:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 5, i32 0
122; CHECK-NEXT:    [[TMP179:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 5, i32 1
123; CHECK-NEXT:    [[TMP190:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 4, i32 0
124; CHECK-NEXT:    [[TMP193:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 4, i32 1
125; CHECK-NEXT:    [[TMP204:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 3, i32 0
126; CHECK-NEXT:    [[TMP207:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 3, i32 1
127; CHECK-NEXT:    [[TMP218:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 2, i32 0
128; CHECK-NEXT:    [[TMP221:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 2, i32 1
129; CHECK-NEXT:    [[TMP232:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 1, i32 0
130; CHECK-NEXT:    [[TMP235:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 1, i32 1
131; CHECK-NEXT:    [[TMP246:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 0, i32 0
132; CHECK-NEXT:    [[TMP249:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 0, i32 1
133; CHECK-NEXT:    [[UP_MVD252:%.*]] = getelementptr [8 x %struct.MV], ptr [[UP_MVD]], i32 0, i32 0
134; CHECK-NEXT:    [[LEFT_MVD253:%.*]] = getelementptr [8 x %struct.MV], ptr [[LEFT_MVD]], i32 0, i32 0
135; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[TMP246]], i8 0, i64 32, i1 false)
136; CHECK-NEXT:    call void @foo(ptr [[UP_MVD252]], ptr [[LEFT_MVD253]], ptr [[TMP41]]) #[[ATTR0]]
137; CHECK-NEXT:    ret void
138;
139entry:
140  %ref_idx = alloca [8 x i8]		; <ptr> [#uses=8]
141  %left_mvd = alloca [8 x %struct.MV]		; <ptr> [#uses=17]
142  %up_mvd = alloca [8 x %struct.MV]		; <ptr> [#uses=17]
143  %tmp20 = getelementptr [8 x i8], ptr %ref_idx, i32 0, i32 7		; <ptr> [#uses=1]
144  store i8 -1, ptr %tmp20, align 1
145  %tmp23 = getelementptr [8 x i8], ptr %ref_idx, i32 0, i32 6		; <ptr> [#uses=1]
146  store i8 -1, ptr %tmp23, align 1
147  %tmp26 = getelementptr [8 x i8], ptr %ref_idx, i32 0, i32 5		; <ptr> [#uses=1]
148  store i8 -1, ptr %tmp26, align 1
149  %tmp29 = getelementptr [8 x i8], ptr %ref_idx, i32 0, i32 4		; <ptr> [#uses=1]
150  store i8 -1, ptr %tmp29, align 1
151  %tmp32 = getelementptr [8 x i8], ptr %ref_idx, i32 0, i32 3		; <ptr> [#uses=1]
152  store i8 -1, ptr %tmp32, align 1
153  %tmp35 = getelementptr [8 x i8], ptr %ref_idx, i32 0, i32 2		; <ptr> [#uses=1]
154  store i8 -1, ptr %tmp35, align 1
155  %tmp38 = getelementptr [8 x i8], ptr %ref_idx, i32 0, i32 1		; <ptr> [#uses=1]
156  store i8 -1, ptr %tmp38, align 1
157  %tmp41 = getelementptr [8 x i8], ptr %ref_idx, i32 0, i32 0		; <ptr> [#uses=2]
158  store i8 -1, ptr %tmp41, align 1
159  %tmp43 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 7, i32 0		; <ptr> [#uses=1]
160  store i16 0, ptr %tmp43, align 2
161  %tmp46 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 7, i32 1		; <ptr> [#uses=1]
162  store i16 0, ptr %tmp46, align 2
163  %tmp57 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 6, i32 0		; <ptr> [#uses=1]
164  store i16 0, ptr %tmp57, align 2
165  %tmp60 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 6, i32 1		; <ptr> [#uses=1]
166  store i16 0, ptr %tmp60, align 2
167  %tmp71 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 5, i32 0		; <ptr> [#uses=1]
168  store i16 0, ptr %tmp71, align 2
169  %tmp74 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 5, i32 1		; <ptr> [#uses=1]
170  store i16 0, ptr %tmp74, align 2
171  %tmp85 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 4, i32 0		; <ptr> [#uses=1]
172  store i16 0, ptr %tmp85, align 2
173  %tmp88 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 4, i32 1		; <ptr> [#uses=1]
174  store i16 0, ptr %tmp88, align 2
175  %tmp99 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 3, i32 0		; <ptr> [#uses=1]
176  store i16 0, ptr %tmp99, align 2
177  %tmp102 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 3, i32 1		; <ptr> [#uses=1]
178  store i16 0, ptr %tmp102, align 2
179  %tmp113 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 2, i32 0		; <ptr> [#uses=1]
180  store i16 0, ptr %tmp113, align 2
181  %tmp116 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 2, i32 1		; <ptr> [#uses=1]
182  store i16 0, ptr %tmp116, align 2
183  %tmp127 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 1, i32 0		; <ptr> [#uses=1]
184  store i16 0, ptr %tmp127, align 2
185  %tmp130 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 1, i32 1		; <ptr> [#uses=1]
186  store i16 0, ptr %tmp130, align 2
187  %tmp141 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 0, i32 0		; <ptr> [#uses=1]
188  store i16 0, ptr %tmp141, align 8
189  %tmp144 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 0, i32 1		; <ptr> [#uses=1]
190  store i16 0, ptr %tmp144, align 2
191  %tmp148 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 7, i32 0		; <ptr> [#uses=1]
192  store i16 0, ptr %tmp148, align 2
193  %tmp151 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 7, i32 1		; <ptr> [#uses=1]
194  store i16 0, ptr %tmp151, align 2
195  %tmp162 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 6, i32 0		; <ptr> [#uses=1]
196  store i16 0, ptr %tmp162, align 2
197  %tmp165 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 6, i32 1		; <ptr> [#uses=1]
198  store i16 0, ptr %tmp165, align 2
199  %tmp176 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 5, i32 0		; <ptr> [#uses=1]
200  store i16 0, ptr %tmp176, align 2
201  %tmp179 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 5, i32 1		; <ptr> [#uses=1]
202  store i16 0, ptr %tmp179, align 2
203  %tmp190 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 4, i32 0		; <ptr> [#uses=1]
204  store i16 0, ptr %tmp190, align 2
205  %tmp193 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 4, i32 1		; <ptr> [#uses=1]
206  store i16 0, ptr %tmp193, align 2
207  %tmp204 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 3, i32 0		; <ptr> [#uses=1]
208  store i16 0, ptr %tmp204, align 2
209  %tmp207 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 3, i32 1		; <ptr> [#uses=1]
210  store i16 0, ptr %tmp207, align 2
211  %tmp218 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 2, i32 0		; <ptr> [#uses=1]
212  store i16 0, ptr %tmp218, align 2
213  %tmp221 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 2, i32 1		; <ptr> [#uses=1]
214  store i16 0, ptr %tmp221, align 2
215  %tmp232 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 1, i32 0		; <ptr> [#uses=1]
216  store i16 0, ptr %tmp232, align 2
217  %tmp235 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 1, i32 1		; <ptr> [#uses=1]
218  store i16 0, ptr %tmp235, align 2
219  %tmp246 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 0, i32 0		; <ptr> [#uses=1]
220  store i16 0, ptr %tmp246, align 8
221  %tmp249 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 0, i32 1		; <ptr> [#uses=1]
222  store i16 0, ptr %tmp249, align 2
223  %up_mvd252 = getelementptr [8 x %struct.MV], ptr %up_mvd, i32 0, i32 0		; <ptr> [#uses=1]
224  %left_mvd253 = getelementptr [8 x %struct.MV], ptr %left_mvd, i32 0, i32 0		; <ptr> [#uses=1]
225  call void @foo( ptr %up_mvd252, ptr %left_mvd253, ptr %tmp41 ) nounwind
226  ret void
227
228}
229
230declare void @foo(ptr, ptr, ptr)
231
232
233; Store followed by memset.
234define void @test3(ptr nocapture %P) nounwind ssp {
235; CHECK-LABEL: @test3(
236; CHECK-NEXT:  entry:
237; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
238; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 2
239; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[ARRAYIDX]], i8 0, i64 15, i1 false)
240; CHECK-NEXT:    ret void
241;
242entry:
243  %arrayidx = getelementptr inbounds i32, ptr %P, i64 1
244  store i32 0, ptr %arrayidx, align 4
245  %add.ptr = getelementptr inbounds i32, ptr %P, i64 2
246  tail call void @llvm.memset.p0.i64(ptr %add.ptr, i8 0, i64 11, i1 false)
247  ret void
248}
249
250; store followed by memset, different offset scenario
251define void @test4(ptr nocapture %P) nounwind ssp {
252; CHECK-LABEL: @test4(
253; CHECK-NEXT:  entry:
254; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
255; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[P]], i8 0, i64 15, i1 false)
256; CHECK-NEXT:    ret void
257;
258entry:
259  store i32 0, ptr %P, align 4
260  %add.ptr = getelementptr inbounds i32, ptr %P, i64 1
261  tail call void @llvm.memset.p0.i64(ptr %add.ptr, i8 0, i64 11, i1 false)
262  ret void
263}
264
265declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
266
267; Memset followed by store.
268define void @test5(ptr nocapture %P) nounwind ssp {
269; CHECK-LABEL: @test5(
270; CHECK-NEXT:  entry:
271; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 2
272; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 1
273; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[ARRAYIDX]], i8 0, i64 15, i1 false)
274; CHECK-NEXT:    ret void
275;
276entry:
277  %add.ptr = getelementptr inbounds i32, ptr %P, i64 2
278  tail call void @llvm.memset.p0.i64(ptr %add.ptr, i8 0, i64 11, i1 false)
279  %arrayidx = getelementptr inbounds i32, ptr %P, i64 1
280  store i32 0, ptr %arrayidx, align 4
281  ret void
282}
283
284;; Memset followed by memset.
285define void @test6(ptr nocapture %P) nounwind ssp {
286; CHECK-LABEL: @test6(
287; CHECK-NEXT:  entry:
288; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 3
289; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[P]], i8 0, i64 24, i1 false)
290; CHECK-NEXT:    ret void
291;
292entry:
293  tail call void @llvm.memset.p0.i64(ptr %P, i8 0, i64 12, i1 false)
294  %add.ptr = getelementptr inbounds i32, ptr %P, i64 3
295  tail call void @llvm.memset.p0.i64(ptr %add.ptr, i8 0, i64 12, i1 false)
296  ret void
297}
298
299; More aggressive heuristic
300; rdar://9892684
301define void @test7(ptr nocapture %c) nounwind optsize {
302; CHECK-LABEL: @test7(
303; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[C:%.*]], i32 1
304; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[C]], i32 2
305; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[C]], i32 3
306; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[C]], i32 4
307; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[C]], i8 -1, i64 20, i1 false)
308; CHECK-NEXT:    ret void
309;
310  store i32 -1, ptr %c, align 4
311  %1 = getelementptr inbounds i32, ptr %c, i32 1
312  store i32 -1, ptr %1, align 4
313  %2 = getelementptr inbounds i32, ptr %c, i32 2
314  store i32 -1, ptr %2, align 4
315  %3 = getelementptr inbounds i32, ptr %c, i32 3
316  store i32 -1, ptr %3, align 4
317  %4 = getelementptr inbounds i32, ptr %c, i32 4
318  store i32 -1, ptr %4, align 4
319  ret void
320}
321
322%struct.test8 = type { [4 x i32] }
323
324define void @test8() {
325; CHECK-LABEL: @test8(
326; CHECK-NEXT:  entry:
327; CHECK-NEXT:    [[MEMTMP:%.*]] = alloca [[STRUCT_TEST8:%.*]], align 16
328; CHECK-NEXT:    store <4 x i32> splat (i32 -1), ptr [[MEMTMP]], align 16
329; CHECK-NEXT:    ret void
330;
331entry:
332  %memtmp = alloca %struct.test8, align 16
333  store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, ptr %memtmp, align 16
334  ret void
335}
336
337@test9buf = internal unnamed_addr global [16 x i64] zeroinitializer, align 16
338
339define void @test9() nounwind {
340; CHECK-LABEL: @test9(
341; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 16 @test9buf, i8 -1, i64 16, i1 false)
342; CHECK-NEXT:    ret void
343;
344  store i8 -1, ptr @test9buf, align 16
345  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 1), align 1
346  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 2), align 2
347  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 3), align 1
348  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 4), align 4
349  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 5), align 1
350  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 6), align 2
351  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 7), align 1
352  store i8 -1, ptr getelementptr inbounds ([16 x i64], ptr @test9buf, i64 0, i64 1), align 8
353  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 9), align 1
354  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 10), align 2
355  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 11), align 1
356  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 12), align 4
357  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 13), align 1
358  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 14), align 2
359  store i8 -1, ptr getelementptr (i8, ptr @test9buf, i64 15), align 1
360  ret void
361}
362
363; PR19092
364define void @test10(ptr nocapture %P) nounwind {
365; CHECK-LABEL: @test10(
366; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 0, i64 42, i1 false)
367; CHECK-NEXT:    ret void
368;
369  tail call void @llvm.memset.p0.i64(ptr %P, i8 0, i64 42, i1 false)
370  tail call void @llvm.memset.p0.i64(ptr %P, i8 0, i64 23, i1 false)
371  ret void
372}
373
374; Memset followed by odd store.
375define void @test11(ptr nocapture %P) nounwind ssp {
376; CHECK-LABEL: @test11(
377; CHECK-NEXT:  entry:
378; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 3
379; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[P]], i8 1, i64 23, i1 false)
380; CHECK-NEXT:    ret void
381;
382entry:
383  %add.ptr = getelementptr inbounds i32, ptr %P, i64 3
384  tail call void @llvm.memset.p0.i64(ptr %add.ptr, i8 1, i64 11, i1 false)
385  store i96 310698676526526814092329217, ptr %P, align 4
386  ret void
387}
388
389; Alignment should be preserved when there is a store with default align
390define void @test12(ptr nocapture %P) nounwind ssp {
391; CHECK-LABEL: @test12(
392; CHECK-NEXT:  entry:
393; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
394; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[P]], i8 0, i64 15, i1 false)
395; CHECK-NEXT:    ret void
396;
397entry:
398  store i32 0, ptr %P
399  %add.ptr = getelementptr inbounds i32, ptr %P, i64 1
400  tail call void @llvm.memset.p0.i64(ptr %add.ptr, i8 0, i64 11, i1 false)
401  ret void
402}
403