@@ -12,7 +12,7 @@ use rustc_middle::mir::visit::{
12
12
} ;
13
13
use rustc_middle:: mir:: { self , Location , TerminatorKind } ;
14
14
use rustc_middle:: ty;
15
- use rustc_middle:: ty:: layout:: HasTyCtxt ;
15
+ use rustc_middle:: ty:: layout:: { HasTyCtxt , TyAndLayout } ;
16
16
use rustc_target:: abi:: LayoutOf ;
17
17
18
18
pub fn non_ssa_locals < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
@@ -27,18 +27,8 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
27
27
let ty = fx. monomorphize ( & decl. ty ) ;
28
28
debug ! ( "local {:?} has type `{}`" , local, ty) ;
29
29
let layout = fx. cx . spanned_layout_of ( ty, decl. source_info . span ) ;
30
- if fx. cx . is_backend_immediate ( layout) {
31
- // These sorts of types are immediates that we can store
32
- // in an Value without an alloca.
33
- } else if fx. cx . is_backend_scalar_pair ( layout) {
34
- // We allow pairs and uses of any of their 2 fields.
35
- } else {
36
- // These sorts of types require an alloca. Note that
37
- // is_llvm_immediate() may *still* be true, particularly
38
- // for newtypes, but we currently force some types
39
- // (e.g., structs) into an alloca unconditionally, just so
40
- // that we don't have to deal with having two pathways
41
- // (gep vs extractvalue etc).
30
+
31
+ if ty_requires_alloca ( & analyzer. fx , layout) {
42
32
analyzer. not_ssa ( local) ;
43
33
}
44
34
}
@@ -132,7 +122,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
132
122
133
123
if let mir:: ProjectionElem :: Field ( ..) = elem {
134
124
let layout = cx. spanned_layout_of ( base_ty. ty , span) ;
135
- if cx . is_backend_immediate ( layout ) || cx . is_backend_scalar_pair ( layout) {
125
+ if self . ty_requires_alloca ( layout) {
136
126
// Recurse with the same context, instead of `Projection`,
137
127
// potentially stopping at non-operand projections,
138
128
// which would trigger `not_ssa` on locals.
@@ -446,3 +436,14 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
446
436
debug ! ( "cleanup_kinds: result={:?}" , result) ;
447
437
result
448
438
}
439
+
440
+ /// Returns `true` if locals of this type need to be allocated on the stack.
441
+ fn ty_requires_alloca < ' a , ' tcx > (
442
+ fx : & FunctionCx < ' a , ' tcx , impl BuilderMethods < ' a , ' tcx > > ,
443
+ ty : TyAndLayout < ' tcx > ,
444
+ ) -> bool {
445
+ // Currently, this returns `true` for ADTs that are otherwise small enough to qualify. For
446
+ // example, `struct Newtype(i32)`. This way, every type has a single way to extract data
447
+ // (gep, extractvalue, etc.).
448
+ !fx. cx . is_backend_immediate ( ty) && !fx. cx . is_backend_scalar_pair ( ty)
449
+ }
0 commit comments