Remove unneeded FunctionCx from some codegen methods · rust-lang/rust@ed06f36 (original) (raw)
`@@ -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, chars 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 loaded with !range metadata, or
``
398
``
`` -
// 3) After a transmute we assumed 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 loaded with !range metadata, or
``
``
1172
`` +
// 3) After a transmute we assumed 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
`+
}
`