1 ; RUN: llc -march=x86-64 -mcpu=corei7 < %s | FileCheck %s
3 target 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"
4 target triple = "x86_64-apple-macosx10.8.0"
6 %struct.A = type { i8, i8, i8, i8, i8, i8, i8, i8 }
8 @a = common global [10000 x %struct.A] zeroinitializer, align 8
10 ; Move all of the constants using a single vector store.
11 ; CHECK: merge_const_store
14 define 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
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
44 ; Move the first 4 constants as a single vector. Move the rest as scalars.
45 ; CHECK: merge_nonconst_store
52 define 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
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
89 define void @merge_loads(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
94 %2 = getelementptr inbounds %struct.A* %q, i64 0, i32 0
95 %3 = getelementptr inbounds %struct.A* %q, i64 0, i32 1
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
112 ._crit_edge: ; preds = %4, %0
116 ; The loads and the stores are interleved. Can't merge them.
117 ;CHECK: no_merge_loads
123 define 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
128 %2 = getelementptr inbounds %struct.A* %q, i64 0, i32 0
129 %3 = getelementptr inbounds %struct.A* %q, i64 0, i32 1
132 a4: ; 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
146 ._crit_edge: ; preds = %4, %0