From d93df7f4122cd7d6e287d90511a6ffa5218cfb11 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 11 Jul 2026 20:15:49 -0700 Subject: [PATCH] [cg_ssa] Eliminate the `is_backend_{immediate,scalar_pair,ref}` methods --- compiler/rustc_abi/src/lib.rs | 34 ++++++- compiler/rustc_codegen_gcc/src/builder.rs | 2 +- compiler/rustc_codegen_gcc/src/type_of.rs | 29 ------ compiler/rustc_codegen_llvm/src/builder.rs | 2 +- compiler/rustc_codegen_llvm/src/type_.rs | 6 -- compiler/rustc_codegen_llvm/src/type_of.rs | 21 ----- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 13 ++- .../rustc_codegen_ssa/src/mir/intrinsic.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/operand.rs | 88 ++++++++++++------- compiler/rustc_codegen_ssa/src/mir/retag.rs | 10 ++- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 16 ++-- .../rustc_codegen_ssa/src/traits/builder.rs | 4 +- .../rustc_codegen_ssa/src/traits/type_.rs | 16 ---- 14 files changed, 118 insertions(+), 129 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index e26b806dc7397..12cc13f40fddd 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1871,12 +1871,25 @@ impl BackendRepr { } } - /// Returns `true` if this is a scalar type + /// Returns `true` if this is specifically a [`Self::Scalar`] type. + /// + /// This excludes SIMD types. #[inline] pub fn is_scalar(&self) -> bool { matches!(*self, BackendRepr::Scalar(_)) } + /// Returns `true` if this is a scalar type or SIMD type. + #[inline] + pub fn is_scalar_or_simd(&self) -> bool { + matches!( + *self, + BackendRepr::Scalar(_) + | BackendRepr::SimdVector { .. } + | BackendRepr::SimdScalableVector { .. } + ) + } + /// Returns `true` if this is a bool #[inline] pub fn is_bool(&self) -> bool { @@ -2322,6 +2335,25 @@ impl LayoutData { } } + /// In the backend, a value with this type and layout is fully represented by + /// its SSA value(s), independent of the contents of memory. + /// + /// For example, you can swap by reading both then writing both without using + /// an alloca because the store of one cannot affect the value of the other. + /// + /// Any projection into a standalone type must also yield a standalone type, + /// since it might not be in memory at all. + #[inline] + pub fn is_ssa_standalone(&self) -> bool { + match self.backend_repr { + BackendRepr::Memory { .. } => self.is_zst(), + BackendRepr::Scalar(..) + | BackendRepr::ScalarPair { .. } + | BackendRepr::SimdVector { .. } + | BackendRepr::SimdScalableVector { .. } => true, + } + } + /// Checks if these two `Layout` are equal enough to be considered "the same for all function /// call ABIs". Note however that real ABIs depend on more details that are not reflected in the /// `Layout`; the `PassMode` need to be compared as well. Also note that we assume diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index da17f05bb8a32..7671d2e026b03 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1054,7 +1054,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let val = if place.val.llextra.is_some() { // FIXME: Merge with the `else` below? OperandValue::Ref(place.val) - } else if place.layout.is_gcc_immediate() { + } else if place.layout.backend_repr.is_scalar_or_simd() { let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align); OperandValue::Immediate( if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr { diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 227b513c0ff30..f2ce7bca1e338 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -154,8 +154,6 @@ fn uncached_gcc_type<'gcc, 'tcx>( } pub trait LayoutGccExt<'tcx> { - fn is_gcc_immediate(&self) -> bool; - fn is_gcc_scalar_pair(&self) -> bool; fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; fn scalar_gcc_type_at<'gcc>( @@ -177,25 +175,6 @@ pub trait LayoutGccExt<'tcx> { } impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { - fn is_gcc_immediate(&self) -> bool { - match self.backend_repr { - BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true, - // FIXME(rustc_scalable_vector): Not yet implemented in rustc_codegen_gcc. - BackendRepr::SimdScalableVector { .. } => todo!(), - BackendRepr::ScalarPair { .. } | BackendRepr::Memory { .. } => false, - } - } - - fn is_gcc_scalar_pair(&self) -> bool { - match self.backend_repr { - BackendRepr::ScalarPair { .. } => true, - BackendRepr::Scalar(_) - | BackendRepr::SimdVector { .. } - | BackendRepr::SimdScalableVector { .. } - | BackendRepr::Memory { .. } => false, - } - } - /// Gets the GCC type corresponding to a Rust type, i.e., `rustc_middle::ty::Ty`. /// The pointee type of the pointer in `PlaceRef` is always this type. /// For sized types, it is also the right LLVM type for an `alloca` @@ -350,14 +329,6 @@ impl<'gcc, 'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { layout.immediate_gcc_type(self) } - fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool { - layout.is_gcc_immediate() - } - - fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool { - layout.is_gcc_scalar_pair() - } - fn scalar_pair_element_backend_type( &self, layout: TyAndLayout<'tcx>, diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 95380e4cb7533..64e581f313079 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -770,7 +770,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let val = if let Some(_) = place.val.llextra { // FIXME: Merge with the `else` below? OperandValue::Ref(place.val) - } else if place.layout.is_llvm_immediate() { + } else if place.layout.backend_repr.is_scalar_or_simd() { let mut const_llval = None; let llty = place.layout.llvm_type(self); if let Some(global) = llvm::LLVMIsAGlobalVariable(place.val.llval) { diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 0d49971f52533..c422515c1a64b 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -296,12 +296,6 @@ impl<'ll, 'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> &'ll Type { layout.immediate_llvm_type(self) } - fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool { - layout.is_llvm_immediate() - } - fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool { - layout.is_llvm_scalar_pair() - } fn scalar_pair_element_backend_type( &self, layout: TyAndLayout<'tcx>, diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index d1c2e1d567e40..0caf7e761bdb1 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -209,8 +209,6 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { } pub(crate) trait LayoutLlvmExt<'tcx> { - fn is_llvm_immediate(&self) -> bool; - fn is_llvm_scalar_pair(&self) -> bool; fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type; fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type; fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type; @@ -223,25 +221,6 @@ pub(crate) trait LayoutLlvmExt<'tcx> { } impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { - fn is_llvm_immediate(&self) -> bool { - match self.backend_repr { - BackendRepr::Scalar(_) - | BackendRepr::SimdVector { .. } - | BackendRepr::SimdScalableVector { .. } => true, - BackendRepr::ScalarPair { .. } | BackendRepr::Memory { .. } => false, - } - } - - fn is_llvm_scalar_pair(&self) -> bool { - match self.backend_repr { - BackendRepr::ScalarPair { .. } => true, - BackendRepr::Scalar(_) - | BackendRepr::SimdVector { .. } - | BackendRepr::SimdScalableVector { .. } - | BackendRepr::Memory { .. } => false, - } - } - /// Gets the LLVM type corresponding to a Rust type, i.e., `rustc_middle::ty::Ty`. /// The pointee type of the pointer in `PlaceRef` is always this type. /// For sized types, it is also the right LLVM type for an `alloca` diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index fb5734ba087c6..1074a14d4ee6a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -83,12 +83,11 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> LocalAnalyzer<'a, 'b, 'tcx, Bx> LocalKind::Unused => { let ty = fx.monomorphize(decl.ty); let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span); - *kind = - if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) { - LocalKind::SSA(location) - } else { - LocalKind::Memory - }; + *kind = if let abi::BackendRepr::Memory { .. } = layout.backend_repr { + LocalKind::Memory + } else { + LocalKind::SSA(location) + }; } LocalKind::SSA(_) => *kind = LocalKind::Memory, } @@ -157,7 +156,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> LocalAnalyzer<'a, 'b, 'tcx, Bx> } } debug_assert!( - !self.fx.cx.is_backend_ref(layout), + layout.is_ssa_standalone(), "Post-projection {place_ref:?} layout should be non-Ref, but it's {layout:?}", ); } diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 6116c0fa9eb98..c365be69eed91 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let sym::typed_swap_nonoverlapping = name { let pointee_ty = fn_args.type_at(0); let pointee_layout = bx.layout_of(pointee_ty); - if !bx.is_backend_ref(pointee_layout) + if pointee_layout.is_ssa_standalone() // But if we're not going to optimize, trying to use the fallback // body just makes things worse, so don't bother. || bx.sess().opts.optimize == OptLevel::No @@ -609,7 +609,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; debug_assert!( - op_val.is_expected_variant_for_type(bx.cx(), result_layout), + op_val.is_expected_variant_for_type(result_layout), "[{name:?}] Value {op_val:?} is wrong for type {result_layout:?}", ); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 2fa283a6c2eb4..0fd8a091e3ee3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -501,7 +501,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( PassMode::Direct(_) => { let llarg = bx.get_param(llarg_idx); llarg_idx += 1; - debug_assert!(bx.is_backend_immediate(arg.layout)); + debug_assert!(arg.layout.backend_repr.is_scalar_or_simd()); return local(OperandRef { val: OperandValue::Immediate(llarg), layout: arg.layout, diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index c53dd38a3af5e..2fd2846e259e2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -28,25 +28,43 @@ use crate::traits::*; pub enum OperandValue { /// A reference to the actual operand. The data is guaranteed /// to be valid for the operand's lifetime. - /// The second value, if any, is the extra data (vtable or length) + /// The [`PlaceValue::llextra`], if any, is the extra data (vtable or length) /// which indicates that it refers to an unsized rvalue. /// /// An `OperandValue` *must* be this variant for any type for which - /// [`LayoutTypeCodegenMethods::is_backend_ref`] returns `true`. + /// [`rustc_abi::LayoutData::is_ssa_standalone`] returns `false`. /// (That basically amounts to "isn't one of the other variants".) /// /// This holds a [`PlaceValue`] (like a [`PlaceRef`] does) with a pointer /// to the location holding the value. The type behind that pointer is the /// one returned by [`LayoutTypeCodegenMethods::backend_type`]. + /// + /// Note that a [`load_operand`] which produces this variant didn't actually + /// *load* anything; it just put the pointer-to-place into this variant. + /// + /// [`load_operand`]: BuilderMethods::load_operand Ref(PlaceValue), /// A single LLVM immediate value. /// - /// An `OperandValue` *must* be this variant for any type for which - /// [`LayoutTypeCodegenMethods::is_backend_immediate`] returns `true`. + /// An `OperandValue` *must* be this variant for any type that's + /// [`BackendRepr::Scalar`], [`BackendRepr::SimdVector`], or + /// [`BackendRepr::SimdScalableVector`]. + /// /// The backend value in this variant must be the *immediate* backend type, /// as returned by [`LayoutTypeCodegenMethods::immediate_backend_type`]. + /// + /// Notably, that means that in LLVM a `bool` is `i1` here, even though we + /// load and store `bool`s as LLVM's `i8` type. Methods such as + /// [`BuilderMethods::load_operand`] and [`OperandRef::store_with_annotation`] + /// will handle that correctly, but if you're using the value directly or + /// implementing such methods, be sure to convert using + /// [`BuilderMethods::from_immediate`] and [`BuilderMethods::to_immediate_scalar`] + /// in the appropriate places. Immediate(V), - /// A pair of immediate LLVM values. Used by wide pointers too. + /// A pair of immediate LLVM values. + /// + /// Notably this includes wide pointers, where the two values are the pointer + /// and the metadata (slice length, vtable pointer, etc). /// /// # Invariants /// - For `Pair(a, b)`, `a` is always at offset 0, but may have `FieldIdx(1..)` @@ -54,11 +72,10 @@ pub enum OperandValue { /// - `a` and `b` will have a different FieldIdx, but otherwise `b`'s may be lower /// or they may not be adjacent, due to arbitrary numbers of 1ZST fields that /// will not affect the shape of the data which determines if `Pair` will be used. - /// - An `OperandValue` *must* be this variant for any type for which - /// [`LayoutTypeCodegenMethods::is_backend_scalar_pair`] returns `true`. + /// - An `OperandValue` *must* be this variant for any type that's [`BackendRepr::ScalarPair`]. /// - The backend values in this variant must be the *immediate* backend types, /// as returned by [`LayoutTypeCodegenMethods::scalar_pair_element_backend_type`] - /// with `immediate: true`. + /// with `immediate: true`. See the note in [`Self::Immediate`]. Pair(V, V), /// A value taking no bytes, and which therefore needs no LLVM value at all. /// @@ -104,16 +121,18 @@ impl OperandValue { } #[must_use] - pub(crate) fn is_expected_variant_for_type<'tcx, Cx: LayoutTypeCodegenMethods<'tcx>>( - &self, - cx: &Cx, - ty: TyAndLayout<'tcx>, - ) -> bool { - match self { - OperandValue::ZeroSized => ty.is_zst(), - OperandValue::Immediate(_) => cx.is_backend_immediate(ty), - OperandValue::Pair(_, _) => cx.is_backend_scalar_pair(ty), - OperandValue::Ref(_) => cx.is_backend_ref(ty), + pub(crate) fn is_expected_variant_for_type<'tcx>(&self, ty: TyAndLayout<'tcx>) -> bool { + match (self, ty.backend_repr) { + (OperandValue::ZeroSized, BackendRepr::Memory { .. }) => ty.is_zst(), + (OperandValue::Ref(_), BackendRepr::Memory { .. }) => !ty.is_zst(), + ( + OperandValue::Immediate(_), + BackendRepr::Scalar(..) + | BackendRepr::SimdVector { .. } + | BackendRepr::SimdScalableVector { .. }, + ) => true, + (OperandValue::Pair(_, _), BackendRepr::ScalarPair { .. }) => true, + _ => false, } } } @@ -369,11 +388,11 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let field = self.layout.field(bx.cx(), i); let offset = self.layout.fields.offset(i); - if !bx.is_backend_ref(self.layout) && bx.is_backend_ref(field) { + if self.layout.is_ssa_standalone() && !field.is_ssa_standalone() { // Part of https://github.com/rust-lang/compiler-team/issues/838 span_bug!( fx.mir.span, - "Non-ref type {self:?} cannot project to ref field type {field:?}", + "Standalone type {self:?} cannot project to memory-dependent field type {field:?}", ); } @@ -943,18 +962,23 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { layout: TyAndLayout<'tcx>, ) -> OperandValue { assert!(layout.is_sized()); - if layout.is_zst() { - OperandValue::ZeroSized - } else if bx.cx().is_backend_immediate(layout) { - let ibty = bx.cx().immediate_backend_type(layout); - OperandValue::Immediate(bx.const_poison(ibty)) - } else if bx.cx().is_backend_scalar_pair(layout) { - let ibty0 = bx.cx().scalar_pair_element_backend_type(layout, 0, true); - let ibty1 = bx.cx().scalar_pair_element_backend_type(layout, 1, true); - OperandValue::Pair(bx.const_poison(ibty0), bx.const_poison(ibty1)) - } else { - let ptr = bx.cx().type_ptr(); - OperandValue::Ref(PlaceValue::new_sized(bx.const_poison(ptr), layout.align.abi)) + match layout.backend_repr { + _ if layout.is_zst() => OperandValue::ZeroSized, + BackendRepr::Scalar(_) + | BackendRepr::SimdVector { .. } + | BackendRepr::SimdScalableVector { .. } => { + let ibty = bx.cx().immediate_backend_type(layout); + OperandValue::Immediate(bx.const_poison(ibty)) + } + BackendRepr::ScalarPair { .. } => { + let ibty0 = bx.cx().scalar_pair_element_backend_type(layout, 0, true); + let ibty1 = bx.cx().scalar_pair_element_backend_type(layout, 1, true); + OperandValue::Pair(bx.const_poison(ibty0), bx.const_poison(ibty1)) + } + BackendRepr::Memory { .. } => { + let ptr = bx.cx().type_ptr(); + OperandValue::Ref(PlaceValue::new_sized(bx.const_poison(ptr), layout.align.abi)) + } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/retag.rs b/compiler/rustc_codegen_ssa/src/mir/retag.rs index 3f839d7945afd..680f0b44d70dd 100644 --- a/compiler/rustc_codegen_ssa/src/mir/retag.rs +++ b/compiler/rustc_codegen_ssa/src/mir/retag.rs @@ -14,9 +14,7 @@ use rustc_middle::ty::layout::TyAndLayout; use crate::mir::FunctionCx; use crate::mir::operand::{OperandRef, OperandRefBuilder, OperandValue}; use crate::mir::place::PlaceRef; -use crate::traits::{ - BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, LayoutTypeCodegenMethods, -}; +use crate::traits::{BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods}; use crate::{RetagFlags, RetagInfo}; pub(crate) fn rvalue_needs_retag(rvalue: &Rvalue<'_>) -> bool { @@ -255,8 +253,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let field_layout = curr_operand.layout.field(bx, ix.index()); // Part of https://github.com/rust-lang/compiler-team/issues/838 - if !bx.is_backend_ref(curr_operand.layout) && bx.is_backend_ref(field_layout) { + if curr_operand.layout.is_ssa_standalone() && !field_layout.is_ssa_standalone() + { // FIXME: support vector types, requires insert_element as part of cg-ssa + // FIXME: Nothing should be looking at the *array* inside a `repr(simd)` type, + // as that array doesn't really exist. Perhaps this should be a `bug!`, + // with simd types handled before getting here? } else { let field_operand = curr_operand.extract_field(self, bx, ix.as_usize()); self.retag_operand(bx, &plan, field_operand, builder, field_offset); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index b002d7554b36e..7f013e4cce041 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1,3 +1,5 @@ +use std::assert_matches; + use itertools::Itertools as _; use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT}; use rustc_index::IndexVec; @@ -137,7 +139,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) => { // The destination necessarily contains a wide pointer, so if // it's a scalar pair, it's a wide pointer or newtype thereof. - if bx.cx().is_backend_scalar_pair(dest.layout) { + if let BackendRepr::ScalarPair { .. } = dest.layout.backend_repr { // Into-coerce of a thin pointer to a wide pointer -- just // use the operand path. let temp = self.codegen_rvalue_operand(bx, rvalue); @@ -499,7 +501,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let val = match *kind { mir::CastKind::PointerExposeProvenance => { - assert!(bx.cx().is_backend_immediate(cast)); + assert!(cast.backend_repr.is_scalar_or_simd()); let llptr = operand.immediate(); let llcast_ty = bx.cx().immediate_backend_type(cast); let lladdr = bx.ptrtoint(llptr, llcast_ty); @@ -549,7 +551,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { operand.val } mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _) => { - assert!(bx.cx().is_backend_scalar_pair(cast)); + assert_matches!(cast.backend_repr, BackendRepr::ScalarPair { .. }); let (lldata, llextra) = operand.val.pointer_parts(); let (lldata, llextra) = base::unsize_ptr(bx, lldata, operand.layout.ty, cast.ty, llextra); @@ -561,9 +563,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) => { bug!("{kind:?} is for borrowck, and should never appear in codegen"); } - mir::CastKind::PtrToPtr if bx.cx().is_backend_scalar_pair(operand.layout) => { + mir::CastKind::PtrToPtr if let BackendRepr::ScalarPair { .. } = operand.layout.backend_repr => { if let OperandValue::Pair(data_ptr, meta) = operand.val { - if bx.cx().is_backend_scalar_pair(cast) { + if let BackendRepr::ScalarPair { .. } = cast.layout.backend_repr { OperandValue::Pair(data_ptr, meta) } else { // Cast of wide-ptr to thin-ptr is an extraction of data-ptr. @@ -590,7 +592,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let from_backend_ty = bx.cx().immediate_backend_type(operand.layout); - assert!(bx.cx().is_backend_immediate(cast)); + assert!(cast.backend_repr.is_scalar_or_simd()); let to_backend_ty = bx.cx().immediate_backend_type(cast); if operand.layout.is_uninhabited() { let val = OperandValue::Immediate(bx.cx().const_poison(to_backend_ty)); @@ -732,7 +734,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }; assert!( - val.is_expected_variant_for_type(self.cx, layout), + val.is_expected_variant_for_type(layout), "Made wrong variant {val:?} for type {layout:?}", ); OperandRef { val, layout, move_annotation: None } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 0d27ff90991b3..caf63abeef3ad 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -513,7 +513,9 @@ pub trait BuilderMethods<'a, 'tcx>: let ty = self.backend_type(layout); let val = self.load_from_place(ty, src); self.store_to_place_with_flags(val, dst, flags); - } else if self.sess().opts.optimize == OptLevel::No && self.is_backend_immediate(layout) { + } else if self.sess().opts.optimize == OptLevel::No + && layout.backend_repr.is_scalar_or_simd() + { // If we're not optimizing, the aliasing information from `memcpy` // isn't useful, so just load-store the value for smaller code. let temp = self.load_operand(src.with_type(layout)); diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 45ea8384b2d46..707eb3a6ee85d 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -127,28 +127,12 @@ pub trait LayoutTypeCodegenMethods<'tcx>: BackendTypes { /// [`from_immediate`](super::BuilderMethods::from_immediate) and /// [`to_immediate_scalar`](super::BuilderMethods::to_immediate_scalar). fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type; - fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool; - fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool; fn scalar_pair_element_backend_type( &self, layout: TyAndLayout<'tcx>, index: usize, immediate: bool, ) -> Self::Type; - - /// A type that produces an [`OperandValue::Ref`] when loaded. - /// - /// AKA one that's not a ZST, not `is_backend_immediate`, and - /// not `is_backend_scalar_pair`. For such a type, a - /// [`load_operand`] doesn't actually `load` anything. - /// - /// [`OperandValue::Ref`]: crate::mir::operand::OperandValue::Ref - /// [`load_operand`]: super::BuilderMethods::load_operand - fn is_backend_ref(&self, layout: TyAndLayout<'tcx>) -> bool { - !(layout.is_zst() - || self.is_backend_immediate(layout) - || self.is_backend_scalar_pair(layout)) - } } // For backends that support CFI using type membership (i.e., testing whether a given pointer is