Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 11ee3a8

Browse files
committed
Auto merge of #131201 - compiler-errors:unop-not, r=cjgillot
Disable jump threading `UnOp::Not` for non-bool Fix #131195, where jumpthreading was optimizing `!a == b` into `a != b` for non-bool, where this is definitely not true.
2 parents 7067e4a + f0bfba2 commit 11ee3a8

File tree

4 files changed

+111
-0
lines changed

4 files changed

+111
-0
lines changed

‎compiler/rustc_mir_transform/src/jump_threading.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,8 +494,16 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
494494
}
495495
// Transfer the conditions on the copy rhs, after inversing polarity.
496496
Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => {
497+
if !place.ty(self.body, self.tcx).ty.is_bool() {
498+
// Constructing the conditions by inverting the polarity
499+
// of equality is only correct for bools. That is to say,
500+
// `!a == b` is not `a != b` for integers greater than 1 bit.
501+
return;
502+
}
497503
let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return };
498504
let Some(place) = self.map.find(place.as_ref()) else { return };
505+
// FIXME: I think This could be generalized to not bool if we
506+
// actually perform a logical not on the condition's value.
499507
let conds = conditions.map(self.arena, Condition::inv);
500508
state.insert_value_idx(place, conds, &self.map);
501509
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
- // MIR for `bitwise_not` before JumpThreading
2+
+ // MIR for `bitwise_not` after JumpThreading
3+
4+
fn bitwise_not() -> i32 {
5+
let mut _0: i32;
6+
let mut _1: i32;
7+
let mut _2: bool;
8+
let mut _3: i32;
9+
let mut _4: i32;
10+
scope 1 {
11+
debug a => _1;
12+
}
13+
14+
bb0: {
15+
StorageLive(_1);
16+
_1 = const 0_i32;
17+
_1 = const 1_i32;
18+
StorageLive(_2);
19+
StorageLive(_3);
20+
StorageLive(_4);
21+
_4 = copy _1;
22+
_3 = Not(move _4);
23+
StorageDead(_4);
24+
_2 = Eq(move _3, const 0_i32);
25+
switchInt(move _2) -> [0: bb2, otherwise: bb1];
26+
}
27+
28+
bb1: {
29+
StorageDead(_3);
30+
_0 = const 1_i32;
31+
goto -> bb3;
32+
}
33+
34+
bb2: {
35+
StorageDead(_3);
36+
_0 = const 0_i32;
37+
goto -> bb3;
38+
}
39+
40+
bb3: {
41+
StorageDead(_2);
42+
StorageDead(_1);
43+
return;
44+
}
45+
}
46+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
- // MIR for `bitwise_not` before JumpThreading
2+
+ // MIR for `bitwise_not` after JumpThreading
3+
4+
fn bitwise_not() -> i32 {
5+
let mut _0: i32;
6+
let mut _1: i32;
7+
let mut _2: bool;
8+
let mut _3: i32;
9+
let mut _4: i32;
10+
scope 1 {
11+
debug a => _1;
12+
}
13+
14+
bb0: {
15+
StorageLive(_1);
16+
_1 = const 0_i32;
17+
_1 = const 1_i32;
18+
StorageLive(_2);
19+
StorageLive(_3);
20+
StorageLive(_4);
21+
_4 = copy _1;
22+
_3 = Not(move _4);
23+
StorageDead(_4);
24+
_2 = Eq(move _3, const 0_i32);
25+
switchInt(move _2) -> [0: bb2, otherwise: bb1];
26+
}
27+
28+
bb1: {
29+
StorageDead(_3);
30+
_0 = const 1_i32;
31+
goto -> bb3;
32+
}
33+
34+
bb2: {
35+
StorageDead(_3);
36+
_0 = const 0_i32;
37+
goto -> bb3;
38+
}
39+
40+
bb3: {
41+
StorageDead(_2);
42+
StorageDead(_1);
43+
return;
44+
}
45+
}
46+

‎tests/mir-opt/jump_threading.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,16 @@ fn floats() -> u32 {
531531
if x == 0.0 { 0 } else { 1 }
532532
}
533533

534+
pub fn bitwise_not() -> i32 {
535+
// CHECK-LABEL: fn bitwise_not(
536+
// CHECK: switchInt(
537+
538+
// Test for #131195, which was optimizing `!a == b` into `a != b`.
539+
let mut a: i32 = 0;
540+
a = 1;
541+
if !a == 0 { 1 } else { 0 }
542+
}
543+
534544
fn main() {
535545
// CHECK-LABEL: fn main(
536546
too_complex(Ok(0));
@@ -562,3 +572,4 @@ fn main() {
562572
// EMIT_MIR jump_threading.assume.JumpThreading.diff
563573
// EMIT_MIR jump_threading.aggregate_copy.JumpThreading.diff
564574
// EMIT_MIR jump_threading.floats.JumpThreading.diff
575+
// EMIT_MIR jump_threading.bitwise_not.JumpThreading.diff

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /