# How to iterate all block statements in IRCode?

**URL:** <https://discourse.julialang.org/t/how-to-iterate-all-block-statements-in-ircode/83701>\
**Category:** Internals & Design\
**Created:** [July 3, 2022, 1:39pm UTC](https://discourse.julialang.org/t/how-to-iterate-all-block-statements-in-ircode/83701 "2022-07-03T13:39:19Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [July 3, 2022, 1:39pm UTC](https://discourse.julialang.org/t/how-to-iterate-all-block-statements-in-ircode/83701/1 "2022-07-03T13:39:19Z")

</div>

Say, I have an instance of IRCode like this:

```julia
7 1 ─ %1 = Main.bar(_2)::Tuple{Float64, Float64} │
  │ %2 = Base.indexed_iterate(%1, 1)::PartialStruct(Tuple{Float64, Int64}, Any[Float64, Const(2)])
  │ %3 = Core.getfield(%2, 1)::Float64 │
  │ %4 = Core.getfield(%2, 2)::Const(2) │
  │ %9 = π (%4, Const(2)) │
  │ %5 = Base.indexed_iterate(%1, 2, %9)::PartialStruct(Tuple{Float64, Int64}, Any[Float64, Const(3)])
  │ %6 = Core.getfield(%5, 1)::Float64 │
8 │ %7 = (%3 + %6)::Float64 │
  └── return %7 

```

I know how to:

- get the list of all original nodes: `ir.stmts.inst`
- get the ids of nodes in the `i`th block: `ir.cfg.blocks[i].stmts`
- get the list of new nodes, e.g. the `PiNode` above, as well as their place in the common list of nodes: `ir.new_nodes.stmts.inst`, `ir.new_nodes.info`

Now I want to get the list of all nodes - the original and the new ones - belonging to a particular block. Is there a mapping of blocks to new nodes or an utility function to iterate all block statements in the correct order?

---

<div class="post-metadata">

**Author:** ![gbaraldi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gbaraldi/32/22101_2.png) [@gbaraldi](https://discourse.julialang.org/u/gbaraldi)\
**Post date:** [July 3, 2022, 1:47pm UTC](https://discourse.julialang.org/t/how-to-iterate-all-block-statements-in-ircode/83701/2 "2022-07-03T13:47:25Z")

</div>

I might be wrong but I believe `IncrementalCompact` does something like what you described

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [July 3, 2022, 3:36pm UTC](https://discourse.julialang.org/t/how-to-iterate-all-block-statements-in-ircode/83701/3 "2022-07-03T15:36:58Z")

</div>

Indeed, the code looks relevant, but I can’t figure out how to use it to get all nodes for a particular block. Simply iterating over the `IncrementalCompact` also doesn’t include new nodes:

```julia
julia> for node in Core.Compiler.IncrementalCompact(ir) println(node) end
Pair{Pair{Int64, Int64}, Any}(1 => 1, :(Main.bar(_2)))
Pair{Pair{Int64, Int64}, Any}(2 => 2, :(Base.indexed_iterate(%1, 1)))
Pair{Pair{Int64, Int64}, Any}(3 => 3, :(Core.getfield(%2, 1)))
Pair{Pair{Int64, Int64}, Any}(4 => 4, :(Core.getfield(%2, 2)))
Pair{Pair{Int64, Int64}, Any}(5 => 5, :(Base.indexed_iterate(%1, 2, %4)))
Pair{Pair{Int64, Int64}, Any}(6 => 6, :(Core.getfield(%5, 1)))
Pair{Pair{Int64, Int64}, Any}(7 => 7, :(%3 + %6))
Pair{Pair{Int64, Int64}, Any}(8 => 8, :(return %7))

```

Is there a chance you have a relevant example?

---

<div class="post-metadata">

**Author:** ![ToucheSir](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/touchesir/32/14411_2.png) [@ToucheSir](https://discourse.julialang.org/u/ToucheSir)\
**Post date:** [July 3, 2022, 4:43pm UTC](https://discourse.julialang.org/t/how-to-iterate-all-block-statements-in-ircode/83701/4 "2022-07-03T16:43:14Z")

</div>

Check out `Core.Compiler.bbidxiter` and `CFG` (which is stored in the IRCode, I believe)

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [July 3, 2022, 11:14pm UTC](https://discourse.julialang.org/t/how-to-iterate-all-block-statements-in-ircode/83701/5 "2022-07-03T23:14:08Z")

</div>

`bbidxiter` seems to be even closer, but I’m still missing the exact way to utilize it:

```julia
julia> itr = Core.Compiler.bbidxiter(ir)
7 1 ─ %1 = Main.bar(_2)::Tuple{Float64, Float64} │
  │ %2 = Base.indexed_iterate(%1, 1)::PartialStruct(Tuple{Float64, Int64}, Any[Float64, Const(2)])
  │ %3 = Core.getfield(%2, 1)::Float64 │
  │ %4 = Core.getfield(%2, 2)::Const(2) │
  │ π (%4, Const(2)) │ # <-- PiNode in the correct position!
  │ %5 = Base.indexed_iterate(%1, 2, %4)::PartialStruct(Tuple{Float64, Int64}, Any[Float64, Const(3)])
  │ %6 = Core.getfield(%5, 1)::Float64 │
8 │ %7 = (%3 + %6)::Float64 │
  └── return %7 │
  ) 

julia> Core.Compiler.iterate(itr, (1, 1))
((1, 1), (2, 1))

julia> Core.Compiler.iterate(itr)
((1, 1), (2, 1))

julia> Core.Compiler.iterate(itr, (2, 1))
((1, 2), (3, 1))

julia> Core.Compiler.iterate(itr, (3, 1))
((1, 3), (4, 1))

julia> Core.Compiler.iterate(itr, (4, 1))
((1, 4), (5, 1))

# I'd expect the PiNode to arise around this place
julia> Core.Compiler.iterate(itr, (5, 1))
((1, 5), (6, 1))

julia> Core.Compiler.iterate(itr, (6, 1))
((1, 6), (7, 1))

julia> Core.Compiler.iterate(itr, (7, 1))
((1, 7), (8, 1))

julia> Core.Compiler.iterate(itr, (8, 1))
((1, 8), (9, 2))

julia> Core.Compiler.iterate(itr, (9, 1))

```

On the other hand, the answers in this thread made me look into the implementation of [`show_ir()`](https://github.com/JuliaLang/julia/blob/master/base/compiler/ssair/show.jl#L773-L791) which prints the nodes in correct order. It seems like they iterate over original nodes and pop new nodes when needed, regardless of the current block. I’m going to try the same strategy and see how it works for my case.

---

<div class="post-metadata">

**Author:** ![ToucheSir](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/touchesir/32/14411_2.png) [@ToucheSir](https://discourse.julialang.org/u/ToucheSir)\
**Post date:** [July 4, 2022, 6:29am UTC](https://discourse.julialang.org/t/how-to-iterate-all-block-statements-in-ircode/83701/6 "2022-07-04T06:29:27Z")

</div>

For `bbidxiter`, I’d just toss it in a for loop, check when the block number (first element) matches the one(s) you and and then index into the `IRCode` with statement number (second element). A little easier but maybe less robust would be to index [`BasicBlock`](https://github.com/JuliaLang/julia/blob/v1.8.0-rc1/base/compiler/ssair/basicblock.jl)s on `IRCode.CFG` directly and iterate over their `stmts`.

Note that I’m not sure how well/if at all these work on non-compacted IR. There’s a bit of handling of range wraparound on the basic block side, but it’s likely far from bulletproof.
