Skip to content

Commit 827651f

Browse files
committed
Auto merge of #155674 - JonathanBrouwer:rollup-NG1fnzG, r=JonathanBrouwer
Rollup of 10 pull requests Successful merges: - #146544 (mir-opt: Remove the workaround in UnreachableEnumBranching) - #154819 (Fix ICE for inherent associated type mismatches) - #155265 (Improved assumptions relating to isqrt) - #152576 (c-variadic: use `emit_ptr_va_arg` for mips) - #154481 (Mark a function only used in nightly as nightly only) - #155614 (c-variadic: rename `VaList::arg` to `VaList::next_arg`) - #155630 (Make `//@ skip-filecheck` a normal compiletest directive) - #155641 (Remove non-working code for "running" mir-opt tests) - #155652 (Expand `Path::is_empty` docs) - #155656 (rustc_llvm: update opt-level handling for LLVM 23)
2 parents 92c7010 + 0fa807c commit 827651f

194 files changed

Lines changed: 755 additions & 490 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_abi/src/callconv.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ impl HomogeneousAggregate {
3535
/// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in
3636
/// the same `struct`. Only succeeds if only one of them has any data,
3737
/// or both units are identical.
38+
#[cfg(feature = "nightly")]
3839
fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> {
3940
match (self, other) {
4041
(x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x),

compiler/rustc_codegen_llvm/src/va_arg.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,14 +1171,29 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
11711171
AllowHigherAlign::Yes,
11721172
ForceRightAdjust::No,
11731173
),
1174+
Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => emit_ptr_va_arg(
1175+
bx,
1176+
addr,
1177+
target_ty,
1178+
PassMode::Direct,
1179+
match &target.llvm_abiname {
1180+
LlvmAbi::N32 | LlvmAbi::N64 => SlotSize::Bytes8,
1181+
LlvmAbi::O32 => SlotSize::Bytes4,
1182+
other => bug!("unexpected LLVM ABI {other}"),
1183+
},
1184+
AllowHigherAlign::Yes,
1185+
// In big-endian mode the actual value is stored in the right side of the slot, meaning
1186+
// that when the value is smaller than a slot, we need to adjust the pointer we read
1187+
// to somewhere in the middle of the slot.
1188+
match bx.tcx().sess.target.endian {
1189+
Endian::Big => ForceRightAdjust::Yes,
1190+
Endian::Little => ForceRightAdjust::No,
1191+
},
1192+
),
11741193

11751194
Arch::Bpf => bug!("bpf does not support c-variadic functions"),
11761195
Arch::SpirV => bug!("spirv does not support c-variadic functions"),
11771196

1178-
Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => {
1179-
// FIXME: port MipsTargetLowering::lowerVAARG.
1180-
bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))
1181-
}
11821197
Arch::Sparc | Arch::Avr | Arch::M68k | Arch::Msp430 => {
11831198
// Clang uses the LLVM implementation for these architectures.
11841199
bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))

compiler/rustc_index/src/bit_set.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use std::marker::PhantomData;
2-
#[cfg(not(feature = "nightly"))]
3-
use std::mem;
42
use std::ops::{Bound, Range, RangeBounds};
53
use std::rc::Rc;
64
use std::{fmt, iter, slice};

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,17 @@ static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
165165
return OptimizationLevel::O2;
166166
case LLVMRustPassBuilderOptLevel::O3:
167167
return OptimizationLevel::O3;
168+
#if LLVM_VERSION_GE(23, 0)
169+
case LLVMRustPassBuilderOptLevel::Os:
170+
return OptimizationLevel::O2;
171+
case LLVMRustPassBuilderOptLevel::Oz:
172+
return OptimizationLevel::O2;
173+
#else
168174
case LLVMRustPassBuilderOptLevel::Os:
169175
return OptimizationLevel::Os;
170176
case LLVMRustPassBuilderOptLevel::Oz:
171177
return OptimizationLevel::Oz;
178+
#endif
172179
default:
173180
report_fatal_error("Bad PassBuilderOptLevel.");
174181
}

