@@ -278,7 +278,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
278278 {
279279 let from_backend_ty = bx. backend_type ( operand. layout ) ;
280280 let to_backend_ty = bx. backend_type ( cast) ;
281- Some ( OperandValue :: Immediate ( self . transmute_immediate (
281+ Some ( OperandValue :: Immediate ( transmute_immediate (
282282 bx,
283283 imm,
284284 from_scalar,
@@ -303,8 +303,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
303303 let out_a_ibty = bx. scalar_pair_element_backend_type ( cast, 0 , false ) ;
304304 let out_b_ibty = bx. scalar_pair_element_backend_type ( cast, 1 , false ) ;
305305 Some ( OperandValue :: Pair (
306- self . transmute_immediate ( bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty) ,
307- self . transmute_immediate ( bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty) ,
306+ transmute_immediate ( bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty) ,
307+ transmute_immediate ( bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty) ,
308308 ) )
309309 } else {
310310 None
@@ -332,7 +332,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
332332 // valid ranges. For example, `char`s are passed as just `i32`, with no
333333 // way for LLVM to know that they're 0x10FFFF at most. Thus we assume
334334 // the range of the input value too, not just the output range.
335- self . assume_scalar_range ( bx, imm, from_scalar, from_backend_ty) ;
335+ assume_scalar_range ( bx, imm, from_scalar, from_backend_ty) ;
336336
337337 imm = match ( from_scalar. primitive ( ) , to_scalar. primitive ( ) ) {
338338 ( Int ( _, is_signed) , Int ( ..) ) => bx. intcast ( imm, to_backend_ty, is_signed) ,
@@ -365,98 +365,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
365365 Some ( imm)
366366 }
367367
368- /// Transmutes one of the immediates from an [`OperandValue::Immediate`]
369- /// or an [`OperandValue::Pair`] to an immediate of the target type.
370- ///
371- /// `to_backend_ty` must be the *non*-immediate backend type (so it will be
372- /// `i8`, not `i1`, for `bool`-like types.)
373- fn transmute_immediate (
374- & self ,
375- bx : & mut Bx ,
376- mut imm : Bx :: Value ,
377- from_scalar : abi:: Scalar ,
378- from_backend_ty : Bx :: Type ,
379- to_scalar : abi:: Scalar ,
380- to_backend_ty : Bx :: Type ,
381- ) -> Bx :: Value {
382- assert_eq ! ( from_scalar. size( self . cx) , to_scalar. size( self . cx) ) ;
383-
384- // While optimizations will remove no-op transmutes, they might still be
385- // there in debug or things that aren't no-op in MIR because they change
386- // the Rust type but not the underlying layout/niche.
387- if from_scalar == to_scalar && from_backend_ty == to_backend_ty {
388- return imm;
389- }
390-
391- use abi:: Primitive :: * ;
392- imm = bx. from_immediate ( imm) ;
393-
394- // If we have a scalar, we must already know its range. Either
395- //
396- // 1) It's a parameter with `range` parameter metadata,
397- // 2) It's something we `load`ed with `!range` metadata, or
398- // 3) After a transmute we `assume`d the range (see below).
399- //
400- // That said, last time we tried removing this, it didn't actually help
401- // the rustc-perf results, so might as well keep doing it
402- // <https://github.com/rust-lang/rust/pull/135610#issuecomment-2599275182>
403- self . assume_scalar_range ( bx, imm, from_scalar, from_backend_ty) ;
404-
405- imm = match ( from_scalar. primitive ( ) , to_scalar. primitive ( ) ) {
406- ( Int ( ..) | Float ( _) , Int ( ..) | Float ( _) ) => bx. bitcast ( imm, to_backend_ty) ,
407- ( Pointer ( ..) , Pointer ( ..) ) => bx. pointercast ( imm, to_backend_ty) ,
408- ( Int ( ..) , Pointer ( ..) ) => bx. ptradd ( bx. const_null ( bx. type_ptr ( ) ) , imm) ,
409- ( Pointer ( ..) , Int ( ..) ) => {
410- // FIXME: this exposes the provenance, which shouldn't be necessary.
411- bx. ptrtoint ( imm, to_backend_ty)
412- }
413- ( Float ( _) , Pointer ( ..) ) => {
414- let int_imm = bx. bitcast ( imm, bx. cx ( ) . type_isize ( ) ) ;
415- bx. ptradd ( bx. const_null ( bx. type_ptr ( ) ) , int_imm)
416- }
417- ( Pointer ( ..) , Float ( _) ) => {
418- // FIXME: this exposes the provenance, which shouldn't be necessary.
419- let int_imm = bx. ptrtoint ( imm, bx. cx ( ) . type_isize ( ) ) ;
420- bx. bitcast ( int_imm, to_backend_ty)
421- }
422- } ;
423-
424- // This `assume` remains important for cases like (a conceptual)
425- // transmute::<u32, NonZeroU32>(x) == 0
426- // since it's never passed to something with parameter metadata (especially
427- // after MIR inlining) so the only way to tell the backend about the
428- // constraint that the `transmute` introduced is to `assume` it.
429- self . assume_scalar_range ( bx, imm, to_scalar, to_backend_ty) ;
430-
431- imm = bx. to_immediate_scalar ( imm, to_scalar) ;
432- imm
433- }
434-
435- fn assume_scalar_range (
436- & self ,
437- bx : & mut Bx ,
438- imm : Bx :: Value ,
439- scalar : abi:: Scalar ,
440- backend_ty : Bx :: Type ,
441- ) {
442- if matches ! ( self . cx. sess( ) . opts. optimize, OptLevel :: No ) || scalar. is_always_valid ( self . cx ) {
443- return ;
444- }
445-
446- match scalar. primitive ( ) {
447- abi:: Primitive :: Int ( ..) => {
448- let range = scalar. valid_range ( self . cx ) ;
449- bx. assume_integer_range ( imm, backend_ty, range) ;
450- }
451- abi:: Primitive :: Pointer ( abi:: AddressSpace :: DATA )
452- if !scalar. valid_range ( self . cx ) . contains ( 0 ) =>
453- {
454- bx. assume_nonnull ( imm) ;
455- }
456- abi:: Primitive :: Pointer ( ..) | abi:: Primitive :: Float ( ..) => { }
457- }
458- }
459-
460368 pub ( crate ) fn codegen_rvalue_unsized (
461369 & mut self ,
462370 bx : & mut Bx ,
@@ -1231,3 +1139,93 @@ impl OperandValueKind {
12311139 } )
12321140 }
12331141}
1142+
1143+ /// Transmutes one of the immediates from an [`OperandValue::Immediate`]
1144+ /// or an [`OperandValue::Pair`] to an immediate of the target type.
1145+ ///
1146+ /// `to_backend_ty` must be the *non*-immediate backend type (so it will be
1147+ /// `i8`, not `i1`, for `bool`-like types.)
1148+ fn transmute_immediate < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
1149+ bx : & mut Bx ,
1150+ mut imm : Bx :: Value ,
1151+ from_scalar : abi:: Scalar ,
1152+ from_backend_ty : Bx :: Type ,
1153+ to_scalar : abi:: Scalar ,
1154+ to_backend_ty : Bx :: Type ,
1155+ ) -> Bx :: Value {
1156+ assert_eq ! ( from_scalar. size( bx. cx( ) ) , to_scalar. size( bx. cx( ) ) ) ;
1157+
1158+ // While optimizations will remove no-op transmutes, they might still be
1159+ // there in debug or things that aren't no-op in MIR because they change
1160+ // the Rust type but not the underlying layout/niche.
1161+ if from_scalar == to_scalar && from_backend_ty == to_backend_ty {
1162+ return imm;
1163+ }
1164+
1165+ use abi:: Primitive :: * ;
1166+ imm = bx. from_immediate ( imm) ;
1167+
1168+ // If we have a scalar, we must already know its range. Either
1169+ //
1170+ // 1) It's a parameter with `range` parameter metadata,
1171+ // 2) It's something we `load`ed with `!range` metadata, or
1172+ // 3) After a transmute we `assume`d the range (see below).
1173+ //
1174+ // That said, last time we tried removing this, it didn't actually help
1175+ // the rustc-perf results, so might as well keep doing it
1176+ // <https://github.com/rust-lang/rust/pull/135610#issuecomment-2599275182>
1177+ assume_scalar_range ( bx, imm, from_scalar, from_backend_ty) ;
1178+
1179+ imm = match ( from_scalar. primitive ( ) , to_scalar. primitive ( ) ) {
1180+ ( Int ( ..) | Float ( _) , Int ( ..) | Float ( _) ) => bx. bitcast ( imm, to_backend_ty) ,
1181+ ( Pointer ( ..) , Pointer ( ..) ) => bx. pointercast ( imm, to_backend_ty) ,
1182+ ( Int ( ..) , Pointer ( ..) ) => bx. ptradd ( bx. const_null ( bx. type_ptr ( ) ) , imm) ,
1183+ ( Pointer ( ..) , Int ( ..) ) => {
1184+ // FIXME: this exposes the provenance, which shouldn't be necessary.
1185+ bx. ptrtoint ( imm, to_backend_ty)
1186+ }
1187+ ( Float ( _) , Pointer ( ..) ) => {
1188+ let int_imm = bx. bitcast ( imm, bx. cx ( ) . type_isize ( ) ) ;
1189+ bx. ptradd ( bx. const_null ( bx. type_ptr ( ) ) , int_imm)
1190+ }
1191+ ( Pointer ( ..) , Float ( _) ) => {
1192+ // FIXME: this exposes the provenance, which shouldn't be necessary.
1193+ let int_imm = bx. ptrtoint ( imm, bx. cx ( ) . type_isize ( ) ) ;
1194+ bx. bitcast ( int_imm, to_backend_ty)
1195+ }
1196+ } ;
1197+
1198+ // This `assume` remains important for cases like (a conceptual)
1199+ // transmute::<u32, NonZeroU32>(x) == 0
1200+ // since it's never passed to something with parameter metadata (especially
1201+ // after MIR inlining) so the only way to tell the backend about the
1202+ // constraint that the `transmute` introduced is to `assume` it.
1203+ assume_scalar_range ( bx, imm, to_scalar, to_backend_ty) ;
1204+
1205+ imm = bx. to_immediate_scalar ( imm, to_scalar) ;
1206+ imm
1207+ }
1208+
1209+ fn assume_scalar_range < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
1210+ bx : & mut Bx ,
1211+ imm : Bx :: Value ,
1212+ scalar : abi:: Scalar ,
1213+ backend_ty : Bx :: Type ,
1214+ ) {
1215+ if matches ! ( bx. cx( ) . sess( ) . opts. optimize, OptLevel :: No ) || scalar. is_always_valid ( bx. cx ( ) ) {
1216+ return ;
1217+ }
1218+
1219+ match scalar. primitive ( ) {
1220+ abi:: Primitive :: Int ( ..) => {
1221+ let range = scalar. valid_range ( bx. cx ( ) ) ;
1222+ bx. assume_integer_range ( imm, backend_ty, range) ;
1223+ }
1224+ abi:: Primitive :: Pointer ( abi:: AddressSpace :: DATA )
1225+ if !scalar. valid_range ( bx. cx ( ) ) . contains ( 0 ) =>
1226+ {
1227+ bx. assume_nonnull ( imm) ;
1228+ }
1229+ abi:: Primitive :: Pointer ( ..) | abi:: Primitive :: Float ( ..) => { }
1230+ }
1231+ }
0 commit comments