@@ -6,6 +6,7 @@ use rustc_middle::bug;
66use rustc_middle:: ty:: layout:: { FnAbiOf , LayoutOf , TyAndLayout } ;
77use rustc_middle:: ty:: print:: { with_no_trimmed_paths, with_no_visible_paths} ;
88use rustc_middle:: ty:: { self , Ty , TypeVisitableExt } ;
9+ use rustc_target:: abi:: HasDataLayout ;
910use rustc_target:: abi:: { Abi , Align , FieldsShape } ;
1011use rustc_target:: abi:: { Int , Pointer , F32 , F64 } ;
1112use rustc_target:: abi:: { PointeeInfo , Scalar , Size , TyAbiInterface , Variants } ;
@@ -192,6 +193,7 @@ pub trait LayoutLlvmExt<'tcx> {
192193 ) -> & ' a Type ;
193194 fn llvm_field_index < ' a > ( & self , cx : & CodegenCx < ' a , ' tcx > , index : usize ) -> u64 ;
194195 fn pointee_info_at < ' a > ( & self , cx : & CodegenCx < ' a , ' tcx > , offset : Size ) -> Option < PointeeInfo > ;
196+ fn scalar_copy_llvm_type < ' a > ( & self , cx : & CodegenCx < ' a , ' tcx > ) -> Option < & ' a Type > ;
195197}
196198
197199impl < ' tcx > LayoutLlvmExt < ' tcx > for TyAndLayout < ' tcx > {
@@ -414,4 +416,35 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
414416 cx. pointee_infos . borrow_mut ( ) . insert ( ( self . ty , offset) , result) ;
415417 result
416418 }
419+
420+ fn scalar_copy_llvm_type < ' a > ( & self , cx : & CodegenCx < ' a , ' tcx > ) -> Option < & ' a Type > {
421+ debug_assert ! ( self . is_sized( ) ) ;
422+
423+ // FIXME: this is a fairly arbitrary choice, but 128 bits on WASM
424+ // (matching the 128-bit SIMD types proposal) and 256 bits on x64
425+ // (like AVX2 registers) seems at least like a tolerable starting point.
426+ let threshold = cx. data_layout ( ) . pointer_size * 4 ;
427+ if self . layout . size ( ) > threshold {
428+ return None ;
429+ }
430+
431+ // Vectors, even for non-power-of-two sizes, have the same layout as
432+ // arrays but don't count as aggregate types
433+ if let FieldsShape :: Array { count, .. } = self . layout . fields ( )
434+ && let element = self . field ( cx, 0 )
435+ && element. ty . is_integral ( )
436+ {
437+ // `cx.type_ix(bits)` is tempting here, but while that works great
438+ // for things that *stay* as memory-to-memory copies, it also ends
439+ // up suppressing vectorization as it introduces shifts when it
440+ // extracts all the individual values.
441+
442+ let ety = element. llvm_type ( cx) ;
443+ return Some ( cx. type_vector ( ety, * count) ) ;
444+ }
445+
446+ // FIXME: The above only handled integer arrays; surely more things
447+ // would also be possible. Be careful about provenance, though!
448+ None
449+ }
417450}
0 commit comments