From f0bfba258330884df9c9d14a0aafd741ca9bbdc9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 3 Oct 2024 09:47:06 -0400 Subject: [PATCH] Disable jump threading UnOp::Not for non-bool --- .../rustc_mir_transform/src/jump_threading.rs | 8 ++++ ...bitwise_not.JumpThreading.panic-abort.diff | 46 +++++++++++++++++++ ...itwise_not.JumpThreading.panic-unwind.diff | 3 +- 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 1844b97887a..9b9b0b705bf 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -494,8 +494,16 @@ fn process_assign( } // Transfer the conditions on the copy rhs, after inversing polarity. Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => { + if !place.ty(self.body, self.tcx).ty.is_bool() { + // Constructing the conditions by inverting the polarity + // of equality is only correct for bools. That is to say, + // `!a == b` is not `a != b` for integers greater than 1 bit. + return; + } let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return }; let Some(place) = self.map.find(place.as_ref()) else { return }; + // FIXME: I think This could be generalized to not bool if we + // actually perform a logical not on the condition's value. let conds = conditions.map(self.arena, Condition::inv); state.insert_value_idx(place, conds, &self.map); } diff --git a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff new file mode 100644 index 00000000000..047441e6099 --- /dev/null +++ b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff @@ -0,0 +1,46 @@ +- // MIR for `bitwise_not` before JumpThreading ++ // MIR for `bitwise_not` after JumpThreading + + fn bitwise_not() -> i32 { + let mut _0: i32; + let mut _1: i32; + let mut _2: bool; + let mut _3: i32; + let mut _4: i32; + scope 1 { + debug a => _1; + } + + bb0: { + StorageLive(_1); + _1 = const 0_i32; + _1 = const 1_i32; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + _3 = Not(move _4); + StorageDead(_4); + _2 = Eq(move _3, const 0_i32); + switchInt(move _2) -> [0: bb2, otherwise: bb1]; + } + + bb1: { + StorageDead(_3); + _0 = const 1_i32; + goto -> bb3; + } + + bb2: { + StorageDead(_3); + _0 = const 0_i32; + goto -> bb3; + } + + bb3: { + StorageDead(_2); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff index fb64fff7e11..047441e6099 100644 --- a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff @@ -22,8 +22,7 @@ _3 = Not(move _4); StorageDead(_4); _2 = Eq(move _3, const 0_i32); -- switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ goto -> bb1; + switchInt(move _2) -> [0: bb2, otherwise: bb1]; } bb1: {