Skip to content

Commit

Permalink
cfg: use Tarjan's SCC algorithm to get "minimal loops" (instead of "m…
Browse files Browse the repository at this point in the history
…aximal"). (#48)

Quoting from the comment I added to the code:
> This analysis was added to because of two observations wrt
"reconvergence":
> 1. syntactic loops (from some high-level language), when truly
structured
> (i.e. only using `while`/`do`-`while` exit conditions, not `break`
etc.),
> *always* map to "minimal loops" on a CFG, as the only loop exit edge
is
> built-in, and no part of the syntactic "loop body" can be its
successor
> 2. more pragmatically, compiling shader languages to SPIR-V seems to
(almost?)
> always *either* fully preserve syntactic loops (via SPIR-V
`OpLoopMerge`),
> *or* structurize CFGs in a way that produces "minimal loops", which
can
> be misleading with explicit `break`s (moving user code from just
before
> the `break` to after the loop), but is less impactful than "maximal
loops"

See also:
* #11
(of which this only fixes the loop side, and doesn't even keep the
bitflags)
  • Loading branch information
eddyb authored Oct 5, 2023
2 parents 81e30fe + b8e8300 commit 521c241
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 41 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased] - ReleaseDate

### Changed 🛠
- [PR#48](https://github.com/EmbarkStudios/spirt/pull/48) changed CFG structurization
from "maximal loops" to "minimal loops" (computed using Tarjan's SCC algorithm),
and added `OpLoopMerge` support on top (by extending a "minimal loop" as needed)

## [0.3.0] - 2023-07-25

### Added ⭐
- [PR#45](https://github.com/EmbarkStudios/spirt/pull/45) added the abilit to
- [PR#45](https://github.com/EmbarkStudios/spirt/pull/45) added the ability to
pretty-print `OpExtInst`s (SPIR-V "extended instructions") using official
`extinst.*.grammar.json` descriptions and/or custom ones (registered via `Context`)

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,16 +140,16 @@ global_var GV0 in spv.StorageClass.Output: s32
func F0() -> spv.OpTypeVoid {
loop(v0: s32 <- 1s32, v1: s32 <- 1s32) {
v2 = spv.OpSLessThan(v1, 10s32): bool
(v3: bool, v4: s32, v5: s32) = if v2 {
(v3: bool, v4: s32, v5: s32, _: bool) = if v2 {
v6 = spv.OpIMul(v0, v1): s32
v7 = spv.OpIAdd(v1, 1s32): s32
(true, v6, v7)
(true, v6, v7, false)
} else {
spv.OpStore(Pointer: &GV0, Object: v0)
(false, spv.OpUndef: s32, spv.OpUndef: s32)
(false, spv.OpUndef: s32, spv.OpUndef: s32, true)
}
(v4, v5) -> (v0, v1)
} while v3
spv.OpStore(Pointer: &GV0, Object: v0)
}
```
<!-- END tests/data/for-loop.wgsl.spvasm.structured.spirt -->
Expand Down
16 changes: 8 additions & 8 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ fn main() {
.collect();
extinsts_names_and_grammars.sort();

let all_jsons = format!(
let mut all_jsons = format!(
"pub(super) const SPIRV_CORE_GRAMMAR: &str = include_str!({:?});\n\
pub(super) const EXTINST_NAMES_AND_GRAMMARS: &[(&str, &str)] = &[\n{}];",
pub(super) const EXTINST_NAMES_AND_GRAMMARS: &[(&str, &str)] = &[\n",
khr_spv_include_dir.join(core_grammar),
extinsts_names_and_grammars
.into_iter()
.map(|(name, grammar)| {
format!("({:?}, include_str!({:?})),\n", name, khr_spv_include_dir.join(grammar),)
})
.collect::<String>()
);
for (name, grammar) in extinsts_names_and_grammars {
use std::fmt::Write as _;
writeln!(all_jsons, "({:?}, include_str!({:?})),", name, khr_spv_include_dir.join(grammar))
.unwrap();
}
all_jsons += "];";
std::fs::write(
std::path::PathBuf::from(std::env::var_os("OUT_DIR").unwrap())
.join("khr_spv_grammar_jsons.rs"),
Expand Down
Loading

0 comments on commit 521c241

Please sign in to comment.