compiler/rustc_mir_transform/src/unreachable_enum_branching.rs

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use rustc_abi::Variants;
44
use rustc_data_structures::fx::FxHashSet;
55
use rustc_middle::bug;
66
use rustc_middle::mir::{
7-
BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind,
8-
TerminatorKind,
7+
BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind,
98
};
109
use rustc_middle::ty::layout::TyAndLayout;
1110
use rustc_middle::ty::{Ty, TyCtxt};
@@ -125,43 +124,10 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching {
125124
unreachable_targets.push(index);
126125
}
127126
}
128-
let otherwise_is_empty_unreachable =
129-
body.basic_blocks[targets.otherwise()].is_empty_unreachable();
130-
fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool {
131-
// After resolving https://github.com/llvm/llvm-project/issues/78578,
132-
// We can remove this check.
133-
// The main issue here is that `early-tailduplication` causes compile time overhead
134-
// and potential performance problems.
135-
// Simply put, when encounter a switch (indirect branch) statement,
136-
// `early-tailduplication` tries to duplicate the switch branch statement with BB
137-
// into (each) predecessors. This makes CFG very complex.
138-
// We can understand it as it transforms the following code
139-
// ```rust
140-
// match a { ... many cases };
141-
// match b { ... many cases };
142-
// ```
143-
// into
144-
// ```rust
145-
// match a { ... many match b { goto BB cases } }
146-
// ... BB cases
147-
// ```
148-
// Abandon this transformation when it is possible (the best effort)
149-
// to encounter the problem.
150-
let mut successors = basic_blocks[bb].terminator().successors();
151-
let Some(first_successor) = successors.next() else { return true };
152-
if successors.next().is_some() {
153-
return true;
154-
}
155-
if let TerminatorKind::SwitchInt { .. } =
156-
&basic_blocks[first_successor].terminator().kind
157-
{
158-
return false;
159-
};
160-
true
161-
}
127+
162128
// If and only if there is a variant that does not have a branch set, change the
163129
// current of otherwise as the variant branch and set otherwise to unreachable. It
164-
// transforms following code
130+
// transforms the following code
165131
// ```rust
166132
// match c {
167133
// Ordering::Less => 1,
@@ -177,22 +143,16 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching {
177143
// Ordering::Greater => 3,
178144
// }
179145
// ```
180-
let otherwise_is_last_variant = !otherwise_is_empty_unreachable
181-
&& allowed_variants.len() == 1
182-
// Despite the LLVM issue, we hope that small enum can still be transformed.
183-
// This is valuable for both `a <= b` and `if let Some/Ok(v)`.
184-
&& (targets.all_targets().len() <= 3
185-
|| check_successors(&body.basic_blocks, targets.otherwise()));
186-
let replace_otherwise_to_unreachable = otherwise_is_last_variant
187-
|| (!otherwise_is_empty_unreachable && allowed_variants.is_empty());
188-
146+
let replace_otherwise_to_unreachable = allowed_variants.len() <= 1
147+
&& !body.basic_blocks[targets.otherwise()].is_empty_unreachable();
189148
if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable {
190149
continue;
191150
}
192151

193152
let unreachable_block = patch.unreachable_no_cleanup_block();
194153
let mut targets = targets.clone();
195154
if replace_otherwise_to_unreachable {
155+
let otherwise_is_last_variant = allowed_variants.len() == 1;
196156
if otherwise_is_last_variant {
197157
// We have checked that `allowed_variants` has only one element.
198158
#[allow(rustc::potential_query_instability)]

compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,10 @@ impl<T> Trait<T> for X {
606606
ty: Ty<'tcx>,
607607
) -> bool {
608608
let tcx = self.tcx;
609+
// FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
610+
if !matches!(proj_ty.kind, ty::AliasTyKind::Projection { .. }) {
611+
return false;
612+
}
609613
let Some(body_owner_def_id) = body_owner_def_id else {
610614
return false;
611615
};

library/core/src/ffi/va_list.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ crate::cfg_select! {
204204
/// unsafe fn vmy_func(count: u32, mut ap: VaList<'_>) -> i32 {
205205
/// let mut sum = 0;
206206
/// for _ in 0..count {
207-
/// sum += unsafe { ap.arg::<i32>() };
207+
/// sum += unsafe { ap.next_arg::<i32>() };
208208
/// }
209209
/// sum
210210
/// }
@@ -213,7 +213,7 @@ crate::cfg_select! {
213213
/// assert_eq!(unsafe { my_func(3, 42i32, -7i32, 20i32) }, 55);
214214
/// ```
215215
///
216-
/// The [`VaList::arg`] method reads the next argument from the variable argument list,
216+
/// The [`VaList::next_arg`] method reads the next argument from the variable argument list,
217217
/// and is equivalent to C `va_arg`.
218218
///
219219
/// Cloning a `VaList` performs the equivalent of C `va_copy`, producing an independent cursor
@@ -284,7 +284,7 @@ mod sealed {
284284
impl<T> Sealed for *const T {}
285285
}
286286

287-
/// Types that are valid to read using [`VaList::arg`].
287+
/// Types that are valid to read using [`VaList::next_arg`].
288288
///
289289
/// This trait is implemented for primitive types that have a variable argument application-binary
290290
/// interface (ABI) on the current platform. It is always implemented for:
@@ -391,7 +391,7 @@ impl<'f> VaList<'f> {
391391
/// are no more variable arguments, is unsound.
392392
#[inline] // Avoid codegen when not used to help backends that don't support VaList.
393393
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
394-
pub const unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
394+
pub const unsafe fn next_arg<T: VaArgSafe>(&mut self) -> T {
395395
// SAFETY: the caller must uphold the safety contract for `va_arg`.
396396
unsafe { va_arg(self) }
397397
}

library/core/src/num/imp/int_sqrt.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -41,36 +41,6 @@ pub(in crate::num) const fn u8(n: u8) -> u8 {
4141
U8_ISQRT_WITH_REMAINDER[n as usize].0
4242
}
4343

44-
/// Generates an `i*` function that returns the [integer square root](
45-
/// https://en.wikipedia.org/wiki/Integer_square_root) of any **nonnegative**
46-
/// input of a specific signed integer type.
47-
macro_rules! signed_fn {
48-
($SignedT:ident, $UnsignedT:ident) => {
49-
/// Returns the [integer square root](
50-
/// https://en.wikipedia.org/wiki/Integer_square_root) of any
51-
/// **nonnegative**
52-
#[doc = concat!("[`", stringify!($SignedT), "`](prim@", stringify!($SignedT), ")")]
53-
/// input.
54-
///
55-
/// # Safety
56-
///
57-
/// This results in undefined behavior when the input is negative.
58-
#[must_use = "this returns the result of the operation, \
59-
without modifying the original"]
60-
#[inline]
61-
pub(in crate::num) const unsafe fn $SignedT(n: $SignedT) -> $SignedT {
62-
debug_assert!(n >= 0, "Negative input inside `isqrt`.");
63-
$UnsignedT(n as $UnsignedT) as $SignedT
64-
}
65-
};
66-
}
67-
68-
signed_fn!(i8, u8);
69-
signed_fn!(i16, u16);
70-
signed_fn!(i32, u32);
71-
signed_fn!(i64, u64);
72-
signed_fn!(i128, u128);
73-
7444
/// Generates a `u*` function that returns the [integer square root](
7545
/// https://en.wikipedia.org/wiki/Integer_square_root) of any input of
7646
/// a specific unsigned integer type.

library/core/src/num/int_macros.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,10 +1933,9 @@ macro_rules! int_impl {
19331933
if self < 0 {
19341934
None
19351935
} else {
1936-
// SAFETY: Input is nonnegative in this `else` branch.
1937-
let result = unsafe {
1938-
imp::int_sqrt::$ActualT(self as $ActualT) as $SelfT
1939-
};
1936+
// The upper bound of `$UnsignedT::MAX.isqrt()` told to the compiler
1937+
// in the unsigned function also tells it that `result >= 0`
1938+
let result = self.cast_unsigned().isqrt().cast_signed();
19401939

19411940
// Inform the optimizer what the range of outputs is. If
19421941
// testing `core` crashes with no panic message and a
@@ -1950,15 +1949,9 @@ macro_rules! int_impl {
19501949
// `[0, <$ActualT>::MAX]`, sqrt(n) will be bounded by
19511950
// `[sqrt(0), sqrt(<$ActualT>::MAX)]`.
19521951
unsafe {
1953-
// SAFETY: `<$ActualT>::MAX` is nonnegative.
1954-
const MAX_RESULT: $SelfT = unsafe {
1955-
imp::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT
1956-
};
1957-
1958-
crate::hint::assert_unchecked(result >= 0);
1952+
const MAX_RESULT: $SelfT = <$SelfT>::MAX.cast_unsigned().isqrt().cast_signed();
19591953
crate::hint::assert_unchecked(result <= MAX_RESULT);
19601954
}
1961-
19621955
Some(result)
19631956
}
19641957
}

library/core/src/num/uint_macros.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3682,7 +3682,7 @@ macro_rules! uint_impl {
36823682
without modifying the original"]
36833683
#[inline]
36843684
pub const fn isqrt(self) -> Self {
3685-
let result = imp::int_sqrt::$ActualT(self as $ActualT) as $SelfT;
3685+
let result = imp::int_sqrt::$ActualT(self as $ActualT) as Self;
36863686

36873687
// Inform the optimizer what the range of outputs is. If testing
36883688
// `core` crashes with no panic message and a `num::int_sqrt::u*`
@@ -3693,10 +3693,29 @@ macro_rules! uint_impl {
36933693
// function, which means that increasing the input will never
36943694
// cause the output to decrease. Thus, since the input for unsigned
36953695
// integers is bounded by `[0, <$ActualT>::MAX]`, sqrt(n) will be
3696-
// bounded by `[sqrt(0), sqrt(<$ActualT>::MAX)]`.
3696+
// bounded by `[sqrt(0), sqrt(<$ActualT>::MAX)]` and bounding the
3697+
// input by `[1, <$ActualT>::MAX]` bounds sqrt(n) by
3698+
// `[sqrt(1), sqrt(<$ActualT>::MAX)]`.
36973699
unsafe {
36983700
const MAX_RESULT: $SelfT = imp::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT;
3699-
crate::hint::assert_unchecked(result <= MAX_RESULT);
3701+
crate::hint::assert_unchecked(result <= MAX_RESULT)
3702+
}
3703+
3704+
if self >= 1 {
3705+
// SAFETY: The above statements about monotonicity also apply here.
3706+
// Since the input in this branch is bounded by `[1, <$ActualT>::MAX]`,
3707+
// sqrt(n) is bounded by `[sqrt(1), sqrt(<$ActualT>::MAX)]`, and
3708+
// `sqrt(1) == 1`.
3709+
unsafe { crate::hint::assert_unchecked(result >= 1) }
3710+
}
3711+
3712+
// SAFETY: the isqrt implementation returns the square root and rounds down,
3713+
// meaning `result * result <= self`. This implies `result <= self`.
3714+
// The compiler needs both to optimize for both.
3715+
// `result * result <= self` implies the multiplication will not overflow.
3716+
unsafe {
3717+
crate::hint::assert_unchecked(result.unchecked_mul(result) <= self);
3718+
crate::hint::assert_unchecked(result <= self);
37003719
}
37013720

37023721
result

0 commit comments

Comments
 (0)