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
9 changes: 9 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
Version 1.96.1 (2026-06-30)
===========================

<a id="1.96.1"></a>

- [Cargo: fix timeout/retry behavior](https://github.com/rust-lang/cargo/pull/17131)
- [Cargo: apply patches for CVE-2025-15661, CVE-2026-55199, and CVE-2026-55200 to libssh2](https://github.com/rust-lang/cargo/pull/17140)
- [rustc: fix miscompilation in MIR optimization](https://github.com/rust-lang/rust/pull/158214)

Version 1.96.0 (2026-05-28)
==========================

Expand Down
46 changes: 18 additions & 28 deletions compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,30 +76,24 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
_ => unreachable!(),
}

// delete comparison statement if it the value being switched on was moved, which means
// it can not be used later on
if opt.can_remove_bin_op_stmt {
bb.statements[opt.bin_op_stmt_idx].make_nop(true);
} else {
// if the integer being compared to a const integral is being moved into the
// comparison, e.g `_2 = Eq(move _3, const 'x');`
// we want to avoid making a double move later on in the switchInt on _3.
// So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`,
// we convert the move in the comparison statement to a copy.

// unwrap is safe as we know this statement is an assign
let (_, rhs) = bb.statements[opt.bin_op_stmt_idx].kind.as_assign_mut().unwrap();

use Operand::*;
match rhs {
Rvalue::BinaryOp(_, box (left @ Move(_), Constant(_))) => {
*left = Copy(opt.to_switch_on);
}
Rvalue::BinaryOp(_, box (Constant(_), right @ Move(_))) => {
*right = Copy(opt.to_switch_on);
}
_ => (),
// if the integer being compared to a const integral is being moved into the
// comparison, e.g `_2 = Eq(move _3, const 'x');`
// we want to avoid making a double move later on in the switchInt on _3.
// So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`,
// we convert the move in the comparison statement to a copy.

// unwrap is safe as we know this statement is an assign
let (_, rhs) = bb.statements[opt.bin_op_stmt_idx].kind.as_assign_mut().unwrap();

use Operand::*;
match rhs {
Rvalue::BinaryOp(_, box (left @ Move(_), Constant(_))) => {
*left = Copy(opt.to_switch_on);
}
Rvalue::BinaryOp(_, box (Constant(_), right @ Move(_))) => {
*right = Copy(opt.to_switch_on);
}
_ => (),
}

let terminator = bb.terminator();
Expand Down Expand Up @@ -187,7 +181,6 @@ impl<'tcx> OptimizationFinder<'_, 'tcx> {
Some(OptimizationInfo {
bin_op_stmt_idx: stmt_idx,
bb_idx,
can_remove_bin_op_stmt: discr.is_move(),
to_switch_on,
branch_value_scalar,
branch_value_ty,
Expand Down Expand Up @@ -238,11 +231,8 @@ fn find_branch_value_info<'tcx>(
struct OptimizationInfo<'tcx> {
/// Basic block to apply the optimization
bb_idx: BasicBlock,
/// Statement index of Eq/Ne assignment that can be removed. None if the assignment can not be
/// removed - i.e the statement is used later on
/// Statement index of Eq/Ne assignment
bin_op_stmt_idx: usize,
/// Can remove Eq/Ne assignment
can_remove_bin_op_stmt: bool,
/// Place that needs to be switched on. This place is of type integral
to_switch_on: Place<'tcx>,
/// Constant to use in switch target value
Expand Down
2 changes: 1 addition & 1 deletion src/tools/cargo
Submodule cargo updated 473 files
2 changes: 1 addition & 1 deletion src/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.96.0
1.96.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
- // MIR for `dont_remove_moved_comparison` before SimplifyComparisonIntegral
+ // MIR for `dont_remove_moved_comparison` after SimplifyComparisonIntegral

fn dont_remove_moved_comparison(_1: i8) -> i32 {
let mut _0: i32;
let mut _2: bool;
let mut _3: i32;
let mut _4: i32;

bb0: {
_2 = Eq(copy _1, const 17_i8);
_3 = copy _2 as i32 (IntToInt);
- switchInt(move _2) -> [1: bb1, otherwise: bb2];
+ switchInt(copy _1) -> [17: bb1, otherwise: bb2];
}

bb1: {
_0 = copy _3;
return;
}

bb2: {
_0 = Add(copy _3, const 1_i32);
return;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
StorageLive(_2);
StorageLive(_3);
_3 = copy _1;
- _2 = Eq(copy _1, const 'x');
_2 = Eq(copy _1, const 'x');
- switchInt(move _2) -> [0: bb2, otherwise: bb1];
+ nop;
+ switchInt(copy _1) -> [120: bb1, otherwise: bb2];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
StorageLive(_2);
StorageLive(_3);
_3 = copy _1;
- _2 = Eq(copy _1, const 42_i8);
_2 = Eq(copy _1, const 42_i8);
- switchInt(move _2) -> [0: bb2, otherwise: bb1];
+ nop;
+ switchInt(copy _1) -> [42: bb1, otherwise: bb2];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
StorageLive(_2);
StorageLive(_3);
_3 = copy _1;
- _2 = Eq(copy _1, const 42_u32);
_2 = Eq(copy _1, const 42_u32);
- switchInt(move _2) -> [0: bb2, otherwise: bb1];
+ nop;
+ switchInt(copy _1) -> [42: bb1, otherwise: bb2];
}

Expand All @@ -30,9 +29,8 @@
StorageLive(_4);
StorageLive(_5);
_5 = copy _1;
- _4 = Ne(copy _1, const 21_u32);
_4 = Ne(copy _1, const 21_u32);
- switchInt(move _4) -> [0: bb4, otherwise: bb3];
+ nop;
+ switchInt(copy _1) -> [21: bb4, otherwise: bb3];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
StorageLive(_2);
StorageLive(_3);
_3 = copy _1;
- _2 = Eq(copy _1, const -42_i32);
_2 = Eq(copy _1, const -42_i32);
- switchInt(move _2) -> [0: bb2, otherwise: bb1];
+ nop;
+ switchInt(copy _1) -> [4294967254: bb1, otherwise: bb2];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
StorageLive(_2);
StorageLive(_3);
_3 = copy _1;
- _2 = Eq(copy _1, const 42_u32);
_2 = Eq(copy _1, const 42_u32);
- switchInt(move _2) -> [0: bb2, otherwise: bb1];
+ nop;
+ switchInt(copy _1) -> [42: bb1, otherwise: bb2];
}

Expand Down
38 changes: 37 additions & 1 deletion tests/mir-opt/if_condition_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ fn opt_multiple_ifs(x: u32) -> u32 {
}

// EMIT_MIR if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
// test that we optimize, but do not remove the b statement, as that is used later on
// the switchInt can be optimized but the b statement can't be removed as it's used later on
fn dont_remove_comparison(a: i8) -> i32 {
// CHECK-LABEL: fn dont_remove_comparison(
// CHECK: [[b:_.*]] = Eq(copy _1, const 17_i8);
Expand All @@ -103,6 +103,42 @@ fn dont_remove_comparison(a: i8) -> i32 {
}
}

// EMIT_MIR if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff
// like dont_remove_comparison above, but with switchInt(move _N) - regression test for #158206
#[custom_mir(dialect = "runtime")]
fn dont_remove_moved_comparison(a: i8) -> i32 {
// CHECK-LABEL: fn dont_remove_moved_comparison(
// CHECK: [[b:_.*]] = Eq(copy _1, const 17_i8);
// CHECK: [[cast:_.*]] = copy [[b]] as i32 (IntToInt);
// CHECK: switchInt(copy _1) -> [17: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]];
// CHECK: [[BB1]]:
// CHECK: _0 = copy [[cast]];
// CHECK: [[BB2]]:
// CHECK: _0 = Add(copy [[cast]], const 1_i32);
mir! {
let b: bool;
let c: i32;
let d: i32;
{
b = a == 17;
c = b as i32;
match Move(b) {
true => bb1,
_ => bb2,
}

}
bb1 = {
RET = c;
Return()
}
bb2 = {
RET = c + 1;
Return()
}
}
}

// EMIT_MIR if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
// test that we do not optimize on floats
fn dont_opt_floats(a: f32) -> i32 {
Expand Down
Loading