Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a more efficient iteration order for forward dataflow #62062

Merged
merged 1 commit into from Jul 1, 2019

Conversation

Projects
None yet
8 participants
@ecstatic-morse
Copy link
Contributor

commented Jun 22, 2019

Currently, dataflow begins by visiting each block in order of ID (BasicBlock(0), BasicBlock(1), etc.). This PR changes that initial iteration to reverse post-order (see this blog post for more info). This ensures that the effects of all predecessors will be applied before a basic block is visited if the CFG has no back-edges, and should result in less total iterations even when back-edges exist. This should not change the results of dataflow analysis.

The current ordering for basic blocks may be pretty close to RPO already--BasicBlock(0) is already the start block--in which case the cost of doing the traversal up front will outweigh the efficiency gains.
A perf run is needed to check this.

r? @pnkfelix (I think).

ecstatic-morse added a commit to ecstatic-morse/rust that referenced this pull request Jun 22, 2019

Use more efficient iteration order for backward dataflow
This applies the same basic principle as rust-lang#62062 to the reverse dataflow
analysis used to compute liveness information. It is functionally
equivalent, except that post-order is used instead of reverse post-order.
@nagisa

This comment was marked as resolved.

Copy link
Contributor

commented Jun 22, 2019

@bors try

@bors

This comment was marked as outdated.

Copy link
Contributor

commented Jun 22, 2019

⌛️ Trying commit 70e83b1 with merge d158313...

bors added a commit that referenced this pull request Jun 22, 2019

Auto merge of #62062 - ecstatic-morse:dataflow-order, r=<try>
Use a more efficient iteration order for forward dataflow

