OLD | NEW |
1 ; RUN: opt %s -expand-struct-regs -S | FileCheck %s | 1 ; RUN: opt %s -expand-struct-regs -S | FileCheck %s |
2 ; RUN: opt %s -expand-struct-regs -S | FileCheck %s -check-prefix=CLEANUP | 2 ; RUN: opt %s -expand-struct-regs -S | FileCheck %s -check-prefix=CLEANUP |
3 | 3 |
4 ; These two instructions should not appear in the output: | 4 ; These two instructions should not appear in the output: |
5 ; CLEANUP-NOT: extractvalue | 5 ; CLEANUP-NOT: extractvalue |
6 ; CLEANUP-NOT: insertvalue | 6 ; CLEANUP-NOT: insertvalue |
7 | 7 |
8 target datalayout = "p:32:32:32" | 8 target datalayout = "p:32:32:32" |
9 | 9 |
10 %struct = type { i8, i32 } | 10 %struct = type { i8, i32 } |
11 | 11 |
12 | 12 |
13 define void @struct_load(%struct* %p, i8* %out0, i32* %out1) { | 13 define void @struct_load(%struct* %p, i8* %out0, i32* %out1) { |
14 %val = load %struct* %p | 14 %val = load %struct, %struct* %p |
15 %field0 = extractvalue %struct %val, 0 | 15 %field0 = extractvalue %struct %val, 0 |
16 %field1 = extractvalue %struct %val, 1 | 16 %field1 = extractvalue %struct %val, 1 |
17 store i8 %field0, i8* %out0 | 17 store i8 %field0, i8* %out0 |
18 store i32 %field1, i32* %out1 | 18 store i32 %field1, i32* %out1 |
19 ret void | 19 ret void |
20 } | 20 } |
21 ; CHECK: define void @struct_load | 21 ; CHECK: define void @struct_load |
22 ; CHECK-NEXT: %val.index{{.*}} = getelementptr %struct* %p, i32 0, i32 0 | 22 ; CHECK-NEXT: %val.index{{.*}} = getelementptr %struct, %struct* %p, i32 0, i32
0 |
23 ; CHECK-NEXT: %val.field{{.*}} = load i8* %val.index{{.*}} | 23 ; CHECK-NEXT: %val.field{{.*}} = load i8, i8* %val.index{{.*}} |
24 ; CHECK-NEXT: %val.index{{.*}} = getelementptr %struct* %p, i32 0, i32 1 | 24 ; CHECK-NEXT: %val.index{{.*}} = getelementptr %struct, %struct* %p, i32 0, i32
1 |
25 ; CHECK-NEXT: %val.field{{.*}} = load i32* %val.index{{.*}} | 25 ; CHECK-NEXT: %val.field{{.*}} = load i32, i32* %val.index{{.*}} |
26 ; CHECK-NEXT: store i8 %val.field{{.*}}, i8* %out0 | 26 ; CHECK-NEXT: store i8 %val.field{{.*}}, i8* %out0 |
27 ; CHECK-NEXT: store i32 %val.field{{.*}}, i32* %out1 | 27 ; CHECK-NEXT: store i32 %val.field{{.*}}, i32* %out1 |
28 | 28 |
29 | 29 |
30 define void @struct_store(%struct* %in_ptr, %struct* %out_ptr) { | 30 define void @struct_store(%struct* %in_ptr, %struct* %out_ptr) { |
31 %val = load %struct* %in_ptr | 31 %val = load %struct, %struct* %in_ptr |
32 store %struct %val, %struct* %out_ptr | 32 store %struct %val, %struct* %out_ptr |
33 ret void | 33 ret void |
34 } | 34 } |
35 ; CHECK: define void @struct_store | 35 ; CHECK: define void @struct_store |
36 ; CHECK-NEXT: %val.index{{.*}} = getelementptr %struct* %in_ptr, i32 0, i32 0 | 36 ; CHECK-NEXT: %val.index{{.*}} = getelementptr %struct, %struct* %in_ptr, i32 0,
i32 0 |
37 ; CHECK-NEXT: %val.field{{.*}} = load i8* %val.index{{.*}} | 37 ; CHECK-NEXT: %val.field{{.*}} = load i8, i8* %val.index{{.*}} |
38 ; CHECK-NEXT: %val.index{{.*}} = getelementptr %struct* %in_ptr, i32 0, i32 1 | 38 ; CHECK-NEXT: %val.index{{.*}} = getelementptr %struct, %struct* %in_ptr, i32 0,
i32 1 |
39 ; CHECK-NEXT: %val.field{{.*}} = load i32* %val.index{{.*}} | 39 ; CHECK-NEXT: %val.field{{.*}} = load i32, i32* %val.index{{.*}} |
40 ; CHECK-NEXT: %out_ptr.index{{.*}} = getelementptr %struct* %out_ptr, i32 0, i32
0 | 40 ; CHECK-NEXT: %out_ptr.index{{.*}} = getelementptr %struct, %struct* %out_ptr, i
32 0, i32 0 |
41 ; CHECK-NEXT: store i8 %val.field{{.*}}, i8* %out_ptr.index{{.*}} | 41 ; CHECK-NEXT: store i8 %val.field{{.*}}, i8* %out_ptr.index{{.*}} |
42 ; CHECK-NEXT: %out_ptr.index{{.*}} = getelementptr %struct* %out_ptr, i32 0, i32
1 | 42 ; CHECK-NEXT: %out_ptr.index{{.*}} = getelementptr %struct, %struct* %out_ptr, i
32 0, i32 1 |
43 ; CHECK-NEXT: store i32 %val.field{{.*}}, i32* %out_ptr.index{{.*}} | 43 ; CHECK-NEXT: store i32 %val.field{{.*}}, i32* %out_ptr.index{{.*}} |
44 | 44 |
45 | 45 |
46 ; Ensure that the pass works correctly across basic blocks. | 46 ; Ensure that the pass works correctly across basic blocks. |
47 define void @across_basic_block(%struct* %in_ptr, %struct* %out_ptr) { | 47 define void @across_basic_block(%struct* %in_ptr, %struct* %out_ptr) { |
48 %val = load %struct* %in_ptr | 48 %val = load %struct, %struct* %in_ptr |
49 br label %bb | 49 br label %bb |
50 bb: | 50 bb: |
51 store %struct %val, %struct* %out_ptr | 51 store %struct %val, %struct* %out_ptr |
52 ret void | 52 ret void |
53 } | 53 } |
54 ; CHECK: define void @across_basic_block | 54 ; CHECK: define void @across_basic_block |
55 ; CHECK: load | 55 ; CHECK: load |
56 ; CHECK: load | 56 ; CHECK: load |
57 ; CHECK: bb: | 57 ; CHECK: bb: |
58 ; CHECK: store | 58 ; CHECK: store |
59 ; CHECK: store | 59 ; CHECK: store |
60 | 60 |
61 | 61 |
62 define void @const_struct_store(%struct* %ptr) { | 62 define void @const_struct_store(%struct* %ptr) { |
63 store %struct { i8 99, i32 1234 }, %struct* %ptr | 63 store %struct { i8 99, i32 1234 }, %struct* %ptr |
64 ret void | 64 ret void |
65 } | 65 } |
66 ; CHECK: define void @const_struct_store | 66 ; CHECK: define void @const_struct_store |
67 ; CHECK: store i8 99 | 67 ; CHECK: store i8 99 |
68 ; CHECK: store i32 1234 | 68 ; CHECK: store i32 1234 |
69 | 69 |
70 | 70 |
71 define void @struct_phi_node(%struct* %ptr) { | 71 define void @struct_phi_node(%struct* %ptr) { |
72 entry: | 72 entry: |
73 %val = load %struct* %ptr | 73 %val = load %struct, %struct* %ptr |
74 br label %bb | 74 br label %bb |
75 bb: | 75 bb: |
76 %phi = phi %struct [ %val, %entry ] | 76 %phi = phi %struct [ %val, %entry ] |
77 ret void | 77 ret void |
78 } | 78 } |
79 ; CHECK: bb: | 79 ; CHECK: bb: |
80 ; CHECK-NEXT: %phi.index{{.*}} = phi i8 [ %val.field{{.*}}, %entry ] | 80 ; CHECK-NEXT: %phi.index{{.*}} = phi i8 [ %val.field{{.*}}, %entry ] |
81 ; CHECK-NEXT: %phi.index{{.*}} = phi i32 [ %val.field{{.*}}, %entry ] | 81 ; CHECK-NEXT: %phi.index{{.*}} = phi i32 [ %val.field{{.*}}, %entry ] |
82 | 82 |
83 | 83 |
84 define void @struct_phi_node_multiple_entry(i1 %arg, %struct* %ptr) { | 84 define void @struct_phi_node_multiple_entry(i1 %arg, %struct* %ptr) { |
85 entry: | 85 entry: |
86 %val = load %struct* %ptr | 86 %val = load %struct, %struct* %ptr |
87 br i1 %arg, label %bb, label %bb | 87 br i1 %arg, label %bb, label %bb |
88 bb: | 88 bb: |
89 %phi = phi %struct [ %val, %entry ], [ %val, %entry ] | 89 %phi = phi %struct [ %val, %entry ], [ %val, %entry ] |
90 ret void | 90 ret void |
91 } | 91 } |
92 ; CHECK: bb: | 92 ; CHECK: bb: |
93 ; CHECK-NEXT: %phi.index{{.*}} = phi i8 [ %val.field{{.*}}, %entry ], [ %val.fie
ld{{.*}}, %entry ] | 93 ; CHECK-NEXT: %phi.index{{.*}} = phi i8 [ %val.field{{.*}}, %entry ], [ %val.fie
ld{{.*}}, %entry ] |
94 ; CHECK-NEXT: %phi.index{{.*}} = phi i32 [ %val.field{{.*}}, %entry ], [ %val.fi
eld{{.*}}, %entry ] | 94 ; CHECK-NEXT: %phi.index{{.*}} = phi i32 [ %val.field{{.*}}, %entry ], [ %val.fi
eld{{.*}}, %entry ] |
95 | 95 |
96 | 96 |
97 define void @struct_select_inst(i1 %cond, %struct* %ptr1, %struct* %ptr2) { | 97 define void @struct_select_inst(i1 %cond, %struct* %ptr1, %struct* %ptr2) { |
98 %val1 = load %struct* %ptr1 | 98 %val1 = load %struct, %struct* %ptr1 |
99 %val2 = load %struct* %ptr2 | 99 %val2 = load %struct, %struct* %ptr2 |
100 %select = select i1 %cond, %struct %val1, %struct %val2 | 100 %select = select i1 %cond, %struct %val1, %struct %val2 |
101 ret void | 101 ret void |
102 } | 102 } |
103 ; CHECK: define void @struct_select_inst | 103 ; CHECK: define void @struct_select_inst |
104 ; CHECK: %select.index{{.*}} = select i1 %cond, i8 %val1.field{{.*}}, i8 %val2.f
ield{{.*}} | 104 ; CHECK: %select.index{{.*}} = select i1 %cond, i8 %val1.field{{.*}}, i8 %val2.f
ield{{.*}} |
105 ; CHECK-NEXT: %select.index{{.*}} = select i1 %cond, i32 %val1.field{{.*}}, i32
%val2.field{{.*}} | 105 ; CHECK-NEXT: %select.index{{.*}} = select i1 %cond, i32 %val1.field{{.*}}, i32
%val2.field{{.*}} |
106 | 106 |
107 | 107 |
108 define void @insert_and_extract(i8* %out0, i32* %out1) { | 108 define void @insert_and_extract(i8* %out0, i32* %out1) { |
109 %temp = insertvalue %struct undef, i8 100, 0 | 109 %temp = insertvalue %struct undef, i8 100, 0 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 store i32 %g, i32* %a2 | 144 store i32 %g, i32* %a2 |
145 store { { i32, i64 } } %h, { { i32, i64 } }* %a3 | 145 store { { i32, i64 } } %h, { { i32, i64 } }* %a3 |
146 ret void | 146 ret void |
147 } | 147 } |
148 ; CHECK-LABEL: define void @nested_structs() | 148 ; CHECK-LABEL: define void @nested_structs() |
149 ; CHECK-NEXT: %a1 = alloca i64 | 149 ; CHECK-NEXT: %a1 = alloca i64 |
150 ; CHECK-NEXT: %a2 = alloca i32 | 150 ; CHECK-NEXT: %a2 = alloca i32 |
151 ; CHECK-NEXT: %a3 = alloca { { i32, i64 } } | 151 ; CHECK-NEXT: %a3 = alloca { { i32, i64 } } |
152 ; CHECK-NEXT: store i64 6, i64* %a1 | 152 ; CHECK-NEXT: store i64 6, i64* %a1 |
153 ; CHECK-NEXT: store i32 5, i32* %a2 | 153 ; CHECK-NEXT: store i32 5, i32* %a2 |
154 ; CHECK-NEXT: %a3.index = getelementptr { { i32, i64 } }* %a3, i32 0, i32 0 | 154 ; CHECK-NEXT: %a3.index = getelementptr { { i32, i64 } }, { { i32, i64 } }* %
a3, i32 0, i32 0 |
155 ; CHECK-NEXT: %a3.index.index = getelementptr { i32, i64 }* %a3.index, i32 0,
i32 0 | 155 ; CHECK-NEXT: %a3.index.index = getelementptr { i32, i64 }, { i32, i64 }* %a3
.index, i32 0, i32 0 |
156 ; CHECK-NEXT: store i32 5, i32* %a3.index.index | 156 ; CHECK-NEXT: store i32 5, i32* %a3.index.index |
157 ; CHECK-NEXT: %a3.index.index1 = getelementptr { i32, i64 }* %a3.index, i32 0
, i32 1 | 157 ; CHECK-NEXT: %a3.index.index1 = getelementptr { i32, i64 }, { i32, i64 }* %a
3.index, i32 0, i32 1 |
158 ; CHECK-NEXT: store i64 6, i64* %a3.index.index1 | 158 ; CHECK-NEXT: store i64 6, i64* %a3.index.index1 |
159 | 159 |
160 define void @load_another_pass() { | 160 define void @load_another_pass() { |
161 %a = alloca { { i8, i64 } } | 161 %a = alloca { { i8, i64 } } |
162 %b = load { { i8, i64 } }* %a | 162 %b = load { { i8, i64 } }, { { i8, i64 } }* %a |
163 %c = load { { i8, i64 } }* %a, align 16 | 163 %c = load { { i8, i64 } }, { { i8, i64 } }* %a, align 16 |
164 ret void | 164 ret void |
165 } | 165 } |
166 ; CHECK-LABEL: define void @load_another_pass() | 166 ; CHECK-LABEL: define void @load_another_pass() |
167 ; CHECK: %b.field.field = load i8* %b.field.index | 167 ; CHECK: %b.field.field = load i8, i8* %b.field.index |
168 ; CHECK: %b.field.field{{.*}} = load i64* %b.field.index{{.*}} | 168 ; CHECK: %b.field.field{{.*}} = load i64, i64* %b.field.index{{.*}} |
169 ; CHECK: %c.field.field = load i8* %c.field.index, align 16 | 169 ; CHECK: %c.field.field = load i8, i8* %c.field.index, align 16 |
170 ; CHECK: %c.field.field{{.*}} = load i64* %c.field.index{{.*}}, align 4 | 170 ; CHECK: %c.field.field{{.*}} = load i64, i64* %c.field.index{{.*}}, ali
gn 4 |
171 | 171 |
172 define void @store_another_pass() { | 172 define void @store_another_pass() { |
173 %a = alloca { { i16, i64 } } | 173 %a = alloca { { i16, i64 } } |
174 store { { i16, i64 } } undef, { { i16, i64 } }* %a | 174 store { { i16, i64 } } undef, { { i16, i64 } }* %a |
175 store { { i16, i64 } } undef, { { i16, i64 } }* %a, align 16 | 175 store { { i16, i64 } } undef, { { i16, i64 } }* %a, align 16 |
176 ret void | 176 ret void |
177 } | 177 } |
178 ; CHECK-LABEL: define void @store_another_pass() | 178 ; CHECK-LABEL: define void @store_another_pass() |
179 ; CHECK: store i16 undef, i16* %a.index.index | 179 ; CHECK: store i16 undef, i16* %a.index.index |
180 ; CHECK: store i64 undef, i64* %a.index.index{{.*}} | 180 ; CHECK: store i64 undef, i64* %a.index.index{{.*}} |
181 ; CHECK: store i16 undef, i16* %a.index1.index, align 16 | 181 ; CHECK: store i16 undef, i16* %a.index1.index, align 16 |
182 ; CHECK: store i64 undef, i64* %a.index1.index{{.*}}, align 4 | 182 ; CHECK: store i64 undef, i64* %a.index1.index{{.*}}, align 4 |
183 | 183 |
184 define void @select_another_pass() { | 184 define void @select_another_pass() { |
185 %a = load { { i8, i64 } }* null | 185 %a = load { { i8, i64 } }, { { i8, i64 } }* null |
186 %b = load { { i8, i64 } }* null | 186 %b = load { { i8, i64 } }, { { i8, i64 } }* null |
187 %c = select i1 undef, { { i8, i64 } } %a, { { i8, i64 } } %b | 187 %c = select i1 undef, { { i8, i64 } } %a, { { i8, i64 } } %b |
188 store { { i8, i64 } } %c, { { i8, i64 } }* null | 188 store { { i8, i64 } } %c, { { i8, i64 } }* null |
189 ret void | 189 ret void |
190 } | 190 } |
191 ; CHECK-LABEL: define void @select_another_pass() | 191 ; CHECK-LABEL: define void @select_another_pass() |
192 ; CHECK-NEXT: %a.index = getelementptr { { i8, i64 } }* null, i32 0, i32 0 | 192 ; CHECK-NEXT: %a.index = getelementptr { { i8, i64 } }, { { i8, i64 } }* null
, i32 0, i32 0 |
193 ; CHECK-NEXT: %a.field.index = getelementptr { i8, i64 }* %a.index, i32 0, i3
2 0 | 193 ; CHECK-NEXT: %a.field.index = getelementptr { i8, i64 }, { i8, i64 }* %a.ind
ex, i32 0, i32 0 |
194 ; CHECK-NEXT: %a.field.field = load i8* %a.field.index | 194 ; CHECK-NEXT: %a.field.field = load i8, i8* %a.field.index |
195 ; CHECK-NEXT: %a.field.index2 = getelementptr { i8, i64 }* %a.index, i32 0, i
32 1 | 195 ; CHECK-NEXT: %a.field.index2 = getelementptr { i8, i64 }, { i8, i64 }* %a.in
dex, i32 0, i32 1 |
196 ; CHECK-NEXT: %a.field.field3 = load i64* %a.field.index2 | 196 ; CHECK-NEXT: %a.field.field3 = load i64, i64* %a.field.index2 |
197 ; CHECK-NEXT: %b.index = getelementptr { { i8, i64 } }* null, i32 0, i32 0 | 197 ; CHECK-NEXT: %b.index = getelementptr { { i8, i64 } }, { { i8, i64 } }* null
, i32 0, i32 0 |
198 ; CHECK-NEXT: %b.field.index = getelementptr { i8, i64 }* %b.index, i32 0, i3
2 0 | 198 ; CHECK-NEXT: %b.field.index = getelementptr { i8, i64 }, { i8, i64 }* %b.ind
ex, i32 0, i32 0 |
199 ; CHECK-NEXT: %b.field.field = load i8* %b.field.index | 199 ; CHECK-NEXT: %b.field.field = load i8, i8* %b.field.index |
200 ; CHECK-NEXT: %b.field.index5 = getelementptr { i8, i64 }* %b.index, i32 0, i
32 1 | 200 ; CHECK-NEXT: %b.field.index5 = getelementptr { i8, i64 }, { i8, i64 }* %b.in
dex, i32 0, i32 1 |
201 ; CHECK-NEXT: %b.field.field6 = load i64* %b.field.index5 | 201 ; CHECK-NEXT: %b.field.field6 = load i64, i64* %b.field.index5 |
202 ; CHECK-NEXT: %c.index.index = select i1 undef, i8 %a.field.field, i8 %b.fiel
d.field | 202 ; CHECK-NEXT: %c.index.index = select i1 undef, i8 %a.field.field, i8 %b.fiel
d.field |
203 ; CHECK-NEXT: %c.index.index11 = select i1 undef, i64 %a.field.field3, i64 %b
.field.field6 | 203 ; CHECK-NEXT: %c.index.index11 = select i1 undef, i64 %a.field.field3, i64 %b
.field.field6 |
204 ; CHECK-NEXT: %.index = getelementptr { { i8, i64 } }* null, i32 0, i32 0 | 204 ; CHECK-NEXT: %.index = getelementptr { { i8, i64 } }, { { i8, i64 } }* null,
i32 0, i32 0 |
205 ; CHECK-NEXT: %.index.index = getelementptr { i8, i64 }* %.index, i32 0, i32
0 | 205 ; CHECK-NEXT: %.index.index = getelementptr { i8, i64 }, { i8, i64 }* %.index
, i32 0, i32 0 |
206 ; CHECK-NEXT: store i8 %c.index.index, i8* %.index.index | 206 ; CHECK-NEXT: store i8 %c.index.index, i8* %.index.index |
207 ; CHECK-NEXT: %.index.index13 = getelementptr { i8, i64 }* %.index, i32 0, i3
2 1 | 207 ; CHECK-NEXT: %.index.index13 = getelementptr { i8, i64 }, { i8, i64 }* %.ind
ex, i32 0, i32 1 |
208 ; CHECK-NEXT: store i64 %c.index.index11, i64* %.index.index13 | 208 ; CHECK-NEXT: store i64 %c.index.index11, i64* %.index.index13 |
209 ; CHECK-NEXT: ret void | 209 ; CHECK-NEXT: ret void |
210 | 210 |
211 define void @phi_another_pass() { | 211 define void @phi_another_pass() { |
212 entry: | 212 entry: |
213 br i1 false, label %next, label %not_next | 213 br i1 false, label %next, label %not_next |
214 | 214 |
215 not_next: | 215 not_next: |
216 %a = alloca { { i64, i16 }, i8* } | 216 %a = alloca { { i64, i16 }, i8* } |
217 %b = load { { i64, i16 }, i8* }* %a | 217 %b = load { { i64, i16 }, i8* }, { { i64, i16 }, i8* }* %a |
218 br label %next | 218 br label %next |
219 | 219 |
220 next: | 220 next: |
221 %c = phi { { i64, i16 }, i8* } [ undef, %entry ], [ %b, %not_next ] | 221 %c = phi { { i64, i16 }, i8* } [ undef, %entry ], [ %b, %not_next ] |
222 store { { i64, i16 }, i8* } %c, { { i64, i16 }, i8* }* null | 222 store { { i64, i16 }, i8* } %c, { { i64, i16 }, i8* }* null |
223 ret void | 223 ret void |
224 } | 224 } |
225 ; CHECK-LABEL: define void @phi_another_pass() | 225 ; CHECK-LABEL: define void @phi_another_pass() |
226 ; CHECK: %c.index.index = phi i64 [ undef, %entry ], [ %b.field.field, %
not_next ] | 226 ; CHECK: %c.index.index = phi i64 [ undef, %entry ], [ %b.field.field, %
not_next ] |
227 ; CHECK: %c.index.index{{.*}} = phi i16 [ undef, %entry ], [ %b.field.fi
eld{{.*}}, %not_next ] | 227 ; CHECK: %c.index.index{{.*}} = phi i16 [ undef, %entry ], [ %b.field.fi
eld{{.*}}, %not_next ] |
228 ; CHECK: %c.index{{.*}} = phi i8* [ undef, %entry ], [ %b.field{{.*}}, %
not_next ] | 228 ; CHECK: %c.index{{.*}} = phi i8* [ undef, %entry ], [ %b.field{{.*}}, %
not_next ] |
OLD | NEW |