blob: 79f8ee54a2a03b8aa22e1e8680c7aefa7120ec5e [file] [log] [blame]
Nadav Rotem7cbc12a2012-10-03 16:11:15 +00001; RUN: llc -march=x86-64 -mcpu=corei7 < %s | FileCheck %s
2
3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
4target triple = "x86_64-apple-macosx10.8.0"
5
6%struct.A = type { i8, i8, i8, i8, i8, i8, i8, i8 }
7%struct.B = type { i32, i32, i32, i32, i32, i32, i32, i32 }
8
9; Move all of the constants using a single vector store.
10; CHECK: merge_const_store
11; save 1,2,3 ... as one big integer.
12; CHECK: movabsq $578437695752307201
13; CHECK: ret
14define void @merge_const_store(i32 %count, %struct.A* nocapture %p) nounwind uwtable noinline ssp {
15 %1 = icmp sgt i32 %count, 0
16 br i1 %1, label %.lr.ph, label %._crit_edge
17.lr.ph:
18 %i.02 = phi i32 [ %10, %.lr.ph ], [ 0, %0 ]
19 %.01 = phi %struct.A* [ %11, %.lr.ph ], [ %p, %0 ]
20 %2 = getelementptr inbounds %struct.A* %.01, i64 0, i32 0
21 store i8 1, i8* %2, align 1
22 %3 = getelementptr inbounds %struct.A* %.01, i64 0, i32 1
23 store i8 2, i8* %3, align 1
24 %4 = getelementptr inbounds %struct.A* %.01, i64 0, i32 2
25 store i8 3, i8* %4, align 1
26 %5 = getelementptr inbounds %struct.A* %.01, i64 0, i32 3
27 store i8 4, i8* %5, align 1
28 %6 = getelementptr inbounds %struct.A* %.01, i64 0, i32 4
29 store i8 5, i8* %6, align 1
30 %7 = getelementptr inbounds %struct.A* %.01, i64 0, i32 5
31 store i8 6, i8* %7, align 1
32 %8 = getelementptr inbounds %struct.A* %.01, i64 0, i32 6
33 store i8 7, i8* %8, align 1
34 %9 = getelementptr inbounds %struct.A* %.01, i64 0, i32 7
35 store i8 8, i8* %9, align 1
36 %10 = add nsw i32 %i.02, 1
37 %11 = getelementptr inbounds %struct.A* %.01, i64 1
38 %exitcond = icmp eq i32 %10, %count
39 br i1 %exitcond, label %._crit_edge, label %.lr.ph
40._crit_edge:
41 ret void
42}
43
44; Move the first 4 constants as a single vector. Move the rest as scalars.
45; CHECK: merge_nonconst_store
46; CHECK: movl $67305985
47; CHECK: movb
48; CHECK: movb
49; CHECK: movb
50; CHECK: movb
51; CHECK: ret
52define void @merge_nonconst_store(i32 %count, i8 %zz, %struct.A* nocapture %p) nounwind uwtable noinline ssp {
53 %1 = icmp sgt i32 %count, 0
54 br i1 %1, label %.lr.ph, label %._crit_edge
55.lr.ph:
56 %i.02 = phi i32 [ %10, %.lr.ph ], [ 0, %0 ]
57 %.01 = phi %struct.A* [ %11, %.lr.ph ], [ %p, %0 ]
58 %2 = getelementptr inbounds %struct.A* %.01, i64 0, i32 0
59 store i8 1, i8* %2, align 1
60 %3 = getelementptr inbounds %struct.A* %.01, i64 0, i32 1
61 store i8 2, i8* %3, align 1
62 %4 = getelementptr inbounds %struct.A* %.01, i64 0, i32 2
63 store i8 3, i8* %4, align 1
64 %5 = getelementptr inbounds %struct.A* %.01, i64 0, i32 3
65 store i8 4, i8* %5, align 1
66 %6 = getelementptr inbounds %struct.A* %.01, i64 0, i32 4
67 store i8 %zz, i8* %6, align 1 ; <----------- Not a const;
68 %7 = getelementptr inbounds %struct.A* %.01, i64 0, i32 5
69 store i8 6, i8* %7, align 1
70 %8 = getelementptr inbounds %struct.A* %.01, i64 0, i32 6
71 store i8 7, i8* %8, align 1
72 %9 = getelementptr inbounds %struct.A* %.01, i64 0, i32 7
73 store i8 8, i8* %9, align 1
74 %10 = add nsw i32 %i.02, 1
75 %11 = getelementptr inbounds %struct.A* %.01, i64 1
76 %exitcond = icmp eq i32 %10, %count
77 br i1 %exitcond, label %._crit_edge, label %.lr.ph
78._crit_edge:
79 ret void
80}
81
82
83;CHECK: merge_loads_i16
84; load:
85;CHECK: movw
86; store:
87;CHECK: movw
88;CHECK: ret
89define void @merge_loads_i16(i32 %count, %struct.A* noalias nocapture %q, %struct.A* noalias nocapture %p) nounwind uwtable noinline ssp {
90 %1 = icmp sgt i32 %count, 0
91 br i1 %1, label %.lr.ph, label %._crit_edge
92
93.lr.ph: ; preds = %0
94 %2 = getelementptr inbounds %struct.A* %q, i64 0, i32 0
95 %3 = getelementptr inbounds %struct.A* %q, i64 0, i32 1
96 br label %4
97
98; <label>:4 ; preds = %4, %.lr.ph
99 %i.02 = phi i32 [ 0, %.lr.ph ], [ %9, %4 ]
100 %.01 = phi %struct.A* [ %p, %.lr.ph ], [ %10, %4 ]
101 %5 = load i8* %2, align 1
102 %6 = load i8* %3, align 1
103 %7 = getelementptr inbounds %struct.A* %.01, i64 0, i32 0
104 store i8 %5, i8* %7, align 1
105 %8 = getelementptr inbounds %struct.A* %.01, i64 0, i32 1
106 store i8 %6, i8* %8, align 1
107 %9 = add nsw i32 %i.02, 1
108 %10 = getelementptr inbounds %struct.A* %.01, i64 1
109 %exitcond = icmp eq i32 %9, %count
110 br i1 %exitcond, label %._crit_edge, label %4
111
112._crit_edge: ; preds = %4, %0
113 ret void
114}
115
116; The loads and the stores are interleved. Can't merge them.
117;CHECK: no_merge_loads
118;CHECK: movb
119;CHECK: movb
120;CHECK: movb
121;CHECK: movb
122;CHECK: ret
123define void @no_merge_loads(i32 %count, %struct.A* noalias nocapture %q, %struct.A* noalias nocapture %p) nounwind uwtable noinline ssp {
124 %1 = icmp sgt i32 %count, 0
125 br i1 %1, label %.lr.ph, label %._crit_edge
126
127.lr.ph: ; preds = %0
128 %2 = getelementptr inbounds %struct.A* %q, i64 0, i32 0
129 %3 = getelementptr inbounds %struct.A* %q, i64 0, i32 1
130 br label %a4
131
132a4: ; preds = %4, %.lr.ph
133 %i.02 = phi i32 [ 0, %.lr.ph ], [ %a9, %a4 ]
134 %.01 = phi %struct.A* [ %p, %.lr.ph ], [ %a10, %a4 ]
135 %a5 = load i8* %2, align 1
136 %a7 = getelementptr inbounds %struct.A* %.01, i64 0, i32 0
137 store i8 %a5, i8* %a7, align 1
138 %a8 = getelementptr inbounds %struct.A* %.01, i64 0, i32 1
139 %a6 = load i8* %3, align 1
140 store i8 %a6, i8* %a8, align 1
141 %a9 = add nsw i32 %i.02, 1
142 %a10 = getelementptr inbounds %struct.A* %.01, i64 1
143 %exitcond = icmp eq i32 %a9, %count
144 br i1 %exitcond, label %._crit_edge, label %a4
145
146._crit_edge: ; preds = %4, %0
147 ret void
148}
149
150
151;CHECK: merge_loads_integer
152; load:
153;CHECK: movq
154; store:
155;CHECK: movq
156;CHECK: ret
157define void @merge_loads_integer(i32 %count, %struct.B* noalias nocapture %q, %struct.B* noalias nocapture %p) nounwind uwtable noinline ssp {
158 %1 = icmp sgt i32 %count, 0
159 br i1 %1, label %.lr.ph, label %._crit_edge
160
161.lr.ph: ; preds = %0
162 %2 = getelementptr inbounds %struct.B* %q, i64 0, i32 0
163 %3 = getelementptr inbounds %struct.B* %q, i64 0, i32 1
164 br label %4
165
166; <label>:4 ; preds = %4, %.lr.ph
167 %i.02 = phi i32 [ 0, %.lr.ph ], [ %9, %4 ]
168 %.01 = phi %struct.B* [ %p, %.lr.ph ], [ %10, %4 ]
169 %5 = load i32* %2
170 %6 = load i32* %3
171 %7 = getelementptr inbounds %struct.B* %.01, i64 0, i32 0
172 store i32 %5, i32* %7
173 %8 = getelementptr inbounds %struct.B* %.01, i64 0, i32 1
174 store i32 %6, i32* %8
175 %9 = add nsw i32 %i.02, 1
176 %10 = getelementptr inbounds %struct.B* %.01, i64 1
177 %exitcond = icmp eq i32 %9, %count
178 br i1 %exitcond, label %._crit_edge, label %4
179
180._crit_edge: ; preds = %4, %0
181 ret void
182}
183
184
185;CHECK: merge_loads_vector
186; load:
187;CHECK: movups
188; store:
189;CHECK: movups
190;CHECK: ret
191define void @merge_loads_vector(i32 %count, %struct.B* noalias nocapture %q, %struct.B* noalias nocapture %p) nounwind uwtable noinline ssp {
192 %a1 = icmp sgt i32 %count, 0
193 br i1 %a1, label %.lr.ph, label %._crit_edge
194
195.lr.ph: ; preds = %0
196 %a2 = getelementptr inbounds %struct.B* %q, i64 0, i32 0
197 %a3 = getelementptr inbounds %struct.B* %q, i64 0, i32 1
198 %a4 = getelementptr inbounds %struct.B* %q, i64 0, i32 2
199 %a5 = getelementptr inbounds %struct.B* %q, i64 0, i32 3
200 br label %block4
201
202block4: ; preds = %4, %.lr.ph
203 %i.02 = phi i32 [ 0, %.lr.ph ], [ %c9, %block4 ]
204 %.01 = phi %struct.B* [ %p, %.lr.ph ], [ %c10, %block4 ]
205 %a7 = getelementptr inbounds %struct.B* %.01, i64 0, i32 0
206 %a8 = getelementptr inbounds %struct.B* %.01, i64 0, i32 1
207 %a9 = getelementptr inbounds %struct.B* %.01, i64 0, i32 2
208 %a10 = getelementptr inbounds %struct.B* %.01, i64 0, i32 3
209 %b1 = load i32* %a2
210 %b2 = load i32* %a3
211 %b3 = load i32* %a4
212 %b4 = load i32* %a5
213 store i32 %b1, i32* %a7
214 store i32 %b2, i32* %a8
215 store i32 %b3, i32* %a9
216 store i32 %b4, i32* %a10
217 %c9 = add nsw i32 %i.02, 1
218 %c10 = getelementptr inbounds %struct.B* %.01, i64 1
219 %exitcond = icmp eq i32 %c9, %count
220 br i1 %exitcond, label %._crit_edge, label %block4
221
222._crit_edge: ; preds = %4, %0
223 ret void
224}
225
226
227;CHECK: merge_loads_no_align
228; load:
229;CHECK: movl
230;CHECK: movl
231;CHECK: movl
232;CHECK: movl
233; store:
234;CHECK: movl
235;CHECK: movl
236;CHECK: movl
237;CHECK: movl
238;CHECK: ret
239define void @merge_loads_no_align(i32 %count, %struct.B* noalias nocapture %q, %struct.B* noalias nocapture %p) nounwind uwtable noinline ssp {
240 %a1 = icmp sgt i32 %count, 0
241 br i1 %a1, label %.lr.ph, label %._crit_edge
242
243.lr.ph: ; preds = %0
244 %a2 = getelementptr inbounds %struct.B* %q, i64 0, i32 0
245 %a3 = getelementptr inbounds %struct.B* %q, i64 0, i32 1
246 %a4 = getelementptr inbounds %struct.B* %q, i64 0, i32 2
247 %a5 = getelementptr inbounds %struct.B* %q, i64 0, i32 3
248 br label %block4
249
250block4: ; preds = %4, %.lr.ph
251 %i.02 = phi i32 [ 0, %.lr.ph ], [ %c9, %block4 ]
252 %.01 = phi %struct.B* [ %p, %.lr.ph ], [ %c10, %block4 ]
253 %a7 = getelementptr inbounds %struct.B* %.01, i64 0, i32 0
254 %a8 = getelementptr inbounds %struct.B* %.01, i64 0, i32 1
255 %a9 = getelementptr inbounds %struct.B* %.01, i64 0, i32 2
256 %a10 = getelementptr inbounds %struct.B* %.01, i64 0, i32 3
257 %b1 = load i32* %a2, align 1
258 %b2 = load i32* %a3, align 1
259 %b3 = load i32* %a4, align 1
260 %b4 = load i32* %a5, align 1
261 store i32 %b1, i32* %a7, align 1
262 store i32 %b2, i32* %a8, align 1
263 store i32 %b3, i32* %a9, align 1
264 store i32 %b4, i32* %a10, align 1
265 %c9 = add nsw i32 %i.02, 1
266 %c10 = getelementptr inbounds %struct.B* %.01, i64 1
267 %exitcond = icmp eq i32 %c9, %count
268 br i1 %exitcond, label %._crit_edge, label %block4
269
270._crit_edge: ; preds = %4, %0
271 ret void
272}
273