@@ -278,7 +278,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
278
278
{
279
279
let from_backend_ty = bx. backend_type ( operand. layout ) ;
280
280
let to_backend_ty = bx. backend_type ( cast) ;
281
- Some ( OperandValue :: Immediate ( self . transmute_immediate (
281
+ Some ( OperandValue :: Immediate ( transmute_immediate (
282
282
bx,
283
283
imm,
284
284
from_scalar,
@@ -303,8 +303,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
303
303
let out_a_ibty = bx. scalar_pair_element_backend_type ( cast, 0 , false ) ;
304
304
let out_b_ibty = bx. scalar_pair_element_backend_type ( cast, 1 , false ) ;
305
305
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) ,
308
308
) )
309
309
} else {
310
310
None
@@ -332,7 +332,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
332
332
// valid ranges. For example, `char`s are passed as just `i32`, with no
333
333
// way for LLVM to know that they're 0x10FFFF at most. Thus we assume
334
334
// 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) ;
336
336
337
337
imm = match ( from_scalar. primitive ( ) , to_scalar. primitive ( ) ) {
338
338
( 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> {
365
365
Some ( imm)
366
366
}
367
367
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
-
460
368
pub ( crate ) fn codegen_rvalue_unsized (
461
369
& mut self ,
462
370
bx : & mut Bx ,
@@ -1231,3 +1139,93 @@ impl OperandValueKind {
1231
1139
} )
1232
1140
}
1233
1141
}
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