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
7 changes: 4 additions & 3 deletions library/core/src/alloc/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,10 @@ pub unsafe trait GlobalAlloc {
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
// SAFETY: the caller must ensure that the `new_size` does not overflow.
// `layout.align()` comes from a `Layout` and is thus guaranteed to be valid.
let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) };
let alignment = layout.alignment();
// SAFETY: the caller must ensure that the `new_size` does not overflow
// when rounded up to the next multiple of `alignment`.
let new_layout = unsafe { Layout::from_size_alignment_unchecked(new_size, alignment) };
// SAFETY: the caller must ensure that `new_layout` is greater than zero.
let new_ptr = unsafe { self.alloc(new_layout) };
if !new_ptr.is_null() {
Expand Down
55 changes: 41 additions & 14 deletions library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,20 +516,47 @@ impl<T, const N: usize> [T; N] {
///
/// # Note on performance and stack usage
///
/// Unfortunately, usages of this method are currently not always optimized
/// as well as they could be. This mainly concerns large arrays, as mapping
/// over small arrays seem to be optimized just fine. Also note that in
/// debug mode (i.e. without any optimizations), this method can use a lot
/// of stack space (a few times the size of the array or more).
///
/// Therefore, in performance-critical code, try to avoid using this method
/// on large arrays or check the emitted code. Also try to avoid chained
/// maps (e.g. `arr.map(...).map(...)`).
///
/// In many cases, you can instead use [`Iterator::map`] by calling `.iter()`
/// or `.into_iter()` on your array. `[T; N]::map` is only necessary if you
/// really need a new array of the same size as the result. Rust's lazy
/// iterators tend to get optimized very well.
/// Note that this method is *eager*. It evaluates `f` all `N` times before
/// returning the new array.
///
/// That means that `arr.map(f).map(g)` is, in general, *not* equivalent to
/// `array.map(|x| g(f(x)))`, as the former calls `f` 4 times then `g` 4 times,
/// whereas the latter interleaves the calls (`fgfgfgfg`).
///
/// A consequence of this is that it can have fairly-high stack usage, especially
/// in debug mode or for long arrays. The backend may be able to optimize it
/// away, but especially for complicated mappings it might not be able to.
///
/// If you're doing a one-step `map` and really want an array as the result,
/// then absolutely use this method. Its implementation uses a bunch of tricks
/// to help the optimizer handle it well. Particularly for simple arrays,
/// like `[u8; 3]` or `[f32; 4]`, there's nothing to be concerned about.
///
/// However, if you don't actually need an *array* of the results specifically,
/// just to process them, then you likely want [`Iterator::map`] instead.
///
/// For example, rather than doing an array-to-array map of all the elements
/// in the array up-front and only iterating after that completes,
///
/// ```
/// # let my_array = [1, 2, 3];
/// # let f = |x: i32| x + 1;
/// for x in my_array.map(f) {
/// // ...
/// }
/// ```
///
/// It's often better to use an iterator along the lines of
///
/// ```
/// # let my_array = [1, 2, 3];
/// # let f = |x: i32| x + 1;
/// for x in my_array.into_iter().map(f) {
/// // ...
/// }
/// ```
///
/// as that's more likely to avoid large temporaries.
///
///
/// # Examples
Expand Down
5 changes: 4 additions & 1 deletion library/core/src/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1260,7 +1260,10 @@ pub trait SizedTypeProperties: Sized {

#[doc(hidden)]
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
const ALIGNMENT: Alignment = Alignment::of::<Self>();
const ALIGNMENT: Alignment = {
// This can't panic since type alignment is always a power of two.
Alignment::new(Self::ALIGN).unwrap()
};

/// `true` if this type requires no storage.
/// `false` if its [size](size_of) is greater than zero.
Expand Down
3 changes: 1 addition & 2 deletions library/core/src/ptr/alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ impl Alignment {
#[inline]
#[must_use]
pub const fn of<T>() -> Self {
// This can't actually panic since type alignment is always a power of two.
const { Alignment::new(align_of::<T>()).unwrap() }
<T as mem::SizedTypeProperties>::ALIGNMENT
}

/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
Expand Down
16 changes: 12 additions & 4 deletions src/bootstrap/src/core/builder/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::core::build_steps::tool::SourceType;
use crate::core::config::SplitDebuginfo;
use crate::core::config::flags::Color;
use crate::utils::build_stamp;
use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_args, linker_flags};
use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_flags};
use crate::{
BootstrapCommand, CLang, Compiler, Config, DryRun, EXTRA_CHECK_CFGS, GitRepo, Mode,
RemapScheme, TargetSelection, command, prepare_behaviour_dump_dir, t,
Expand Down Expand Up @@ -310,7 +310,15 @@ impl Cargo {
}
}

for arg in linker_args(builder, compiler.host, LldThreads::Yes) {
// We need to set host linker flags for compiling build scripts and proc-macros.
// This is done the same way as the target linker flags below, so cargo won't see
// any fingerprint difference between host==target versus cross-compiled targets
// when it comes to those host build artifacts.
if let Some(host_linker) = builder.linker(compiler.host) {
let host = crate::envify(&compiler.host.triple);
self.command.env(format!("CARGO_TARGET_{host}_LINKER"), host_linker);
}
for arg in linker_flags(builder, compiler.host, LldThreads::Yes) {
self.hostflags.arg(&arg);
}

Expand All @@ -319,11 +327,11 @@ impl Cargo {
self.command.env(format!("CARGO_TARGET_{target}_LINKER"), target_linker);
}
// We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not
// `linker_args` here.
// `linker_args` here. Cargo will pass that to both rustc and rustdoc invocations.
for flag in linker_flags(builder, target, LldThreads::Yes) {
self.rustflags.arg(&flag);
}
for arg in linker_args(builder, target, LldThreads::Yes) {
for arg in linker_flags(builder, target, LldThreads::Yes) {
self.rustdocflags.arg(&arg);
}

Expand Down
40 changes: 40 additions & 0 deletions tests/codegen-llvm/simd/array-repeat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//@ add-minicore
//@ revisions: X86 AARCH64 RISCV S390X
//@ [X86] compile-flags: -Copt-level=3 --target=x86_64-unknown-linux-gnu
//@ [X86] needs-llvm-components: x86
//@ [AARCH64] compile-flags: -Copt-level=3 --target=aarch64-unknown-linux-gnu
//@ [AARCH64] needs-llvm-components: aarch64
//@ [RISCV] compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu -Ctarget-feature=+v
//@ [RISCV] needs-llvm-components: riscv
//@ [S390X] compile-flags: -Copt-level=3 --target s390x-unknown-linux-gnu -Ctarget-feature=+vector
//@ [S390X] needs-llvm-components: systemz
#![crate_type = "lib"]
#![feature(repr_simd)]
#![feature(no_core)]
#![no_std]
#![no_core]
extern crate minicore;
use minicore::*;

#[repr(simd)]
pub struct Simd<T, const N: usize>(pub [T; N]);

pub type u8x16 = Simd<u8, 16>;

// Regression test for https://github.com/rust-lang/rust/issues/97804.

#[unsafe(no_mangle)]
fn foo(v: u16, p: &mut [u8; 16]) {
// An array repeat transmuted into a SIMD type should emit a canonical LLVM splat sequence:
//
// CHECK-LABEL: foo
// CHECK: start
// CHECK-NEXT: %0 = insertelement <8 x i16> poison, i16 %v, i64 0
// CHECK-NEXT: %1 = shufflevector <8 x i16> %0, <8 x i16> poison, <8 x i32> zeroinitializer
// CHECK-NEXT: store <8 x i16> %1, ptr %p, align 1
// CHECK-NEXT: ret void
unsafe {
let v: u8x16 = mem::transmute([v; 8]);
*p = mem::transmute(v);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
+ _6 = const {0x1 as *const [bool; 0]};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
+ _6 = const {0x1 as *const [bool; 0]};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
+ _6 = const {0x1 as *const [bool; 0]};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
+ _6 = const {0x1 as *const [bool; 0]};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
Expand Down
2 changes: 1 addition & 1 deletion tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
StorageLive(_1);
StorageLive(_2);
StorageLive(_3);
- _3 = const std::ptr::Alignment::of::<u8>::{constant#0};
- _3 = const <u8 as std::mem::SizedTypeProperties>::ALIGNMENT;
- _2 = copy _3 as *mut u8 (Transmute);
+ _3 = const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }};
+ _2 = const {0x1 as *mut u8};
Expand Down
22 changes: 0 additions & 22 deletions triagebot.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1536,13 +1536,6 @@ mir-opt = [
"@wesleywiser",
"@saethlin",
]
types = [
"@jackh726",
"@lcnr",
"@oli-obk",
"@spastorino",
"@BoxyUwU",
]
borrowck = [
"@davidtwco",
"@matthewjasper"
Expand All @@ -1562,21 +1555,6 @@ style-team = [
"@joshtriplett",
"@traviscross",
]
project-const-traits = [
"@fee1-dead",
"@fmease",
"@oli-obk",
]
project-stable-mir = [
"@celinval",
"@oli-obk",
"@scottmcm",
"@makai410",
]
project-exploit-mitigations = [
"@cuviper",
"@rcvalle",
]
compiletest = [
"@jieyouxu",
]
Expand Down
Loading