Currently, dataflow begins by visiting each block in order of ID (`BasicBlock(0)`, `BasicBlock(1)`, etc.). This PR changes that initial iteration to reverse post-order (see [this blog post](https://eli.thegreenplace.net/2015/directed-graph-traversal-orderings-and-applications-to-data-flow-analysis/#data-flow-analysis) for more info). This ensures that the effects of all predecessors will be applied before a basic block is visited if the CFG has no back-edges, and should result in less total iterations even when back-edges exist. This should not change the results of dataflow analysis.

The current ordering for basic blocks may be pretty close to RPO already--`BasicBlock(0)` is already the start block--in which case the cost of doing the traversal up front will outweigh the efficiency gains.
A perf run is needed to check this.

r? @pnkfelix (I think).

bors added a commit that referenced this pull request Jun 22, 2019

Auto merge of #62063 - ecstatic-morse:dataflow-backward-order, r=<try>
Use a more efficient iteration order for backward dataflow

This applies the same basic principle as #62062 to the reverse dataflow analysis used to compute liveness information. It is functionally equivalent, except that post-order is used instead of reverse post-order.

In the long-term, `BitDenotation` should probably be extended to support both forward and backward dataflow, but there's some more work needed to get to that point.
@ecstatic-morse

This comment has been minimized.

Copy link
Contributor Author

commented Jun 22, 2019

@nagisa. Do you think the assertion about unreachable basic blocks is correct? I added it because there could be two successive basic blocks which are unreachable from the start block, in which case the entry set for the second one would be wrong.

@bors

This comment was marked as outdated.

Copy link
Contributor

commented Jun 22, 2019

💔 Test failed - checks-travis

@rust-highfive

This comment was marked as outdated.

Copy link
Collaborator

commented Jun 22, 2019

Your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_fold:end:services

travis_fold:start:git.checkout
travis_time:start:00db9d3b
$ git clone --depth=2 --branch=try https://github.com/rust-lang/rust.git rust-lang/rust
---
Cloning into 'rust-lang/rust'...
travis_time:end:00db9d3b:start=1561236884528252885,finish=1561236890454781640,duration=5926528755
$ cd rust-lang/rust
$ git checkout -qf d15831326c415cfe964abe98915d89282a0db597
fatal: reference is not a tree: d15831326c415cfe964abe98915d89282a0db597
The command "git checkout -qf d15831326c415cfe964abe98915d89282a0db597" failed and exited with 128 during .
Your build has been stopped.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@nagisa

This comment was marked as resolved.

Copy link
Contributor

commented Jun 22, 2019

@bors try

@bors

This comment was marked as outdated.

Copy link
Contributor

commented Jun 22, 2019

⌛️ Trying commit 70e83b1 with merge 93b672c...

bors added a commit that referenced this pull request Jun 22, 2019

Auto merge of #62062 - ecstatic-morse:dataflow-order, r=<try>
Use a more efficient iteration order for forward dataflow

Currently, dataflow begins by visiting each block in order of ID (`BasicBlock(0)`, `BasicBlock(1)`, etc.). This PR changes that initial iteration to reverse post-order (see [this blog post](https://eli.thegreenplace.net/2015/directed-graph-traversal-orderings-and-applications-to-data-flow-analysis/#data-flow-analysis) for more info). This ensures that the effects of all predecessors will be applied before a basic block is visited if the CFG has no back-edges, and should result in less total iterations even when back-edges exist. This should not change the results of dataflow analysis.

The current ordering for basic blocks may be pretty close to RPO already--`BasicBlock(0)` is already the start block--in which case the cost of doing the traversal up front will outweigh the efficiency gains.
A perf run is needed to check this.

r? @pnkfelix (I think).
@rust-highfive

This comment was marked as outdated.

Copy link
Collaborator

commented Jun 22, 2019

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:077e1133:start=1561234594623482435,finish=1561234595391971367,duration=768488932
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
$ export GCP_CACHE_BUCKET=rust-lang-ci-cache
$ export AWS_ACCESS_KEY_ID=AKIA46X5W6CZEJZ6XT55
---
[00:59:03] .................................................................................................... 500/2922
[00:59:14] .................................................................................................... 600/2922
[00:59:29] .................................................................................................... 700/2922
[00:59:40] .................................................................................................... 800/2922
[00:59:48] .............................................F...............F..F................................... 900/2922
[01:00:13] .................................................................................................... 1100/2922
[01:00:22] .................................................................................................... 1200/2922
[01:00:32] .................................................................................................... 1300/2922
[01:00:44] ......................ii............................................................................ 1400/2922
---
[01:04:33] failures:
[01:04:33] 
[01:04:33] ---- [run-pass] run-pass/generator/drop-env.rs stdout ----
[01:04:33] 
[01:04:33] error: test compilation failed although it shouldn't!
[01:04:33] status: exit code: 101
[01:04:33] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/run-pass/generator/drop-env.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass/generator/drop-env/a" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass/generator/drop-env/auxiliary"
[01:04:33] ------------------------------------------
[01:04:33] 
[01:04:33] ------------------------------------------
[01:04:33] stderr:
[01:04:33] stderr:
[01:04:33] ------------------------------------------
[01:04:33] thread 'rustc' panicked at 'Unreachable basic blocks during dataflow analysis', src/librustc_mir/dataflow/mod.rs:260:9
[01:04:33] 
[01:04:33] error: internal compiler error: unexpected panic
[01:04:33] 
[01:04:33] note: the compiler unexpectedly panicked. this is a bug.
[01:04:33] note: the compiler unexpectedly panicked. this is a bug.
[01:04:33] 
[01:04:33] note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
[01:04:33] 
[01:04:33] note: rustc 1.37.0-dev running on x86_64-unknown-linux-gnu
[01:04:33] 
[01:04:33] note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0
[01:04:33] 
[01:04:33] ------------------------------------------
[01:04:33] 
[01:04:33] 
[01:04:33] 
[01:04:33] ---- [run-pass] run-pass/generator/smoke.rs stdout ----
[01:04:33] 
[01:04:33] error: test compilation failed although it shouldn't!
[01:04:33] status: exit code: 101
[01:04:33] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/run-pass/generator/smoke.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass/generator/smoke/a" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--test" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass/generator/smoke/auxiliary"
[01:04:33] ------------------------------------------
[01:04:33] 
[01:04:33] ------------------------------------------
[01:04:33] stderr:
[01:04:33] stderr:
[01:04:33] ------------------------------------------
[01:04:33] thread 'rustc' panicked at 'Unreachable basic blocks during dataflow analysis', src/librustc_mir/dataflow/mod.rs:260:9
[01:04:33] 
[01:04:33] error: internal compiler error: unexpected panic
[01:04:33] 
[01:04:33] note: the compiler unexpectedly panicked. this is a bug.
[01:04:33] note: the compiler unexpectedly panicked. this is a bug.
[01:04:33] 
[01:04:33] note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
[01:04:33] 
[01:04:33] note: rustc 1.37.0-dev running on x86_64-unknown-linux-gnu
[01:04:33] 
[01:04:33] note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0
[01:04:33] 
[01:04:33] ------------------------------------------
[01:04:33] 
[01:04:33] 
[01:04:33] 
[01:04:33] ---- [run-pass] run-pass/generator/xcrate.rs stdout ----
[01:04:33] 
[01:04:33] error: auxiliary build of "/checkout/src/test/run-pass/generator/auxiliary/xcrate.rs" failed to compile: 
[01:04:33] status: exit code: 101
[01:04:33] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/run-pass/generator/auxiliary/xcrate.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass/generator/xcrate/auxiliary" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--crate-type" "dylib" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass/generator/xcrate/auxiliary"
[01:04:33] ------------------------------------------
[01:04:33] 
[01:04:33] ------------------------------------------
[01:04:33] stderr:
[01:04:33] stderr:
[01:04:33] ------------------------------------------
[01:04:33] warning: trait objects without an explicit `dyn` are deprecated
[01:04:33]   --> /checkout/src/test/run-pass/generator/auxiliary/xcrate.rs:14:37
[01:04:33]    |
[01:04:33] LL | pub fn bar<T: 'static>(t: T) -> Box<Generator<Yield = T, Return = ()> + Unpin> {
[01:04:33]    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn Generator<Yield = T, Return = ()> + Unpin`
[01:04:33]    = note: #[warn(bare_trait_objects)] on by default
[01:04:33] 
[01:04:33] 
[01:04:33] thread 'rustc' panicked at 'Unreachable basic blocks during dataflow analysis', src/librustc_mir/dataflow/mod.rs:260:9
[01:04:33] 
[01:04:33] error: internal compiler error: unexpected panic
[01:04:33] 
[01:04:33] note: the compiler unexpectedly panicked. this is a bug.
[01:04:33] note: the compiler unexpectedly panicked. this is a bug.
[01:04:33] 
[01:04:33] note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
[01:04:33] 
[01:04:33] note: rustc 1.37.0-dev running on x86_64-unknown-linux-gnu
[01:04:33] 
[01:04:33] note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 --crate-type dylib
[01:04:33] 
[01:04:33] ------------------------------------------
[01:04:33] 
[01:04:33] 
---
[01:04:33] thread 'main' panicked at 'Some tests failed', src/tools/compiletest/src/main.rs:521:22
[01:04:33] note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
[01:04:33] 
[01:04:33] 
[01:04:33] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/run-pass" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "run-pass" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-6.0/bin/FileCheck" "--host-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "6.0.0\n" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--llvm-cxxflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
[01:04:33] 
[01:04:33] 
[01:04:33] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:04:33] Build completed unsuccessfully in 0:59:46
---
travis_time:end:0576da13:start=1561238480691749446,finish=1561238480696914280,duration=5164834
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:09f123fc
$ ln -s . checkout && for CORE in obj/cores/core.*; do EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' -ex bt -ex q; echo travis_fold":"end:crashlog; fi; done || true
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:19b91ea8
travis_time:start:19b91ea8
$ cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
cat: ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers: No such file or directory
travis_fold:end:after_failure.5
travis_fold:start:after_failure.6
travis_time:start:0b6ca579
$ dmesg | grep -i kill

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@ecstatic-morse ecstatic-morse force-pushed the ecstatic-morse:dataflow-order branch from 1d26fb0 to b03ebd5 Jun 22, 2019

@nagisa

This comment was marked as resolved.

Copy link
Contributor

commented Jun 22, 2019

@bors try

@bors

This comment was marked as outdated.

Copy link
Contributor

commented Jun 22, 2019

⌛️ Trying commit b03ebd5 with merge 03b8d28...

bors added a commit that referenced this pull request Jun 22, 2019

Auto merge of #62062 - ecstatic-morse:dataflow-order, r=<try>
Use a more efficient iteration order for forward dataflow

Currently, dataflow begins by visiting each block in order of ID (`BasicBlock(0)`, `BasicBlock(1)`, etc.). This PR changes that initial iteration to reverse post-order (see [this blog post](https://eli.thegreenplace.net/2015/directed-graph-traversal-orderings-and-applications-to-data-flow-analysis/#data-flow-analysis) for more info). This ensures that the effects of all predecessors will be applied before a basic block is visited if the CFG has no back-edges, and should result in less total iterations even when back-edges exist. This should not change the results of dataflow analysis.

The current ordering for basic blocks may be pretty close to RPO already--`BasicBlock(0)` is already the start block--in which case the cost of doing the traversal up front will outweigh the efficiency gains.
A perf run is needed to check this.

r? @pnkfelix (I think).

bors added a commit that referenced this pull request Jun 22, 2019

Auto merge of #62063 - ecstatic-morse:dataflow-backward-order, r=<try>
Use a more efficient iteration order for backward dataflow

This applies the same basic principle as #62062 to the reverse dataflow analysis used to compute liveness information. It is functionally equivalent, except that post-order is used instead of reverse post-order.

In the long-term, `BitDenotation` should probably be extended to support both forward and backward dataflow, but there's some more work needed to get to that point.
@bors

This comment was marked as outdated.

Copy link
Contributor

commented Jun 22, 2019

💔 Test failed - checks-travis

@rust-highfive

This comment was marked as outdated.

Copy link
Collaborator

commented Jun 22, 2019

Your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_fold:end:services

travis_fold:start:git.checkout
travis_time:start:1c1a3477
$ git clone --depth=2 --branch=try https://github.com/rust-lang/rust.git rust-lang/rust
---
Cloning into 'rust-lang/rust'...
travis_time:end:1c1a3477:start=1561241805895108140,finish=1561241811474866321,duration=5579758181
$ cd rust-lang/rust
$ git checkout -qf 03b8d2800f299e13f300fa658b68ddaee57d3a77
fatal: reference is not a tree: 03b8d2800f299e13f300fa658b68ddaee57d3a77
The command "git checkout -qf 03b8d2800f299e13f300fa658b68ddaee57d3a77" failed and exited with 128 during .
Your build has been stopped.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@nagisa

This comment has been minimized.

Copy link
Contributor

commented Jun 22, 2019

@bors try

@bors

This comment has been minimized.

Copy link
Contributor

commented Jun 22, 2019

⌛️ Trying commit b03ebd5 with merge 0905d6a...

bors added a commit that referenced this pull request Jun 22, 2019

Auto merge of #62062 - ecstatic-morse:dataflow-order, r=<try>
Use a more efficient iteration order for forward dataflow

Currently, dataflow begins by visiting each block in order of ID (`BasicBlock(0)`, `BasicBlock(1)`, etc.). This PR changes that initial iteration to reverse post-order (see [this blog post](https://eli.thegreenplace.net/2015/directed-graph-traversal-orderings-and-applications-to-data-flow-analysis/#data-flow-analysis) for more info). This ensures that the effects of all predecessors will be applied before a basic block is visited if the CFG has no back-edges, and should result in less total iterations even when back-edges exist. This should not change the results of dataflow analysis.

The current ordering for basic blocks may be pretty close to RPO already--`BasicBlock(0)` is already the start block--in which case the cost of doing the traversal up front will outweigh the efficiency gains.
A perf run is needed to check this.

r? @pnkfelix (I think).
@bors

This comment has been minimized.

Copy link
Contributor

commented Jun 23, 2019

☀️ Try build successful - checks-travis
Build commit: 0905d6a

bors added a commit that referenced this pull request Jun 23, 2019

Auto merge of #62063 - ecstatic-morse:dataflow-backward-order, r=<try>
Use a more efficient iteration order for backward dataflow

This applies the same basic principle as #62062 to the reverse dataflow analysis used to compute liveness information. It is functionally equivalent, except that post-order is used instead of reverse post-order.

In the long-term, `BitDenotation` should probably be extended to support both forward and backward dataflow, but there's some more work needed to get to that point.
@Centril

This comment has been minimized.

Copy link
Member

commented Jun 23, 2019

@rust-timer

This comment has been minimized.

Copy link

commented Jun 23, 2019

Success: Queued 0905d6a with parent d6884ae, comparison URL.

@rust-timer

This comment has been minimized.

Copy link

commented Jun 23, 2019

Finished benchmarking try commit 0905d6a, comparison URL.

@pnkfelix

This comment has been minimized.

Copy link
Member

commented Jun 27, 2019

This seems ... fine? It doesn't seems to hurt anything; it also doesn't improve things terribly much, probably because the block numbering was close to RPO already, as hypothesized.

ts probably not a good idea to implicitly rely on the block numbering always remaining close to RPO, right? And therefore we should land this?

What do you think, @ecstatic-morse ? (@nagisa and @arielb1 may also have thoughts on this, since I know they've each also spent time thinking about or working on dataflow analyses.)

@ecstatic-morse

This comment has been minimized.

Copy link
Contributor Author

commented Jun 27, 2019

I think this should probably land (totally not biased or anything :). It's a sensible default, the overhead of a single extra RPO traversal per dataflow analysis is pretty small, and it removes the implicit dependency on a certain basic block ordering, which may change as more MIR transformations are added. With the addition of more expensive dataflow passes (i.e. reaching definitions), the naive ordering could eventually have an observable performance impact.

The alternative is to wait until a MIR transformation is actually added which renumbers basic blocks, but this PR will probably be long forgotten by then 😄.

@ecstatic-morse

This comment has been minimized.

Copy link
Contributor Author

commented Jun 27, 2019

Also, this does reduce the number of dataflow iterations, just not enough to matter. I observed a reduction of 9% across all dataflow analyses which took more than 5 iterations when running the tests in src/test/run-pass/array-slice-vec/.

Use a more efficient iteration order for forward dataflow
Currently, dataflow begins by visiting each block in order of ID
(`BasicBlock(0)`, `BasicBlock(1)`, etc.). This PR changes that initial
iteration to reverse post-order. This ensures that the effects of all
predecessors will be applied before a basic block is visited if the CFG
has no back-edges, and should result in less total iterations even when
back-edges exist. This should not change the results of dataflow
analysis.

The current ordering for basic blocks is pretty close to RPO
already--`BasicBlock(0)` is already the start block, so the gains from
this are pretty small, especially since we need to do an extra traversal
up front.

Note that some basic blocks are unreachable from the `START_BLOCK`
during dataflow. We add these blocks to the work queue as well to
preserve the original behavior.

@ecstatic-morse ecstatic-morse force-pushed the ecstatic-morse:dataflow-order branch from b03ebd5 to 07c5e2b Jun 27, 2019

ecstatic-morse added a commit to ecstatic-morse/rust that referenced this pull request Jun 27, 2019

Use more efficient iteration order for backward dataflow
This applies the same basic principle as rust-lang#62062 to the reverse dataflow
analysis used to compute liveness information. It is functionally
equivalent, except that post-order is used instead of reverse post-order.

Some `mir::Body`s contain basic blocks which are not reachable from the
`START_BLOCK`. We need to add them to the work queue as well to preserve
the original semantics.
@arielb1

This comment has been minimized.

Copy link
Contributor

commented Jun 28, 2019

@pnkfelix

I think it's OK to land this to avoid the dependence on basic block ordering.

@nagisa

This comment has been minimized.

Copy link
Contributor

commented Jun 29, 2019

@bors r+

@bors

This comment has been minimized.

Copy link
Contributor

commented Jun 29, 2019

📌 Commit 07c5e2b has been approved by nagisa

Centril added a commit to Centril/rust that referenced this pull request Jun 30, 2019

Rollup merge of rust-lang#62062 - ecstatic-morse:dataflow-order, r=na…
…gisa

Use a more efficient iteration order for forward dataflow

Currently, dataflow begins by visiting each block in order of ID (`BasicBlock(0)`, `BasicBlock(1)`, etc.). This PR changes that initial iteration to reverse post-order (see [this blog post](https://eli.thegreenplace.net/2015/directed-graph-traversal-orderings-and-applications-to-data-flow-analysis/#data-flow-analysis) for more info). This ensures that the effects of all predecessors will be applied before a basic block is visited if the CFG has no back-edges, and should result in less total iterations even when back-edges exist. This should not change the results of dataflow analysis.

The current ordering for basic blocks may be pretty close to RPO already--`BasicBlock(0)` is already the start block--in which case the cost of doing the traversal up front will outweigh the efficiency gains.
A perf run is needed to check this.

r? @pnkfelix (I think).

Centril added a commit to Centril/rust that referenced this pull request Jun 30, 2019

Rollup merge of rust-lang#62063 - ecstatic-morse:dataflow-backward-or…
…der, r=nagisa

Use a more efficient iteration order for backward dataflow

This applies the same basic principle as rust-lang#62062 to the reverse dataflow analysis used to compute liveness information. It is functionally equivalent, except that post-order is used instead of reverse post-order.

In the long-term, `BitDenotation` should probably be extended to support both forward and backward dataflow, but there's some more work needed to get to that point.

bors added a commit that referenced this pull request Jul 1, 2019

Auto merge of #62253 - Centril:rollup-115uuuq, r=Centril
Rollup of 8 pull requests

Successful merges:

 - #62062 (Use a more efficient iteration order for forward dataflow)
 - #62063 (Use a more efficient iteration order for backward dataflow)
 - #62224 (rustdoc: remove unused derives and variants)
 - #62228 (Extend the #[must_use] lint to boxed types)
 - #62235 (Extend the `#[must_use]` lint to arrays)
 - #62239 (Fix a typo)
 - #62241 (Always parse 'async unsafe fn' + properly ban in 2015)
 - #62248 (before_exec actually will only get deprecated with 1.37)

Failed merges:

r? @ghost

@bors bors merged commit 07c5e2b into rust-lang:master Jul 1, 2019

1 check passed

pr Build #20190627.29 succeeded
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.