Auto merge of #85646 - Moxinilian:separate-const-switch, r=cjgillot
MIR opt: separate constant predecessors of a switch For each block S ending with a switch, this pass copies S for each of S's predecessors that seem to assign the value being switched over as a const. This is done using a somewhat simple heuristic to determine what seems to be a const transitively. More precisely, this is what the pass does: - find a block that ends in a switch - track if there is an unique place set before the current basic block that determines the result of the switch (this is the part that resolves switching over discriminants) - if there is, iterate over the parents that have a reasonable terminator and find if the found determining place is likely to be (transitively) set from a const within that parent block - if so, add the corresponding edge to a vector of edges to duplicate - once this is done, iterate over the found edges: copy the target block and replace the reference to the target block in the origin block with the new block This pass is not optimal and could probably duplicate in more cases, but the intention was mostly to address cases like in #85133 or #85365, to avoid creating new enums that get destroyed immediately afterwards (notably making the new try v2 `?` desugar zero-cost). A benefit of this pass working the way it does is that it is easy to ensure its correctness: the worst that can happen is for it to needlessly copy a basic block, which is likely to be destroyed by cleanup passes afterwards. The complex parts where aliasing matters are only heuristics and the hard work is left to further passes like ConstProp. # LLVM blocker Unfortunately, I believe it would be unwise to enable this optimization by default for now. Indeed, currently switch lowering passes like SimplifyCFG in LLVM lose the information on the set of possible variant values, which means it tends to actually generate worse code with this optimization enabled. A fix would have to be done in LLVM itself. This is something I also want to look into. I have opened [a bug report at the LLVM bug tracker](https://bugs.llvm.org/show_bug.cgi?id=50455). When this is done, I hope we can enable this pass by default. It should be fairly fast and I think it is beneficial in many cases. Notably, it should be a sound alternative to simplify-arm-identity. By the way, ConstProp only seems to pick up the optimization in functions that are not generic. This is however most likely an issue in ConstProp that I will look into afterwards. This is my first contribution to rustc, and I would like to thank everyone on the Zulip mir-opt chat for the help and support, and especially `@scottmcm` for the guidance.
This commit is contained in:
commit
70f74719a9
9 changed files with 1055 additions and 0 deletions
140
src/test/mir-opt/separate_const_switch.identity.ConstProp.diff
Normal file
140
src/test/mir-opt/separate_const_switch.identity.ConstProp.diff
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
- // MIR for `identity` before ConstProp
|
||||
+ // MIR for `identity` after ConstProp
|
||||
|
||||
fn identity(_1: Result<i32, i32>) -> Result<i32, i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:28:13: 28:14
|
||||
let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:28:37: 28:53
|
||||
let mut _2: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
let mut _5: isize; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let mut _7: !; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let mut _8: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 1 {
|
||||
debug residual => _6; // in scope 1 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
scope 2 {
|
||||
scope 8 (inlined <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug residual => _8; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _16: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _17: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _18: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 9 {
|
||||
debug e => _16; // in scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 10 (inlined <i32 as From<i32>>::from) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug t => _18; // in scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 3 {
|
||||
debug val => _9; // in scope 3 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug self => _4; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _10: isize; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _11: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _12: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _13: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _14: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _15: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 6 {
|
||||
debug v => _11; // in scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
scope 7 {
|
||||
debug e => _13; // in scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_3); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
_4 = _1; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
StorageLive(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_10 = discriminant(_4); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
switchInt(move _10) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_9 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_2 = _9; // scope 4 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_8); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_8 = _6; // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_16); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_16 = move ((_8 as Err).0: i32); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_17); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_18); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_18 = move _16; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_17 = move _18; // scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_18); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_0 as Err).0: i32) = move _17; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_0) = 1; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_17); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_16); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageLive(_13); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_13 = move ((_4 as Err).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_14); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_15); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_15 = move _13; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_14 as Err).0: i32) = move _15; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_14) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_15); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _14; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_14); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_13); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ _5 = const 1_isize; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ switchInt(const 1_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
}
|
||||
|
||||
bb4: {
|
||||
unreachable; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageLive(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_11 = move ((_4 as Ok).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_12); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_12 = move _11; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Continue).0: i32) = move _12; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 0; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_12); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ _5 = const 0_isize; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ switchInt(const 0_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
// MIR for `identity` after PreCodegen
|
||||
|
||||
fn identity(_1: Result<i32, i32>) -> Result<i32, i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:28:13: 28:14
|
||||
let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:28:37: 28:53
|
||||
let mut _2: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
let _5: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let mut _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let _7: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 1 {
|
||||
debug residual => _5; // in scope 1 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
scope 2 {
|
||||
scope 8 (inlined <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug residual => _6; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _14: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _15: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _16: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 9 {
|
||||
debug e => _14; // in scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 10 (inlined <i32 as From<i32>>::from) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug t => _16; // in scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 3 {
|
||||
debug val => _7; // in scope 3 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug self => _4; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _8: isize; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _9: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _10: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _11: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _12: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _13: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 6 {
|
||||
debug v => _9; // in scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
scope 7 {
|
||||
debug e => _11; // in scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_3); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
_4 = _1; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
StorageLive(_8); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_8 = discriminant(_4); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
switchInt(move _8) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_11 = move ((_4 as Err).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_12); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_13); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_13 = move _11; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_12 as Err).0: i32) = move _13; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_12) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_13); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _12; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_12); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_8); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_5); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_5 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_6); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_6 = _5; // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_14); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_14 = move ((_6 as Err).0: i32); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_15); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_16); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_16 = move _14; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_15 = move _16; // scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_16); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_0 as Err).0: i32) = move _15; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_0) = 1; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_15); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_14); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_6); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_5); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
|
||||
bb2: {
|
||||
unreachable; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageLive(_9); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_9 = move ((_4 as Ok).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_10); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_10 = move _9; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Continue).0: i32) = move _10; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 0; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_10); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_9); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_8); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_7); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_7 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_2 = _7; // scope 4 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_7); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
- // MIR for `identity` before SeparateConstSwitch
|
||||
+ // MIR for `identity` after SeparateConstSwitch
|
||||
|
||||
fn identity(_1: Result<i32, i32>) -> Result<i32, i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:28:13: 28:14
|
||||
let mut _0: std::result::Result<i32, i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:28:37: 28:53
|
||||
let mut _2: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _3: std::ops::ControlFlow<std::result::Result<std::convert::Infallible, i32>, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
let mut _5: isize; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let mut _7: !; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let mut _8: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 1 {
|
||||
debug residual => _6; // in scope 1 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
scope 2 {
|
||||
scope 8 (inlined <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug residual => _8; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _16: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _17: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _18: i32; // in scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 9 {
|
||||
debug e => _16; // in scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 10 (inlined <i32 as From<i32>>::from) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug t => _18; // in scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 3 {
|
||||
debug val => _9; // in scope 3 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
debug self => _4; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _10: isize; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _11: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _12: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let _13: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _14: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
let mut _15: i32; // in scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
scope 6 {
|
||||
debug v => _11; // in scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
scope 7 {
|
||||
debug e => _13; // in scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_3); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
_4 = _1; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:9
|
||||
StorageLive(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_10 = discriminant(_4); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
- switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
+ switchInt(move _10) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
- StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- switchInt(move _5) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
- }
|
||||
-
|
||||
- bb2: {
|
||||
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_9 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_2 = _9; // scope 4 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:29:5: 29:11
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
|
||||
- bb3: {
|
||||
+ bb2: {
|
||||
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_8); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
_8 = _6; // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageLive(_16); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_16 = move ((_8 as Err).0: i32); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_17); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_18); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_18 = move _16; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_17 = move _18; // scope 10 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_18); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_0 as Err).0: i32) = move _17; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_0) = 1; // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_17); // scope 9 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_16); // scope 8 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:29:10: 29:11
|
||||
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:30:1: 30:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:30:2: 30:2
|
||||
}
|
||||
|
||||
- bb4: {
|
||||
+ bb3: {
|
||||
StorageLive(_13); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_13 = move ((_4 as Err).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_14); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_15); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_15 = move _13; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_14 as Err).0: i32) = move _15; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_14) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_15); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _14; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 1; // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_14); // scope 7 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_13); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
- goto -> bb1; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
+ StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
}
|
||||
|
||||
- bb5: {
|
||||
+ bb4: {
|
||||
unreachable; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
}
|
||||
|
||||
- bb6: {
|
||||
+ bb5: {
|
||||
StorageLive(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_11 = move ((_4 as Ok).0: i32); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageLive(_12); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
_12 = move _11; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
((_3 as Continue).0: i32) = move _12; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
discriminant(_3) = 0; // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_12); // scope 6 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
StorageDead(_11); // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
- goto -> bb1; // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
+ StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
|
||||
+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
+ switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
|
||||
}
|
||||
}
|
||||
|
||||
35
src/test/mir-opt/separate_const_switch.rs
Normal file
35
src/test/mir-opt/separate_const_switch.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#![feature(control_flow_enum)]
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
// EMIT_MIR separate_const_switch.too_complex.SeparateConstSwitch.diff
|
||||
// EMIT_MIR separate_const_switch.too_complex.ConstProp.diff
|
||||
// EMIT_MIR separate_const_switch.too_complex.PreCodegen.after.mir
|
||||
fn too_complex(x: Result<i32, usize>) -> Option<i32> {
|
||||
// The pass should break the outer match into
|
||||
// two blocks that only have one parent each.
|
||||
// Parents are one of the two branches of the first
|
||||
// match, so a later pass can propagate constants.
|
||||
match {
|
||||
match x {
|
||||
Ok(v) => ControlFlow::Continue(v),
|
||||
Err(r) => ControlFlow::Break(r),
|
||||
}
|
||||
} {
|
||||
ControlFlow::Continue(v) => Some(v),
|
||||
ControlFlow::Break(r) => None,
|
||||
}
|
||||
}
|
||||
|
||||
// EMIT_MIR separate_const_switch.identity.SeparateConstSwitch.diff
|
||||
// EMIT_MIR separate_const_switch.identity.ConstProp.diff
|
||||
// EMIT_MIR separate_const_switch.identity.PreCodegen.after.mir
|
||||
fn identity(x: Result<i32, i32>) -> Result<i32, i32> {
|
||||
Ok(x?)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
too_complex(Ok(0));
|
||||
identity(Ok(0));
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
- // MIR for `too_complex` before ConstProp
|
||||
+ // MIR for `too_complex` after ConstProp
|
||||
|
||||
fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:9:16: 9:17
|
||||
let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:9:42: 9:53
|
||||
let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
let mut _3: isize; // in scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
let _4: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
let mut _5: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
let _6: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
let mut _7: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
let mut _8: isize; // in scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
let mut _10: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
let _11: usize; // in scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
scope 1 {
|
||||
debug v => _4; // in scope 1 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
}
|
||||
scope 2 {
|
||||
debug r => _6; // in scope 2 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
}
|
||||
scope 3 {
|
||||
debug v => _9; // in scope 3 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
}
|
||||
scope 4 {
|
||||
debug r => _11; // in scope 4 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
_3 = discriminant(_1); // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
_6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
_7 = _6; // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
- _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
- switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ _8 = const 1_isize; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ switchInt(const 1_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
_4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
_5 = _4; // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
- _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
- switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ _8 = const 0_isize; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ switchInt(const 0_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageLive(_11); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
_11 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
|
||||
StorageDead(_11); // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
|
||||
goto -> bb5; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
_9 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
StorageLive(_10); // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
_10 = _9; // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
StorageDead(_10); // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
goto -> bb5; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:23:1: 23:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:23:2: 23:2
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// MIR for `too_complex` after PreCodegen
|
||||
|
||||
fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:9:16: 9:17
|
||||
let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:9:42: 9:53
|
||||
let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
let mut _3: isize; // in scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
let _4: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
let mut _5: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
let _6: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
let mut _7: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
let _8: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
let mut _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
let _10: usize; // in scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
scope 1 {
|
||||
debug v => _4; // in scope 1 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
}
|
||||
scope 2 {
|
||||
debug r => _6; // in scope 2 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
}
|
||||
scope 3 {
|
||||
debug v => _8; // in scope 3 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
}
|
||||
scope 4 {
|
||||
debug r => _10; // in scope 4 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
_3 = discriminant(_1); // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
_6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
_7 = _6; // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
StorageLive(_10); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
_10 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
|
||||
StorageDead(_10); // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
|
||||
goto -> bb3; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
_4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
_5 = _4; // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
StorageLive(_8); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
_8 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
StorageLive(_9); // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
_9 = _8; // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
((_0 as Some).0: i32) = move _9; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
StorageDead(_9); // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
StorageDead(_8); // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
goto -> bb3; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:23:1: 23:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:23:2: 23:2
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
- // MIR for `too_complex` before SeparateConstSwitch
|
||||
+ // MIR for `too_complex` after SeparateConstSwitch
|
||||
|
||||
fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/separate_const_switch.rs:9:16: 9:17
|
||||
let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/separate_const_switch.rs:9:42: 9:53
|
||||
let mut _2: std::ops::ControlFlow<usize, i32>; // in scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
let mut _3: isize; // in scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
let _4: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
let mut _5: i32; // in scope 0 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
let _6: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
let mut _7: usize; // in scope 0 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
let mut _8: isize; // in scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
let mut _10: i32; // in scope 0 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
let _11: usize; // in scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
scope 1 {
|
||||
debug v => _4; // in scope 1 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
}
|
||||
scope 2 {
|
||||
debug r => _6; // in scope 2 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
}
|
||||
scope 3 {
|
||||
debug v => _9; // in scope 3 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
}
|
||||
scope 4 {
|
||||
debug r => _11; // in scope 4 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
|
||||
_3 = discriminant(_1); // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
_6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:17:17: 17:18
|
||||
StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
_7 = _6; // scope 2 at $DIR/separate_const_switch.rs:17:42: 17:43
|
||||
((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
|
||||
StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
|
||||
- goto -> bb3; // scope 0 at $DIR/separate_const_switch.rs:15:9: 18:10
|
||||
+ _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
_4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:16:16: 16:17
|
||||
StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
_5 = _4; // scope 1 at $DIR/separate_const_switch.rs:16:44: 16:45
|
||||
((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
|
||||
StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
|
||||
- goto -> bb3; // scope 0 at $DIR/separate_const_switch.rs:15:9: 18:10
|
||||
- }
|
||||
-
|
||||
- bb3: {
|
||||
_8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
- switchInt(move _8) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
+ switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
|
||||
}
|
||||
|
||||
- bb4: {
|
||||
+ bb3: {
|
||||
StorageLive(_11); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
_11 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
|
||||
discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
|
||||
StorageDead(_11); // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
|
||||
- goto -> bb6; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
+ goto -> bb5; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
- bb5: {
|
||||
+ bb4: {
|
||||
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
_9 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:20:31: 20:32
|
||||
StorageLive(_10); // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
_10 = _9; // scope 3 at $DIR/separate_const_switch.rs:20:42: 20:43
|
||||
((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
|
||||
StorageDead(_10); // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
|
||||
- goto -> bb6; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
+ goto -> bb5; // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
|
||||
}
|
||||
|
||||
- bb6: {
|
||||
+ bb5: {
|
||||
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:23:1: 23:2
|
||||
return; // scope 0 at $DIR/separate_const_switch.rs:23:2: 23:2
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue