Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1879,12 +1879,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 {
Expand Down Expand Up @@ -2330,6 +2343,25 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
}
}

/// 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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_gcc/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
29 changes: 0 additions & 29 deletions compiler/rustc_codegen_gcc/src/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>(
Expand All @@ -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`
Expand Down Expand Up @@ -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>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
28 changes: 26 additions & 2 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,33 @@ impl CodegenBackend for LlvmCodegenBackend {
target_config(sess)
}

/// Intrinsics whose fallback body will not be used by the LLVM backend.
fn replaced_intrinsics(&self) -> Vec<Symbol> {
let mut will_not_use_fallback =
vec![sym::unchecked_funnel_shl, sym::unchecked_funnel_shr, sym::carrying_mul_add];
#[rustfmt::skip]
let mut will_not_use_fallback = vec![
// These are mapped to LLVM intrinsics instead.
sym::unchecked_funnel_shl,
sym::unchecked_funnel_shr,
sym::carrying_mul_add,

// Fallback via libm, but the LLVM intrinsic is used instead.
sym::sinf16, sym::sinf32, sym::sinf64,
sym::cosf16, sym::cosf32, sym::cosf64,
sym::powf16, sym::powf32, sym::powf64,
sym::expf16, sym::expf32, sym::expf64,
sym::exp2f16, sym::exp2f32, sym::exp2f64,
sym::logf16, sym::logf32, sym::logf64,
sym::log10f16, sym::log10f32, sym::log10f64,
sym::log2f16, sym::log2f32, sym::log2f64,

// Fallback via f32 or f64, but the LLVM intrinsic is used instead.
sym::floorf16, sym::ceilf16, sym::truncf16,
sym::round_ties_even_f16, sym::roundf16,
sym::sqrtf16, sym::powif16,
sym::fmaf16,

sym::copysignf16, sym::copysignf32, sym::copysignf64, sym::copysignf128,
];

if llvm_util::get_version() >= (22, 0, 0) {
will_not_use_fallback.push(sym::carryless_mul);
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_codegen_llvm/src/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down
21 changes: 0 additions & 21 deletions compiler/rustc_codegen_llvm/src/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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`
Expand Down
13 changes: 6 additions & 7 deletions compiler/rustc_codegen_ssa/src/mir/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down Expand Up @@ -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:?}",
);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:?}",
);

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading
Loading