| Age | Commit message (Collapse) | Author | Lines |
|
x86-32 float return for 'Rust' ABI: treat all float types consistently
This helps with https://github.com/rust-lang/rust/issues/131819: for our own ABI on x86-32, we want to *never* use the float registers. The previous logic only considered F32 and F64, but skipped F16 and F128. So I made the logic just apply to all float types.
try-job: i686-gnu
try-job: i686-gnu-nopt
|
|
Always specify `llvm_abiname` for RISC-V targets
For RISC-V targets, when `llvm_abiname` is not specified LLVM will infer the ABI from the target features, causing #116344 to occur. This PR adds the correct `llvm_abiname` to all RISC-V targets where it is missing (which are all soft-float targets), and adds a test to prevent future RISC-V targets from accidentally omitting `llvm_abiname`. The only affect of this PR is that `-Ctarget-feature=+f` (or similar) will no longer affect the ABI on the modified targets.
<!-- homu-ignore:start -->
r? `@RalfJung`
<!--- homu-ignore:end -->
|
|
rust_for_linux: -Zregparm=<N> commandline flag for X86 (#116972)
Command line flag `-Zregparm=<N>` for X86 (32-bit) for rust-for-linux: https://github.com/rust-lang/rust/issues/116972
Implemented in the similar way as fastcall/vectorcall support (args are marked InReg if fit).
|
|
|
|
|
|
Add codegen test for branchy bool match
Closes #108395
|
|
Return values larger than 2 registers using a return area pointer
LLVM and Cranelift disagree about how to return values that don't fit in the registers designated for return values. LLVM will force the entire return value to be passed by return area pointer, while Cranelift will look at each IR level return value independently and decide to pass it in a register or not, which would result in the return value being passed partially in registers and partially through a return area pointer.
While Cranelift may need to be fixed as the LLVM behavior is generally more correct with respect to the surface language, forcing this behavior in rustc itself makes it easier for other backends to conform to the Rust ABI and for the C ABI rustc already handles this behavior anyway.
In addition LLVM's decision to pass the return value in registers or using a return area pointer depends on how exactly the return type is lowered to an LLVM IR type. For example `Option<u128>` can be lowered as `{ i128, i128 }` in which case the x86_64 backend would use a return area pointer, or it could be passed as `{ i32, i128 }` in which case the x86_64 backend would pass it in registers by taking advantage of an LLVM ABI extension that allows using 3 registers for the x86_64 sysv call conv rather than the officially specified 2 registers.
This adjustment is only necessary for the Rust ABI as for other ABI's the calling convention implementations in rustc_target already ensure any return value which doesn't fit in the available amount of return registers is passed in the right way for the current target.
Helps with https://github.com/rust-lang/rustc_codegen_cranelift/issues/1525
cc https://github.com/bytecodealliance/wasmtime/issues/9250
|
|
|
|
|
|
|
|
|
|
Avoid superfluous UB checks in `IndexRange`
`IndexRange::len` is justified as an overall invariant, and
`take_prefix` and `take_suffix` are justified by local branch
conditions. A few more UB-checked calls remain in cases that are only
supported locally by `debug_assert!`, which won't do anything in
distributed builds, so those UB checks may still be useful.
We generally expect core's `#![rustc_preserve_ub_checks]` to optimize
away in user's release builds, but the mere presence of that extra code
can sometimes inhibit optimization, as seen in #131563.
|
|
|
|
|
|
llvm/llvm-project#91101 propagates range information across inlining,
resulting in more metadata in this test. Tolerate the range metadata if
it appears.
|
|
Optimize `Box::default` and `Arc::default` to construct more types in place
Both the `Arc` and `Box` `Default` impls currently call `T::default()` before allocating, and then moving the resulting `T` into the allocation.
Most `Default` impls are trivial, which should in theory allow
LLVM to construct `T: Default` directly in the `Box` allocation when calling
`<Box<T>>::default()`.
However, the allocation may fail, which necessitates calling `T`'s destructor if it has one.
If the destructor is non-trivial, then LLVM has a hard time proving that it's
sound to elide, which makes it construct `T` on the stack first, and then copy it into the allocation.
Change both of these impls to allocate first, and then call `T::default` into the uninitialized allocation, so that LLVM doesn't have to prove that it's sound to elide the destructor/initial stack copy.
For example, given the following Rust code:
```rust
#[derive(Default, Clone)]
struct Foo {
x: Vec<u8>,
z: String,
y: Vec<u8>,
}
#[no_mangle]
pub fn src() -> Box<Foo> {
Box::default()
}
```
<details open>
<summary>Before this PR:</summary>
```llvm
`@__rust_no_alloc_shim_is_unstable` = external global i8
; drop_in_place() generated in case the allocation fails
; core::ptr::drop_in_place<playground::Foo>
; Function Attrs: nounwind nonlazybind uwtable
define internal fastcc void `@"_ZN4core3ptr36drop_in_place$LT$playground..Foo$GT$17hff376aece491233bE"(ptr` noalias nocapture noundef readonly align 8 dereferenceable(72) %_1) unnamed_addr #0 personality ptr `@rust_eh_personality` {
start:
%_1.val = load i64, ptr %_1, align 8
%0 = icmp eq i64 %_1.val, 0
br i1 %0, label %bb6, label %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i"
"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i": ; preds = %start
%1 = getelementptr inbounds i8, ptr %_1, i64 8
%_1.val6 = load ptr, ptr %1, align 8, !nonnull !3, !noundef !3
tail call void `@__rust_dealloc(ptr` noundef nonnull %_1.val6, i64 noundef %_1.val, i64 noundef 1) #8
br label %bb6
bb6: ; preds = %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i", %start
%2 = getelementptr inbounds i8, ptr %_1, i64 24
%.val9 = load i64, ptr %2, align 8
%3 = icmp eq i64 %.val9, 0
br i1 %3, label %bb5, label %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i.i11"
"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i.i11": ; preds = %bb6
%4 = getelementptr inbounds i8, ptr %_1, i64 32
%.val10 = load ptr, ptr %4, align 8, !nonnull !3, !noundef !3
tail call void `@__rust_dealloc(ptr` noundef nonnull %.val10, i64 noundef %.val9, i64 noundef 1) #8
br label %bb5
bb5: ; preds = %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i.i11", %bb6
%5 = getelementptr inbounds i8, ptr %_1, i64 48
%.val4 = load i64, ptr %5, align 8
%6 = icmp eq i64 %.val4, 0
br i1 %6, label %"_ZN4core3ptr46drop_in_place$LT$alloc..vec..Vec$LT$u8$GT$$GT$17hb5ca95423e113cf7E.exit16", label %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i15"
"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i15": ; preds = %bb5
%7 = getelementptr inbounds i8, ptr %_1, i64 56
%.val5 = load ptr, ptr %7, align 8, !nonnull !3, !noundef !3
tail call void `@__rust_dealloc(ptr` noundef nonnull %.val5, i64 noundef %.val4, i64 noundef 1) #8
br label %"_ZN4core3ptr46drop_in_place$LT$alloc..vec..Vec$LT$u8$GT$$GT$17hb5ca95423e113cf7E.exit16"
"_ZN4core3ptr46drop_in_place$LT$alloc..vec..Vec$LT$u8$GT$$GT$17hb5ca95423e113cf7E.exit16": ; preds = %bb5, %"_ZN63_$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$10deallocate17heaa87468709346b1E.exit.i.i.i4.i15"
ret void
}
; Function Attrs: nonlazybind uwtable
define noalias noundef nonnull align 8 ptr `@src()` unnamed_addr #1 personality ptr `@rust_eh_personality` {
start:
; alloca to place `Foo` in.
%_1 = alloca [72 x i8], align 8
call void `@llvm.lifetime.start.p0(i64` 72, ptr nonnull %_1)
store i64 0, ptr %_1, align 8
%_2.sroa.4.0._1.sroa_idx = getelementptr inbounds i8, ptr %_1, i64 8
store ptr inttoptr (i64 1 to ptr), ptr %_2.sroa.4.0._1.sroa_idx, align 8
%_2.sroa.5.0._1.sroa_idx = getelementptr inbounds i8, ptr %_1, i64 16
%_3.sroa.4.0..sroa_idx = getelementptr inbounds i8, ptr %_1, i64 32
call void `@llvm.memset.p0.i64(ptr` noundef nonnull align 8 dereferenceable(16) %_2.sroa.5.0._1.sroa_idx, i8 0, i64 16, i1 false)
store ptr inttoptr (i64 1 to ptr), ptr %_3.sroa.4.0..sroa_idx, align 8
%_3.sroa.5.0..sroa_idx = getelementptr inbounds i8, ptr %_1, i64 40
%_4.sroa.4.0..sroa_idx = getelementptr inbounds i8, ptr %_1, i64 56
call void `@llvm.memset.p0.i64(ptr` noundef nonnull align 8 dereferenceable(16) %_3.sroa.5.0..sroa_idx, i8 0, i64 16, i1 false)
store ptr inttoptr (i64 1 to ptr), ptr %_4.sroa.4.0..sroa_idx, align 8
%_4.sroa.5.0..sroa_idx = getelementptr inbounds i8, ptr %_1, i64 64
store i64 0, ptr %_4.sroa.5.0..sroa_idx, align 8
%0 = load volatile i8, ptr `@__rust_no_alloc_shim_is_unstable,` align 1, !noalias !4
%_0.i.i.i = tail call noalias noundef align 8 dereferenceable_or_null(72) ptr `@__rust_alloc(i64` noundef 72, i64 noundef 8) #8, !noalias !4
%1 = icmp eq ptr %_0.i.i.i, null
br i1 %1, label %bb2.i, label %"_ZN5alloc5boxed12Box$LT$T$GT$3new17h0864de14f863a27aE.exit"
bb2.i: ; preds = %start
; invoke alloc::alloc::handle_alloc_error
invoke void `@_ZN5alloc5alloc18handle_alloc_error17h98142d0d8d74161bE(i64` noundef 8, i64 noundef 72) #9
to label %.noexc unwind label %cleanup.i
.noexc: ; preds = %bb2.i
unreachable
cleanup.i: ; preds = %bb2.i
%2 = landingpad { ptr, i32 }
cleanup
; call core::ptr::drop_in_place<playground::Foo>
call fastcc void `@"_ZN4core3ptr36drop_in_place$LT$playground..Foo$GT$17hff376aece491233bE"(ptr` noalias noundef nonnull align 8 dereferenceable(72) %_1) #10
resume { ptr, i32 } %2
"_ZN5alloc5boxed12Box$LT$T$GT$3new17h0864de14f863a27aE.exit": ; preds = %start
; Copy from stack to heap if allocation is successful
call void `@llvm.memcpy.p0.p0.i64(ptr` noundef nonnull align 8 dereferenceable(72) %_0.i.i.i, ptr noundef nonnull align 8 dereferenceable(72) %_1, i64 72, i1 false)
call void `@llvm.lifetime.end.p0(i64` 72, ptr nonnull %_1)
ret ptr %_0.i.i.i
}
```
</details>
<details>
<summary>After this PR</summary>
```llvm
; Notice how there's no `drop_in_place()` generated as well
define noalias noundef nonnull align 8 ptr `@src()` unnamed_addr #0 personality ptr `@rust_eh_personality` {
start:
; no stack allocation
%0 = load volatile i8, ptr `@__rust_no_alloc_shim_is_unstable,` align 1
%_0.i.i.i.i.i = tail call noalias noundef align 8 dereferenceable_or_null(72) ptr `@__rust_alloc(i64` noundef 72, i64 noundef 8) #5
%1 = icmp eq ptr %_0.i.i.i.i.i, null
br i1 %1, label %bb3.i, label %"_ZN5alloc5boxed16Box$LT$T$C$A$GT$13new_uninit_in17h80d6355ef4b73ea3E.exit"
bb3.i: ; preds = %start
; call alloc::alloc::handle_alloc_error
tail call void `@_ZN5alloc5alloc18handle_alloc_error17h98142d0d8d74161bE(i64` noundef 8, i64 noundef 72) #6
unreachable
"_ZN5alloc5boxed16Box$LT$T$C$A$GT$13new_uninit_in17h80d6355ef4b73ea3E.exit": ; preds = %start
; construct `Foo` directly into the allocation if successful
store i64 0, ptr %_0.i.i.i.i.i, align 8
%_8.sroa.4.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 8
store ptr inttoptr (i64 1 to ptr), ptr %_8.sroa.4.0._1.sroa_idx, align 8
%_8.sroa.5.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 16
%_8.sroa.7.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 32
tail call void `@llvm.memset.p0.i64(ptr` noundef nonnull align 8 dereferenceable(16) %_8.sroa.5.0._1.sroa_idx, i8 0, i64 16, i1 false)
store ptr inttoptr (i64 1 to ptr), ptr %_8.sroa.7.0._1.sroa_idx, align 8
%_8.sroa.8.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 40
%_8.sroa.10.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 56
tail call void `@llvm.memset.p0.i64(ptr` noundef nonnull align 8 dereferenceable(16) %_8.sroa.8.0._1.sroa_idx, i8 0, i64 16, i1 false)
store ptr inttoptr (i64 1 to ptr), ptr %_8.sroa.10.0._1.sroa_idx, align 8
%_8.sroa.11.0._1.sroa_idx = getelementptr inbounds i8, ptr %_0.i.i.i.i.i, i64 64
store i64 0, ptr %_8.sroa.11.0._1.sroa_idx, align 8
ret ptr %_0.i.i.i.i.i
}
```
</details>
|
|
|
|
|
|
Support clobber_abi in MSP430 inline assembly
This supports `clobber_abi` which is one of the requirements of stabilization mentioned in #93335.
Refs: Section 3.2 "Register Conventions" in [MSP430 Embedded Application Binary Interface](https://www.ti.com/lit/an/slaa534a/slaa534a.pdf)
cc ``@cr1901``
r? ``@Amanieu``
``@rustbot`` label +O-msp430
|
|
`IndexRange::len` is justified as an overall invariant, and
`take_prefix` and `take_suffix` are justified by local branch
conditions. A few more UB-checked calls remain in cases that are only
supported locally by `debug_assert!`, which won't do anything in
distributed builds, so those UB checks may still be useful.
We generally expect core's `#![rustc_preserve_ub_checks]` to optimize
away in user's release builds, but the mere presence of that extra code
can sometimes inhibit optimization, as seen in #131563.
|
|
Use Default visibility for rustc-generated C symbol declarations
Non-default visibilities should only be used for definitions, not declarations, otherwise linking can fail.
This is based on https://github.com/rust-lang/rust/pull/123994.
Issue https://github.com/rust-lang/rust/issues/123427
When I changed `default-hidden-visibility` to `default-visibility` in https://github.com/rust-lang/rust/pull/130005, I updated all places in the code that used `default-hidden-visibility`, replicating the hidden-visibility bug to also happen for protected visibility.
Without this change, trying to build rustc with `-Z default-visibility=protected` fails with a link error.
|
|
This hack was intended to handle the case where `-Clto=thin` causes the
compiler to emit multiple output files (when producing LLVM-IR or assembly).
The hack only affects 4 tests, of which 3 are just meta-tests for the hack
itself. The one remaining test that motivated the hack currently doesn't even
need it!
(`tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs`)
|
|
Non-default visibilities should only be used for definitions, not
declarations, otherwise linking can fail.
Co-authored-by: Collin Baker <collinbaker@chromium.org>
|
|
LLVM and Cranelift disagree about how to return values that don't fit
in the registers designated for return values. LLVM will force the
entire return value to be passed by return area pointer, while
Cranelift will look at each IR level return value independently and
decide to pass it in a register or not, which would result in the
return value being passed partially in registers and partially through
a return area pointer.
While Cranelift may need to be fixed as the LLVM behavior is generally
more correct with respect to the surface language, forcing this
behavior in rustc itself makes it easier for other backends to conform
to the Rust ABI and for the C ABI rustc already handles this behavior
anyway.
In addition LLVM's decision to pass the return value in registers or
using a return area pointer depends on how exactly the return type is
lowered to an LLVM IR type. For example `Option<u128>` can be lowered
as `{ i128, i128 }` in which case the x86_64 backend would use a return
area pointer, or it could be passed as `{ i32, i128 }` in which case
the x86_64 backend would pass it in registers by taking advantage of an
LLVM ABI extension that allows using 3 registers for the x86_64 sysv
call conv rather than the officially specified 2 registers.
This adjustment is only necessary for the Rust ABI as for other ABI's
the calling convention implementations in rustc_target already ensure
any return value which doesn't fit in the available amount of return
registers is passed in the right way for the current target.
|
|
Same rationale as in the previous commit.
|
|
The `Box<T: Default>` impl currently calls `T::default()` before allocating
the `Box`.
Most `Default` impls are trivial, which should in theory allow
LLVM to construct `T: Default` directly in the `Box` allocation when calling
`<Box<T>>::default()`.
However, the allocation may fail, which necessitates calling `T's` destructor if it has one.
If the destructor is non-trivial, then LLVM has a hard time proving that it's
sound to elide, which makes it construct `T` on the stack first, and then copy it into the allocation.
Create an uninit `Box` first, and then write `T::default` into it, so that LLVM now only needs to prove
that the `T::default` can't panic, which should be trivial for most `Default` impls.
|
|
|
|
Rollup of 7 pull requests
Successful merges:
- #130824 (Add missing module flags for `-Zfunction-return=thunk-extern`)
- #131170 (Fix `target_vendor` in non-IDF Xtensa ESP32 targets)
- #131355 (Add tests for some old fixed issues)
- #131369 (Update books)
- #131370 (rustdoc: improve `<wbr>`-insertion for SCREAMING_CAMEL_CASE)
- #131379 (Fix utf8-bom test)
- #131385 (Un-vacation myself)
r? `@ghost`
`@rustbot` modify labels: rollup
|
|
Add missing module flags for `-Zfunction-return=thunk-extern`
This fixes a bug in the `-Zfunction-return=thunk-extern` flag. The flag needs to be passed onto LLVM to ensure that functions such as `asan.module_ctor` and `asan.module_dtor` that are created internally in LLVM have the mitigation applied to them.
This was originally discovered [in the Linux kernel](https://lore.kernel.org/all/CANiq72myZL4_poCMuNFevtpYYc0V0embjSuKb7y=C+m3vVA_8g@mail.gmail.com/).
Original flag PR: #116892
PR for similar issue: #129373
Tracking issue: #116853
cc ``@ojeda``
r? ``@wesleywiser``
|
|
|
|
- fix for divergence
- fix error message
- fix another cranelift test
- fix some cranelift things
- don't set the NORETURN option for naked asm
- fix use of naked_asm! in doc comment
- fix use of naked_asm! in run-make test
- use `span_bug` in unreachable branch
|
|
|
|
also disallow the `noreturn` option, and infer `naked_asm!` as `!`
|
|
|
|
|
|
|
|
Rollup of 4 pull requests
Successful merges:
- #130005 (Replace -Z default-hidden-visibility with -Z default-visibility)
- #130229 (ptr::add/sub: do not claim equivalence with `offset(c as isize)`)
- #130773 (Update Unicode escapes in `/library/core/src/char/methods.rs`)
- #130933 (rustdoc: lists items that contain multiple paragraphs are more clear)
r? `@ghost`
`@rustbot` modify labels: rollup
|
|
Support clobber_abi and vector/access registers (clobber-only) in s390x inline assembly
This supports `clobber_abi` which is one of the requirements of stabilization mentioned in #93335.
This also supports vector registers (as `vreg`) and access registers (as `areg`) as clobber-only, which need to support clobbering of them to implement clobber_abi.
Refs:
- "1.2.1.1. Register Preservation Rules" section in ELF Application Binary Interface s390x Supplement, Version 1.6.1 (lzsabi_s390x.pdf in https://github.com/IBM/s390x-abi/releases/tag/v1.6.1)
- Register definition in LLVM:
- Vector registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L249
- Access registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L332
I have three questions:
- ~~ELF Application Binary Interface s390x Supplement says that `cc` (condition code, bits 18-19 of PSW) is "Volatile".
However, we do not have a register class for `cc` and instead mark `cc` as clobbered unless `preserves_flags` is specified (https://github.com/rust-lang/rust/pull/111331).
Therefore, in the current implementation, if both `preserves_flags` and `clobber_abi` are specified, `cc` is not marked as clobbered. Is this okay? Or even if `preserves_flags` is used, should `cc` be marked as clobbered if `clobber_abi` is used?~~ UPDATE: resolved https://github.com/rust-lang/rust/pull/130630#issuecomment-2367923121
- ~~ELF Application Binary Interface s390x Supplement says that `pm` (program mask, bits 20-23 of PSW) is "Cleared".
There does not appear to be any registers associated with this in either [LLVM](https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td) or [GCC](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L407-L431), so at this point I don't see any way other than to just ignore it. Is this okay as-is?~~ UPDATE: resolved https://github.com/rust-lang/rust/pull/130630#issuecomment-2367923121
- Is "areg" a good name for register class name for access registers? It may be a bit confusing between that and `reg_addr`, which uses the “a” constraint (https://github.com/rust-lang/rust/pull/119431)...
Note:
- GCC seems to [recognize only `a0` and `a1`](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L428-L429), and using `a[2-15]` [causes errors](https://godbolt.org/z/a46vx8jjn).
Given that cg_gcc has a similar problem with other architecture (https://github.com/rust-lang/rustc_codegen_gcc/issues/485), I don't feel this is a blocker for this PR, but it is worth mentioning here.
- `vreg` should be able to accept `#[repr(simd)]` types as input if the `vector` target feature added in https://github.com/rust-lang/rust/pull/127506 is enabled, but core_arch has no s390x vector type and both `#[repr(simd)]` and `core::simd` are unstable, so I have not implemented it in this PR. EDIT: And supporting it is probably more complex than doing the equivalent on other architectures... https://github.com/rust-lang/rust/pull/88245#issuecomment-905559591
cc `@uweigand`
r? `@Amanieu`
`@rustbot` label +O-SystemZ
|
|
MCP: https://github.com/rust-lang/compiler-team/issues/782
Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com>
|
|
|
|
Refactor the code in the `convert_while_ascii` helper function to make
it more suitable for auto-vectorization and also process the full ascii
prefix of the string. The generic case conversion logic will only be
invoked starting from the first non-ascii character.
The runtime on microbenchmarks with ascii-only inputs improves between
1.5x for short and 4x for long inputs on x86_64 and aarch64.
The new implementation also encapsulates all unsafe inside the
`convert_while_ascii` function.
Fixes #123712
|
|
|
|
Don't alloca for unused locals
We already have a concept of mono-unreachable basic blocks; this is primarily useful for ensuring that we do not compile code under an `if false`. But since we never gave locals the same analysis, a large local only used under an `if false` will still have stack space allocated for it.
There are 3 places we traverse MIR during monomorphization: Inside the collector, `non_ssa_locals`, and the walk to generate code. Unfortunately, https://github.com/rust-lang/rust/pull/129283#issuecomment-2297925578 indicates that we cannot afford the expense of tracking reachable locals during the collector's traversal, so we do need at least two mono-reachable traversals. And of course caching is of no help here because the benchmarks that regress are incr-unchanged; they don't do any codegen.
This fixes the second problem in https://github.com/rust-lang/rust/issues/129282, and brings us anther step toward `const if` at home.
|
|
|
|
|
|
Remove macOS 10.10 dynamic linker bug workaround
Rust's current minimum macOS version is 10.12, so the hack can be removed. This PR also updates the `remove_dir_all` docs to reflect that all supported macOS versions are protected against TOCTOU race conditions (the fallback implementation was already removed in #127683).
try-job: dist-x86_64-apple
try-job: dist-aarch64-apple
try-job: dist-apple-various
try-job: aarch64-apple
try-job: x86_64-apple-1
|
|
inline assembly
|
|
Update the minimum external LLVM to 18
With this change, we'll have stable support for LLVM 18 and 19.
For reference, the previous increase to LLVM 17 was #122649.
cc `@rust-lang/wg-llvm`
r? nikic
|
|
|
|
|