-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of #109475 - scottmcm:simpler-shifts, r=WaffleLapkin
Simpler checked shifts in MIR building Doing masking to check unsigned shift amounts is overcomplicated; just comparing the shift directly saves a statement and a temporary, as well as is much easier to read as a human. And shifting by unsigned is the canonical case -- notably, all the library shifting methods (that don't support every type) take shift RHSs as `u32` -- so we might as well make that simpler since it's easy to do so. This PR also changes *signed* shift amounts to `IntToInt` casts and then uses the same check as for unsigned. The bit-masking is a nice trick, but for example LLVM actually canonicalizes it to an unsigned comparison anyway <https://rust.godbolt.org/z/8h59fMGT4> so I don't think it's worth the effort and the extra `Constant`. (If MIR's `assert` was `assert_nz` then the masking might make sense, but when the `!=` uses another statement I think the comparison is better.) To review, I suggest looking at 2ee0468 first -- that's the interesting code change and has a MIR diff. My favourite part of the diff: ```diff - _20 = BitAnd(_19, const 340282366920938463463374607431768211448_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 - _21 = Ne(move _20, const 0_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 - assert(!move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + _18 = Lt(_17, const 8_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 + assert(move _18, "attempt to shift right by `{}`, which would overflow", _17) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 ```
- Loading branch information
Showing
6 changed files
with
371 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// compile-flags: -C debug-assertions=yes | ||
|
||
// EMIT_MIR shifts.shift_signed.built.after.mir | ||
fn shift_signed(small: i8, big: u128, a: i8, b: i32, c: i128) -> ([i8; 3], [u128; 3]) { | ||
( | ||
[small >> a, small >> b, small >> c], | ||
[big << a, big << b, big << c], | ||
) | ||
} | ||
|
||
// EMIT_MIR shifts.shift_unsigned.built.after.mir | ||
fn shift_unsigned(small: u8, big: i128, a: u8, b: u32, c: u128) -> ([u8; 3], [i128; 3]) { | ||
( | ||
[small >> a, small >> b, small >> c], | ||
[big << a, big << b, big << c], | ||
) | ||
} | ||
|
||
fn main() { | ||
} |
147 changes: 147 additions & 0 deletions
147
tests/mir-opt/building/shifts.shift_signed.built.after.mir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
// MIR for `shift_signed` after built | ||
|
||
fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; 3]) { | ||
debug small => _1; // in scope 0 at $DIR/shifts.rs:+0:17: +0:22 | ||
debug big => _2; // in scope 0 at $DIR/shifts.rs:+0:28: +0:31 | ||
debug a => _3; // in scope 0 at $DIR/shifts.rs:+0:39: +0:40 | ||
debug b => _4; // in scope 0 at $DIR/shifts.rs:+0:46: +0:47 | ||
debug c => _5; // in scope 0 at $DIR/shifts.rs:+0:54: +0:55 | ||
let mut _0: ([i8; 3], [u128; 3]); // return place in scope 0 at $DIR/shifts.rs:+0:66: +0:86 | ||
let mut _6: [i8; 3]; // in scope 0 at $DIR/shifts.rs:+2:9: +2:45 | ||
let mut _7: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 | ||
let mut _8: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:15 | ||
let mut _9: i8; // in scope 0 at $DIR/shifts.rs:+2:19: +2:20 | ||
let mut _10: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 | ||
let mut _11: bool; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20 | ||
let mut _12: i8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 | ||
let mut _13: i8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:27 | ||
let mut _14: i32; // in scope 0 at $DIR/shifts.rs:+2:31: +2:32 | ||
let mut _15: u32; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 | ||
let mut _16: bool; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32 | ||
let mut _17: i8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 | ||
let mut _18: i8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:39 | ||
let mut _19: i128; // in scope 0 at $DIR/shifts.rs:+2:43: +2:44 | ||
let mut _20: u128; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 | ||
let mut _21: bool; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44 | ||
let mut _22: [u128; 3]; // in scope 0 at $DIR/shifts.rs:+3:9: +3:39 | ||
let mut _23: u128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 | ||
let mut _24: u128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:13 | ||
let mut _25: i8; // in scope 0 at $DIR/shifts.rs:+3:17: +3:18 | ||
let mut _26: u8; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 | ||
let mut _27: bool; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18 | ||
let mut _28: u128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 | ||
let mut _29: u128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:23 | ||
let mut _30: i32; // in scope 0 at $DIR/shifts.rs:+3:27: +3:28 | ||
let mut _31: u32; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 | ||
let mut _32: bool; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28 | ||
let mut _33: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 | ||
let mut _34: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:33 | ||
let mut _35: i128; // in scope 0 at $DIR/shifts.rs:+3:37: +3:38 | ||
let mut _36: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 | ||
let mut _37: bool; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38 | ||
|
||
bb0: { | ||
StorageLive(_6); // scope 0 at $DIR/shifts.rs:+2:9: +2:45 | ||
StorageLive(_7); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 | ||
StorageLive(_8); // scope 0 at $DIR/shifts.rs:+2:10: +2:15 | ||
_8 = _1; // scope 0 at $DIR/shifts.rs:+2:10: +2:15 | ||
StorageLive(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 | ||
_9 = _3; // scope 0 at $DIR/shifts.rs:+2:19: +2:20 | ||
_10 = _9 as u8 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 | ||
_11 = Lt(move _10, const 8_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 | ||
assert(move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20 | ||
} | ||
|
||
bb1: { | ||
_7 = Shr(move _8, move _9); // scope 0 at $DIR/shifts.rs:+2:10: +2:20 | ||
StorageDead(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 | ||
StorageDead(_8); // scope 0 at $DIR/shifts.rs:+2:19: +2:20 | ||
StorageLive(_12); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 | ||
StorageLive(_13); // scope 0 at $DIR/shifts.rs:+2:22: +2:27 | ||
_13 = _1; // scope 0 at $DIR/shifts.rs:+2:22: +2:27 | ||
StorageLive(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 | ||
_14 = _4; // scope 0 at $DIR/shifts.rs:+2:31: +2:32 | ||
_15 = _14 as u32 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 | ||
_16 = Lt(move _15, const 8_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 | ||
assert(move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32 | ||
} | ||
|
||
bb2: { | ||
_12 = Shr(move _13, move _14); // scope 0 at $DIR/shifts.rs:+2:22: +2:32 | ||
StorageDead(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 | ||
StorageDead(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32 | ||
StorageLive(_17); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 | ||
StorageLive(_18); // scope 0 at $DIR/shifts.rs:+2:34: +2:39 | ||
_18 = _1; // scope 0 at $DIR/shifts.rs:+2:34: +2:39 | ||
StorageLive(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 | ||
_19 = _5; // scope 0 at $DIR/shifts.rs:+2:43: +2:44 | ||
_20 = _19 as u128 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 | ||
_21 = Lt(move _20, const 8_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 | ||
assert(move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44 | ||
} | ||
|
||
bb3: { | ||
_17 = Shr(move _18, move _19); // scope 0 at $DIR/shifts.rs:+2:34: +2:44 | ||
StorageDead(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 | ||
StorageDead(_18); // scope 0 at $DIR/shifts.rs:+2:43: +2:44 | ||
_6 = [move _7, move _12, move _17]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45 | ||
StorageDead(_17); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 | ||
StorageDead(_12); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 | ||
StorageDead(_7); // scope 0 at $DIR/shifts.rs:+2:44: +2:45 | ||
StorageLive(_22); // scope 0 at $DIR/shifts.rs:+3:9: +3:39 | ||
StorageLive(_23); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 | ||
StorageLive(_24); // scope 0 at $DIR/shifts.rs:+3:10: +3:13 | ||
_24 = _2; // scope 0 at $DIR/shifts.rs:+3:10: +3:13 | ||
StorageLive(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 | ||
_25 = _3; // scope 0 at $DIR/shifts.rs:+3:17: +3:18 | ||
_26 = _25 as u8 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 | ||
_27 = Lt(move _26, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 | ||
assert(move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18 | ||
} | ||
|
||
bb4: { | ||
_23 = Shl(move _24, move _25); // scope 0 at $DIR/shifts.rs:+3:10: +3:18 | ||
StorageDead(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 | ||
StorageDead(_24); // scope 0 at $DIR/shifts.rs:+3:17: +3:18 | ||
StorageLive(_28); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 | ||
StorageLive(_29); // scope 0 at $DIR/shifts.rs:+3:20: +3:23 | ||
_29 = _2; // scope 0 at $DIR/shifts.rs:+3:20: +3:23 | ||
StorageLive(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 | ||
_30 = _4; // scope 0 at $DIR/shifts.rs:+3:27: +3:28 | ||
_31 = _30 as u32 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 | ||
_32 = Lt(move _31, const 128_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 | ||
assert(move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28 | ||
} | ||
|
||
bb5: { | ||
_28 = Shl(move _29, move _30); // scope 0 at $DIR/shifts.rs:+3:20: +3:28 | ||
StorageDead(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 | ||
StorageDead(_29); // scope 0 at $DIR/shifts.rs:+3:27: +3:28 | ||
StorageLive(_33); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 | ||
StorageLive(_34); // scope 0 at $DIR/shifts.rs:+3:30: +3:33 | ||
_34 = _2; // scope 0 at $DIR/shifts.rs:+3:30: +3:33 | ||
StorageLive(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 | ||
_35 = _5; // scope 0 at $DIR/shifts.rs:+3:37: +3:38 | ||
_36 = _35 as u128 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 | ||
_37 = Lt(move _36, const 128_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 | ||
assert(move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38 | ||
} | ||
|
||
bb6: { | ||
_33 = Shl(move _34, move _35); // scope 0 at $DIR/shifts.rs:+3:30: +3:38 | ||
StorageDead(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 | ||
StorageDead(_34); // scope 0 at $DIR/shifts.rs:+3:37: +3:38 | ||
_22 = [move _23, move _28, move _33]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39 | ||
StorageDead(_33); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 | ||
StorageDead(_28); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 | ||
StorageDead(_23); // scope 0 at $DIR/shifts.rs:+3:38: +3:39 | ||
_0 = (move _6, move _22); // scope 0 at $DIR/shifts.rs:+1:5: +4:6 | ||
StorageDead(_22); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 | ||
StorageDead(_6); // scope 0 at $DIR/shifts.rs:+4:5: +4:6 | ||
return; // scope 0 at $DIR/shifts.rs:+5:2: +5:2 | ||
} | ||
|
||
bb7 (cleanup): { | ||
resume; // scope 0 at $DIR/shifts.rs:+0:1: +5:2 | ||
} | ||
} |
Oops, something went wrong.