Skip to content

Commit 0eff07b

Browse files
committed
try to avoid some layout_of calls
1 parent 23fd286 commit 0eff07b

File tree

8 files changed

+75
-71
lines changed

8 files changed

+75
-71
lines changed

Diff for: compiler/rustc_const_eval/src/interpret/cast.rs

+33-34
Original file line numberDiff line numberDiff line change
@@ -24,40 +24,43 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
2424
cast_ty: Ty<'tcx>,
2525
dest: &PlaceTy<'tcx, M::Provenance>,
2626
) -> InterpResult<'tcx> {
27+
// `cast_ty` will often be the same as `dest.ty`, but not always, since subtyping is still
28+
// possible.
29+
let cast_layout =
30+
if cast_ty == dest.layout.ty { dest.layout } else { self.layout_of(cast_ty)? };
2731
// FIXME: In which cases should we trigger UB when the source is uninit?
2832
match cast_kind {
2933
CastKind::PointerCoercion(PointerCoercion::Unsize) => {
30-
let cast_ty = self.layout_of(cast_ty)?;
31-
self.unsize_into(src, cast_ty, dest)?;
34+
self.unsize_into(src, cast_layout, dest)?;
3235
}
3336

3437
CastKind::PointerExposeAddress => {
3538
let src = self.read_immediate(src)?;
36-
let res = self.pointer_expose_address_cast(&src, cast_ty)?;
39+
let res = self.pointer_expose_address_cast(&src, cast_layout)?;
3740
self.write_immediate(*res, dest)?;
3841
}
3942

4043
CastKind::PointerFromExposedAddress => {
4144
let src = self.read_immediate(src)?;
42-
let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?;
45+
let res = self.pointer_from_exposed_address_cast(&src, cast_layout)?;
4346
self.write_immediate(*res, dest)?;
4447
}
4548

4649
CastKind::IntToInt | CastKind::IntToFloat => {
4750
let src = self.read_immediate(src)?;
48-
let res = self.int_to_int_or_float(&src, cast_ty)?;
51+
let res = self.int_to_int_or_float(&src, cast_layout)?;
4952
self.write_immediate(*res, dest)?;
5053
}
5154

5255
CastKind::FloatToFloat | CastKind::FloatToInt => {
5356
let src = self.read_immediate(src)?;
54-
let res = self.float_to_float_or_int(&src, cast_ty)?;
57+
let res = self.float_to_float_or_int(&src, cast_layout)?;
5558
self.write_immediate(*res, dest)?;
5659
}
5760

5861
CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
5962
let src = self.read_immediate(src)?;
60-
let res = self.ptr_to_ptr(&src, cast_ty)?;
63+
let res = self.ptr_to_ptr(&src, cast_layout)?;
6164
self.write_immediate(*res, dest)?;
6265
}
6366

@@ -140,6 +143,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
140143
CastKind::Transmute => {
141144
assert!(src.layout.is_sized());
142145
assert!(dest.layout.is_sized());
146+
assert_eq!(cast_ty, dest.layout.ty); // we otherwise ignore `cast_ty` enirely...
143147
if src.layout.size != dest.layout.size {
144148
let src_bytes = src.layout.size.bytes();
145149
let dest_bytes = dest.layout.size.bytes();
@@ -164,64 +168,61 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
164168
pub fn int_to_int_or_float(
165169
&self,
166170
src: &ImmTy<'tcx, M::Provenance>,
167-
cast_ty: Ty<'tcx>,
171+
cast_to: TyAndLayout<'tcx>,
168172
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
169173
assert!(src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool());
170-
assert!(cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char());
174+
assert!(cast_to.ty.is_floating_point() || cast_to.ty.is_integral() || cast_to.ty.is_char());
171175

172-
let layout = self.layout_of(cast_ty)?;
173176
Ok(ImmTy::from_scalar(
174-
self.cast_from_int_like(src.to_scalar(), src.layout, cast_ty)?,
175-
layout,
177+
self.cast_from_int_like(src.to_scalar(), src.layout, cast_to.ty)?,
178+
cast_to,
176179
))
177180
}
178181

179182
/// Handles 'FloatToFloat' and 'FloatToInt' casts.
180183
pub fn float_to_float_or_int(
181184
&self,
182185
src: &ImmTy<'tcx, M::Provenance>,
183-
cast_ty: Ty<'tcx>,
186+
cast_to: TyAndLayout<'tcx>,
184187
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
185188
use rustc_type_ir::sty::TyKind::*;
186189

187-
let layout = self.layout_of(cast_ty)?;
188190
let val = match src.layout.ty.kind() {
189191
// Floating point
190-
Float(FloatTy::F32) => self.cast_from_float(src.to_scalar().to_f32()?, cast_ty),
191-
Float(FloatTy::F64) => self.cast_from_float(src.to_scalar().to_f64()?, cast_ty),
192+
Float(FloatTy::F32) => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty),
193+
Float(FloatTy::F64) => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty),
192194
_ => {
193-
bug!("Can't cast 'Float' type into {}", cast_ty);
195+
bug!("Can't cast 'Float' type into {}", cast_to.ty);
194196
}
195197
};
196-
Ok(ImmTy::from_scalar(val, layout))
198+
Ok(ImmTy::from_scalar(val, cast_to))
197199
}
198200

199201
/// Handles 'FnPtrToPtr' and 'PtrToPtr' casts.
200202
pub fn ptr_to_ptr(
201203
&self,
202204
src: &ImmTy<'tcx, M::Provenance>,
203-
cast_ty: Ty<'tcx>,
205+
cast_to: TyAndLayout<'tcx>,
204206
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
205207
assert!(src.layout.ty.is_any_ptr());
206-
assert!(cast_ty.is_unsafe_ptr());
208+
assert!(cast_to.ty.is_unsafe_ptr());
207209
// Handle casting any ptr to raw ptr (might be a fat ptr).
208-
let dest_layout = self.layout_of(cast_ty)?;
209-
if dest_layout.size == src.layout.size {
210+
if cast_to.size == src.layout.size {
210211
// Thin or fat pointer that just hast the ptr kind of target type changed.
211-
return Ok(ImmTy::from_immediate(**src, dest_layout));
212+
return Ok(ImmTy::from_immediate(**src, cast_to));
212213
} else {
213214
// Casting the metadata away from a fat ptr.
214215
assert_eq!(src.layout.size, 2 * self.pointer_size());
215-
assert_eq!(dest_layout.size, self.pointer_size());
216+
assert_eq!(cast_to.size, self.pointer_size());
216217
assert!(src.layout.ty.is_unsafe_ptr());
217218
return match **src {
218-
Immediate::ScalarPair(data, _) => Ok(ImmTy::from_scalar(data, dest_layout)),
219+
Immediate::ScalarPair(data, _) => Ok(ImmTy::from_scalar(data, cast_to)),
219220
Immediate::Scalar(..) => span_bug!(
220221
self.cur_span(),
221222
"{:?} input to a fat-to-thin cast ({} -> {})",
222223
*src,
223224
src.layout.ty,
224-
cast_ty
225+
cast_to.ty
225226
),
226227
Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
227228
};
@@ -231,28 +232,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
231232
pub fn pointer_expose_address_cast(
232233
&mut self,
233234
src: &ImmTy<'tcx, M::Provenance>,
234-
cast_ty: Ty<'tcx>,
235+
cast_to: TyAndLayout<'tcx>,
235236
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
236237
assert_matches!(src.layout.ty.kind(), ty::RawPtr(_) | ty::FnPtr(_));
237-
assert!(cast_ty.is_integral());
238+
assert!(cast_to.ty.is_integral());
238239

239240
let scalar = src.to_scalar();
240241
let ptr = scalar.to_pointer(self)?;
241242
match ptr.into_pointer_or_addr() {
242243
Ok(ptr) => M::expose_ptr(self, ptr)?,
243244
Err(_) => {} // Do nothing, exposing an invalid pointer (`None` provenance) is a NOP.
244245
};
245-
let layout = self.layout_of(cast_ty)?;
246-
Ok(ImmTy::from_scalar(self.cast_from_int_like(scalar, src.layout, cast_ty)?, layout))
246+
Ok(ImmTy::from_scalar(self.cast_from_int_like(scalar, src.layout, cast_to.ty)?, cast_to))
247247
}
248248

249249
pub fn pointer_from_exposed_address_cast(
250250
&self,
251251
src: &ImmTy<'tcx, M::Provenance>,
252-
cast_ty: Ty<'tcx>,
252+
cast_to: TyAndLayout<'tcx>,
253253
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
254254
assert!(src.layout.ty.is_integral());
255-
assert_matches!(cast_ty.kind(), ty::RawPtr(_));
255+
assert_matches!(cast_to.ty.kind(), ty::RawPtr(_));
256256

257257
// First cast to usize.
258258
let scalar = src.to_scalar();
@@ -261,8 +261,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
261261

262262
// Then turn address into pointer.
263263
let ptr = M::ptr_from_addr_cast(&self, addr)?;
264-
let layout = self.layout_of(cast_ty)?;
265-
Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(ptr, self), layout))
264+
Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(ptr, self), cast_to))
266265
}
267266

268267
/// Low-level cast helper function. This works directly on scalars and can take 'int-like' input

Diff for: compiler/rustc_const_eval/src/interpret/discriminant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
163163
// Cast bits from tag layout to discriminant layout.
164164
// After the checks we did above, this cannot fail, as
165165
// discriminants are int-like.
166-
let discr_val = self.int_to_int_or_float(&tag_val, discr_layout.ty).unwrap();
166+
let discr_val = self.int_to_int_or_float(&tag_val, discr_layout).unwrap();
167167
let discr_bits = discr_val.to_scalar().assert_bits(discr_layout.size);
168168
// Convert discriminant to variant index, and catch invalid discriminants.
169169
let index = match *ty.kind() {

Diff for: compiler/rustc_mir_transform/src/dataflow_const_prop.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -234,20 +234,26 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
234234
}
235235
}
236236
Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => {
237+
let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
238+
return ValueOrPlace::Value(FlatSet::Top);
239+
};
237240
match self.eval_operand(operand, state) {
238241
FlatSet::Elem(op) => self
239242
.ecx
240-
.int_to_int_or_float(&op, *ty)
243+
.int_to_int_or_float(&op, layout)
241244
.map_or(FlatSet::Top, |result| self.wrap_immediate(*result)),
242245
FlatSet::Bottom => FlatSet::Bottom,
243246
FlatSet::Top => FlatSet::Top,
244247
}
245248
}
246249
Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat, operand, ty) => {
250+
let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
251+
return ValueOrPlace::Value(FlatSet::Top);
252+
};
247253
match self.eval_operand(operand, state) {
248254
FlatSet::Elem(op) => self
249255
.ecx
250-
.float_to_float_or_int(&op, *ty)
256+
.float_to_float_or_int(&op, layout)
251257
.map_or(FlatSet::Top, |result| self.wrap_immediate(*result)),
252258
FlatSet::Bottom => FlatSet::Bottom,
253259
FlatSet::Top => FlatSet::Top,

Diff for: src/tools/miri/src/helpers.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1013,15 +1013,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
10131013
fn float_to_int_checked<F>(
10141014
&self,
10151015
f: F,
1016-
dest_ty: Ty<'tcx>,
1016+
cast_to: TyAndLayout<'tcx>,
10171017
round: rustc_apfloat::Round,
10181018
) -> Option<ImmTy<'tcx, Provenance>>
10191019
where
10201020
F: rustc_apfloat::Float + Into<Scalar<Provenance>>,
10211021
{
10221022
let this = self.eval_context_ref();
10231023

1024-
let val = match dest_ty.kind() {
1024+
let val = match cast_to.ty.kind() {
10251025
// Unsigned
10261026
ty::Uint(t) => {
10271027
let size = Integer::from_uint_ty(this, *t).size();
@@ -1062,10 +1062,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
10621062
_ =>
10631063
span_bug!(
10641064
this.cur_span(),
1065-
"attempted float-to-int conversion with non-int output type {dest_ty:?}"
1065+
"attempted float-to-int conversion with non-int output type {}",
1066+
cast_to.ty,
10661067
),
10671068
};
1068-
Some(ImmTy::from_scalar(val, this.layout_of(dest_ty).unwrap()))
1069+
Some(ImmTy::from_scalar(val, cast_to))
10691070
}
10701071

10711072
/// Returns an integer type that is twice wide as `ty`

Diff for: src/tools/miri/src/shims/intrinsics/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
368368
ty::Float(FloatTy::F32) => {
369369
let f = val.to_scalar().to_f32()?;
370370
this
371-
.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
371+
.float_to_int_checked(f, dest.layout, Round::TowardZero)
372372
.ok_or_else(|| {
373373
err_ub_format!(
374374
"`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`",
@@ -379,7 +379,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
379379
ty::Float(FloatTy::F64) => {
380380
let f = val.to_scalar().to_f64()?;
381381
this
382-
.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
382+
.float_to_int_checked(f, dest.layout, Round::TowardZero)
383383
.ok_or_else(|| {
384384
err_ub_format!(
385385
"`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`",

Diff for: src/tools/miri/src/shims/intrinsics/simd.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -441,17 +441,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
441441
// Int-to-(int|float): always safe
442442
(ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_))
443443
if safe_cast || unsafe_cast =>
444-
this.int_to_int_or_float(&op, dest.layout.ty)?,
444+
this.int_to_int_or_float(&op, dest.layout)?,
445445
// Float-to-float: always safe
446446
(ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast =>
447-
this.float_to_float_or_int(&op, dest.layout.ty)?,
447+
this.float_to_float_or_int(&op, dest.layout)?,
448448
// Float-to-int in safe mode
449449
(ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
450-
this.float_to_float_or_int(&op, dest.layout.ty)?,
450+
this.float_to_float_or_int(&op, dest.layout)?,
451451
// Float-to-int in unchecked mode
452452
(ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast => {
453453
let f = op.to_scalar().to_f32()?;
454-
this.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
454+
this.float_to_int_checked(f, dest.layout, Round::TowardZero)
455455
.ok_or_else(|| {
456456
err_ub_format!(
457457
"`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`",
@@ -462,7 +462,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
462462
}
463463
(ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast => {
464464
let f = op.to_scalar().to_f64()?;
465-
this.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
465+
this.float_to_int_checked(f, dest.layout, Round::TowardZero)
466466
.ok_or_else(|| {
467467
err_ub_format!(
468468
"`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`",
@@ -473,12 +473,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
473473
}
474474
// Ptr-to-ptr cast
475475
(ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast =>
476-
this.ptr_to_ptr(&op, dest.layout.ty)?,
476+
this.ptr_to_ptr(&op, dest.layout)?,
477477
// Ptr/Int casts
478478
(ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast =>
479-
this.pointer_expose_address_cast(&op, dest.layout.ty)?,
479+
this.pointer_expose_address_cast(&op, dest.layout)?,
480480
(ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast =>
481-
this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?,
481+
this.pointer_from_exposed_address_cast(&op, dest.layout)?,
482482
// Error otherwise
483483
_ =>
484484
throw_unsup_format!(

Diff for: src/tools/miri/src/shims/x86/sse.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
173173
_ => unreachable!(),
174174
};
175175

176-
let res = this.float_to_int_checked(op, dest.layout.ty, rnd).unwrap_or_else(|| {
176+
let res = this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| {
177177
// Fallback to minimum acording to SSE semantics.
178178
ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout)
179179
});
@@ -196,7 +196,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
196196

197197
let right = this.read_immediate(right)?;
198198
let dest0 = this.project_index(&dest, 0)?;
199-
let res0 = this.int_to_int_or_float(&right, dest0.layout.ty)?;
199+
let res0 = this.int_to_int_or_float(&right, dest0.layout)?;
200200
this.write_immediate(*res0, &dest0)?;
201201

202202
for i in 1..dest_len {

0 commit comments

Comments
 (0)