Skip to content

Commit 1c316d3

Browse files
committed
Auto merge of #152361 - JonathanBrouwer:rollup-Qkwz1vN, r=JonathanBrouwer
Rollup of 5 pull requests Successful merges: - #151869 (add test for codegen of SIMD vector from array repeat) - #152077 (bootstrap: always propagate `CARGO_TARGET_{host}_LINKER`) - #126100 (Reword the caveats on `array::map`) - #152275 (Stop having two different alignment constants) - #152325 (Remove more adhoc groups that correspond to teams)
2 parents 6efa357 + b0c9c4b commit 1c316d3

File tree

12 files changed

+107
-51
lines changed

12 files changed

+107
-51
lines changed

library/core/src/alloc/global.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,9 +284,10 @@ pub unsafe trait GlobalAlloc {
284284
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
285285
#[stable(feature = "global_alloc", since = "1.28.0")]
286286
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
287-
// SAFETY: the caller must ensure that the `new_size` does not overflow.
288-
// `layout.align()` comes from a `Layout` and is thus guaranteed to be valid.
289-
let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) };
287+
let alignment = layout.alignment();
288+
// SAFETY: the caller must ensure that the `new_size` does not overflow
289+
// when rounded up to the next multiple of `alignment`.
290+
let new_layout = unsafe { Layout::from_size_alignment_unchecked(new_size, alignment) };
290291
// SAFETY: the caller must ensure that `new_layout` is greater than zero.
291292
let new_ptr = unsafe { self.alloc(new_layout) };
292293
if !new_ptr.is_null() {

library/core/src/array/mod.rs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -516,20 +516,47 @@ impl<T, const N: usize> [T; N] {
516516
///
517517
/// # Note on performance and stack usage
518518
///
519-
/// Unfortunately, usages of this method are currently not always optimized
520-
/// as well as they could be. This mainly concerns large arrays, as mapping
521-
/// over small arrays seem to be optimized just fine. Also note that in
522-
/// debug mode (i.e. without any optimizations), this method can use a lot
523-
/// of stack space (a few times the size of the array or more).
524-
///
525-
/// Therefore, in performance-critical code, try to avoid using this method
526-
/// on large arrays or check the emitted code. Also try to avoid chained
527-
/// maps (e.g. `arr.map(...).map(...)`).
528-
///
529-
/// In many cases, you can instead use [`Iterator::map`] by calling `.iter()`
530-
/// or `.into_iter()` on your array. `[T; N]::map` is only necessary if you
531-
/// really need a new array of the same size as the result. Rust's lazy
532-
/// iterators tend to get optimized very well.
519+
/// Note that this method is *eager*. It evaluates `f` all `N` times before
520+
/// returning the new array.
521+
///
522+
/// That means that `arr.map(f).map(g)` is, in general, *not* equivalent to
523+
/// `array.map(|x| g(f(x)))`, as the former calls `f` 4 times then `g` 4 times,
524+
/// whereas the latter interleaves the calls (`fgfgfgfg`).
525+
///
526+
/// A consequence of this is that it can have fairly-high stack usage, especially
527+
/// in debug mode or for long arrays. The backend may be able to optimize it
528+
/// away, but especially for complicated mappings it might not be able to.
529+
///
530+
/// If you're doing a one-step `map` and really want an array as the result,
531+
/// then absolutely use this method. Its implementation uses a bunch of tricks
532+
/// to help the optimizer handle it well. Particularly for simple arrays,
533+
/// like `[u8; 3]` or `[f32; 4]`, there's nothing to be concerned about.
534+
///
535+
/// However, if you don't actually need an *array* of the results specifically,
536+
/// just to process them, then you likely want [`Iterator::map`] instead.
537+
///
538+
/// For example, rather than doing an array-to-array map of all the elements
539+
/// in the array up-front and only iterating after that completes,
540+
///
541+
/// ```
542+
/// # let my_array = [1, 2, 3];
543+
/// # let f = |x: i32| x + 1;
544+
/// for x in my_array.map(f) {
545+
/// // ...
546+
/// }
547+
/// ```
548+
///
549+
/// It's often better to use an iterator along the lines of
550+
///
551+
/// ```
552+
/// # let my_array = [1, 2, 3];
553+
/// # let f = |x: i32| x + 1;
554+
/// for x in my_array.into_iter().map(f) {
555+
/// // ...
556+
/// }
557+
/// ```
558+
///
559+
/// as that's more likely to avoid large temporaries.
533560
///
534561
///
535562
/// # Examples

library/core/src/mem/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,10 @@ pub trait SizedTypeProperties: Sized {
12601260

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

12651268
/// `true` if this type requires no storage.
12661269
/// `false` if its [size](size_of) is greater than zero.

library/core/src/ptr/alignment.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ impl Alignment {
5252
#[inline]
5353
#[must_use]
5454
pub const fn of<T>() -> Self {
55-
// This can't actually panic since type alignment is always a power of two.
56-
const { Alignment::new(align_of::<T>()).unwrap() }
55+
<T as mem::SizedTypeProperties>::ALIGNMENT
5756
}
5857

5958
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.

src/bootstrap/src/core/builder/cargo.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::core::build_steps::tool::SourceType;
1010
use crate::core::config::SplitDebuginfo;
1111
use crate::core::config::flags::Color;
1212
use crate::utils::build_stamp;
13-
use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_args, linker_flags};
13+
use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_flags};
1414
use crate::{
1515
BootstrapCommand, CLang, Compiler, Config, DryRun, EXTRA_CHECK_CFGS, GitRepo, Mode,
1616
RemapScheme, TargetSelection, command, prepare_behaviour_dump_dir, t,
@@ -310,7 +310,15 @@ impl Cargo {
310310
}
311311
}
312312

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

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//@ add-minicore
2+
//@ revisions: X86 AARCH64 RISCV S390X
3+
//@ [X86] compile-flags: -Copt-level=3 --target=x86_64-unknown-linux-gnu
4+
//@ [X86] needs-llvm-components: x86
5+
//@ [AARCH64] compile-flags: -Copt-level=3 --target=aarch64-unknown-linux-gnu
6+
//@ [AARCH64] needs-llvm-components: aarch64
7+
//@ [RISCV] compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu -Ctarget-feature=+v
8+
//@ [RISCV] needs-llvm-components: riscv
9+
//@ [S390X] compile-flags: -Copt-level=3 --target s390x-unknown-linux-gnu -Ctarget-feature=+vector
10+
//@ [S390X] needs-llvm-components: systemz
11+
#![crate_type = "lib"]
12+
#![feature(repr_simd)]
13+
#![feature(no_core)]
14+
#![no_std]
15+
#![no_core]
16+
extern crate minicore;
17+
use minicore::*;
18+
19+
#[repr(simd)]
20+
pub struct Simd<T, const N: usize>(pub [T; N]);
21+
22+
pub type u8x16 = Simd<u8, 16>;
23+
24+
// Regression test for https://github.com/rust-lang/rust/issues/97804.
25+
26+
#[unsafe(no_mangle)]
27+
fn foo(v: u16, p: &mut [u8; 16]) {
28+
// An array repeat transmuted into a SIMD type should emit a canonical LLVM splat sequence:
29+
//
30+
// CHECK-LABEL: foo
31+
// CHECK: start
32+
// CHECK-NEXT: %0 = insertelement <8 x i16> poison, i16 %v, i64 0
33+
// CHECK-NEXT: %1 = shufflevector <8 x i16> %0, <8 x i16> poison, <8 x i32> zeroinitializer
34+
// CHECK-NEXT: store <8 x i16> %1, ptr %p, align 1
35+
// CHECK-NEXT: ret void
36+
unsafe {
37+
let v: u8x16 = mem::transmute([v; 8]);
38+
*p = mem::transmute(v);
39+
}
40+
}

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
StorageLive(_4);
4545
StorageLive(_5);
4646
StorageLive(_6);
47-
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
47+
- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute);
4848
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
4949
+ _6 = const {0x1 as *const [bool; 0]};
5050
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
StorageLive(_4);
4545
StorageLive(_5);
4646
StorageLive(_6);
47-
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
47+
- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute);
4848
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
4949
+ _6 = const {0x1 as *const [bool; 0]};
5050
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
StorageLive(_4);
4545
StorageLive(_5);
4646
StorageLive(_6);
47-
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
47+
- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute);
4848
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
4949
+ _6 = const {0x1 as *const [bool; 0]};
5050
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
StorageLive(_4);
4545
StorageLive(_5);
4646
StorageLive(_6);
47-
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute);
47+
- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute);
4848
- _5 = NonNull::<[bool; 0]> { pointer: copy _6 };
4949
+ _6 = const {0x1 as *const [bool; 0]};
5050
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};

0 commit comments

Comments
 (0)