1
- // skip-filecheck
2
1
// unit-test: ScalarReplacementOfAggregates
3
2
// compile-flags: -Cpanic=abort
4
3
// no-prefer-dynamic
@@ -13,28 +12,68 @@ impl Drop for Tag {
13
12
fn drop ( & mut self ) { }
14
13
}
15
14
15
+ /// Check that SROA excludes structs with a `Drop` implementation.
16
16
pub fn dropping ( ) {
17
+ // CHECK-LABEL: fn dropping(
18
+
19
+ // CHECK: [[aggregate:_[0-9]+]]: S;
20
+
21
+ // CHECK: bb0: {
22
+ // CHECK: [[aggregate]] = S
17
23
S ( Tag ( 0 ) , Tag ( 1 ) , Tag ( 2 ) ) . 1 ;
18
24
}
19
25
26
+ /// Check that SROA excludes enums.
20
27
pub fn enums ( a : usize ) -> usize {
28
+ // CHECK-LABEL: fn enums(
29
+
30
+ // CHECK: [[enum:_[0-9]+]]: std::option::Option<usize>;
31
+
32
+ // CHECK: bb0: {
33
+ // CHECK: [[enum]] = Option::<usize>::Some
34
+ // CHECK: _5 = (([[enum]] as Some).0: usize)
35
+ // CHECK: _0 = _5
21
36
if let Some ( a) = Some ( a) { a } else { 0 }
22
37
}
23
38
39
+ /// Check that SROA destructures `U`.
24
40
pub fn structs ( a : f32 ) -> f32 {
41
+ // CHECK-LABEL: fn structs(
25
42
struct U {
26
43
_foo : usize ,
27
44
a : f32 ,
28
45
}
29
-
46
+ // CHECK: [[ret:_0]]: f32;
47
+ // CHECK: [[struct:_[0-9]+]]: structs::U;
48
+ // CHECK: [[a_tmp:_[0-9]+]]: f32;
49
+ // CHECK: [[foo:_[0-9]+]]: usize;
50
+ // CHECK: [[a_ret:_[0-9]+]]: f32;
51
+
52
+ // CHECK: bb0: {
53
+ // CHECK-NOT: [[struct]]
54
+ // CHECK: [[a_tmp]] = _1;
55
+ // CHECK-NOT: [[struct]]
56
+ // CHECK: [[foo]] = const 0_usize;
57
+ // CHECK-NOT: [[struct]]
58
+ // CHECK: [[a_ret]] = move [[a_tmp]];
59
+ // CHECK-NOT: [[struct]]
60
+ // CHECK: _0 = [[a_ret]];
61
+ // CHECK-NOT: [[struct]]
30
62
U { _foo : 0 , a } . a
31
63
}
32
64
65
+ /// Check that SROA excludes unions.
33
66
pub fn unions ( a : f32 ) -> u32 {
67
+ // CHECK-LABEL: fn unions(
34
68
union Repr {
35
69
f : f32 ,
36
70
u : u32 ,
37
71
}
72
+ // CHECK: [[union:_[0-9]+]]: unions::Repr;
73
+
74
+ // CHECK: bb0: {
75
+ // CHECK: [[union]] = Repr {
76
+ // CHECK: _0 = ([[union]].1: u32)
38
77
unsafe { Repr { f : a } . u }
39
78
}
40
79
@@ -46,11 +85,21 @@ struct Foo {
46
85
d : Option < isize > ,
47
86
}
48
87
49
- fn g ( ) -> u32 {
50
- 3
51
- }
52
-
88
+ /// Check that non-escaping uses of a struct are destructured.
53
89
pub fn flat ( ) {
90
+ // CHECK-LABEL: fn flat(
91
+
92
+ // CHECK: [[struct:_[0-9]+]]: Foo;
93
+
94
+ // CHECK: bb0: {
95
+ // CHECK: [[init_unit:_[0-9]+]] = ();
96
+ // CHECK: [[init_opt_isize:_[0-9]+]] = Option::<isize>::Some
97
+
98
+ // CHECK: [[destr_five:_[0-9]+]] = const 5_u8;
99
+ // CHECK: [[destr_unit:_[0-9]+]] = move [[init_unit]];
100
+ // CHECK: [[destr_a:_[0-9]+]] = const "a";
101
+ // CHECK: [[destr_opt_isize:_[0-9]+]] = move [[init_opt_isize]];
102
+
54
103
let Foo { a, b, c, d } = Foo { a : 5 , b : ( ) , c : "a" , d : Some ( -4 ) } ;
55
104
let _ = a;
56
105
let _ = b;
@@ -65,6 +114,10 @@ struct Escaping {
65
114
c : u32 ,
66
115
}
67
116
117
+ fn g ( ) -> u32 {
118
+ 3
119
+ }
120
+
68
121
fn f ( a : * const u32 ) {
69
122
println ! ( "{}" , unsafe { * a. add( 2 ) } ) ;
70
123
}
@@ -76,31 +129,91 @@ fn f(a: *const u32) {
76
129
// of them to `f`. However, this would lead to a miscompilation because `b` and `c`
77
130
// might no longer appear right after `a` in memory.
78
131
pub fn escaping ( ) {
132
+ // CHECK-LABEL: fn escaping(
133
+
134
+ // CHECK: [[ptr:_[0-9]+]]: *const u32;
135
+ // CHECK: [[ref:_[0-9]+]]: &u32;
136
+ // CHECK: [[struct:_[0-9]+]]: Escaping;
137
+ // CHECK: [[a:_[0-9]+]]: u32;
138
+
139
+ // CHECK: bb0: {
140
+ // CHECK: [[struct]] = Escaping {
141
+ // CHECK: [[ref]] = &([[struct]].0
142
+ // CHECK: [[ptr]] = &raw const (*[[ref]]);
79
143
f ( & Escaping { a : 1 , b : 2 , c : g ( ) } . a ) ;
80
144
}
81
145
146
+ /// Check that copies from an internal struct are destructured and reassigned to
147
+ /// the original struct.
82
148
fn copies ( x : Foo ) {
149
+ // CHECK-LABEL: fn copies(
150
+
151
+ // CHECK: [[external:_[0-9]+]]: Foo) ->
152
+ // CHECK: [[internal:_[0-9]+]]: Foo;
153
+ // CHECK: [[byte:_[0-9]+]]: u8;
154
+ // CHECK: [[unit:_[0-9]+]]: ();
155
+ // CHECK: [[str:_[0-9]+]]: &str;
156
+ // CHECK: [[opt_isize:_[0-9]+]]: std::option::Option<isize>;
157
+
158
+ // CHECK: bb0: {
159
+ // CHECK: [[byte]] = ([[external]].0
160
+ // CHECK: [[unit]] = ([[external]].1
161
+ // CHECK: [[str]] = ([[external]].2
162
+ // CHECK: [[opt_isize]] = ([[external]].3
163
+
83
164
let y = x;
84
165
let t = y. a ;
85
166
let u = y. c ;
86
167
let z = y;
87
168
let a = z. b ;
88
169
}
89
170
171
+ /// Check that copies from an internal struct are destructured and reassigned to
172
+ /// the original struct.
90
173
fn ref_copies ( x : & Foo ) {
174
+ // CHECK-LABEL: fn ref_copies(
175
+
176
+ // CHECK: [[external:_[0-9]+]]: &Foo) ->
177
+ // CHECK: [[internal:_[0-9]+]]: Foo;
178
+ // CHECK: [[byte:_[0-9]+]]: u8;
179
+ // CHECK: [[unit:_[0-9]+]]: ();
180
+ // CHECK: [[str:_[0-9]+]]: &str;
181
+ // CHECK: [[opt_isize:_[0-9]+]]: std::option::Option<isize>;
182
+
183
+ // CHECK: bb0: {
184
+ // CHECK: [[byte]] = ((*[[external]]).0
185
+ // CHECK: [[unit]] = ((*[[external]]).1
186
+ // CHECK: [[str]] = ((*[[external]]).2
187
+ // CHECK: [[opt_isize]] = ((*[[external]]).3
188
+
91
189
let y = * x;
92
190
let t = y. a ;
93
191
let u = y. c ;
94
192
}
95
193
194
+ /// Check that deaggregated assignments from constants are placed after the constant's
195
+ /// assignment. Also check that copying field accesses from the copy of the constant are
196
+ /// reassigned to copy from the constant.
96
197
fn constant ( ) {
198
+ // CHECK-LABEL: constant(
199
+
200
+ // CHECK: [[constant:_[0-9]+]]: (usize, u8);
201
+ // CHECK: [[t:_[0-9]+]]: usize;
202
+ // CHECK: [[u:_[0-9]+]]: u8;
203
+
204
+ // CHECK: bb0: {
205
+ // CHECK-NOT: [[constant]]
206
+ // CHECK: [[constant]] = const
207
+ // CHECK: [[t]] = move ([[constant]].0: usize)
208
+ // CHECK: [[u]] = move ([[constant]].1: u8)
97
209
const U : ( usize , u8 ) = ( 5 , 9 ) ;
98
210
let y = U ;
99
211
let t = y. 0 ;
100
212
let u = y. 1 ;
101
213
}
102
214
103
215
fn main ( ) {
216
+ // CHECK-LABEL: fn main(
104
217
dropping ( ) ;
105
218
enums ( 5 ) ;
106
219
structs ( 5. ) ;
0 commit comments