@@ -12,7 +12,7 @@ use rustc_middle::mir::visit::{
1212} ;
1313use rustc_middle:: mir:: { self , Location , TerminatorKind } ;
1414use rustc_middle:: ty;
15- use rustc_middle:: ty:: layout:: HasTyCtxt ;
15+ use rustc_middle:: ty:: layout:: { HasTyCtxt , TyAndLayout } ;
1616use rustc_target:: abi:: LayoutOf ;
1717
1818pub 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>>(
2727 let ty = fx. monomorphize ( & decl. ty ) ;
2828 debug ! ( "local {:?} has type `{}`" , local, ty) ;
2929 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) {
4232 analyzer. not_ssa ( local) ;
4333 }
4434 }
@@ -132,7 +122,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
132122
133123 if let mir:: ProjectionElem :: Field ( ..) = elem {
134124 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) {
136126 // Recurse with the same context, instead of `Projection`,
137127 // potentially stopping at non-operand projections,
138128 // which would trigger `not_ssa` on locals.
@@ -446,3 +436,14 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
446436 debug ! ( "cleanup_kinds: result={:?}" , result) ;
447437 result
448438}
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