Agreed that it looks weird for RegWrite to have its register as an input. Just note that this is the canonical(ish) way of describing memory writes in single static assignment (SSA) form.
Reg defines one logical data structure, much like an Array or SRAM, so, as with other data structures, writes to registers in the IR take the form Update(structure, address, value).
There are multiple ways to detect that a symbol is written in an operation, including looking at the Effects of the node (this includes a written symbols Set), looking at the writers metadata of the original symbol, and just pattern matching on the node.
You're probably already aware of what Reduce is describing here, but just in case:
The first ("map") function (s1(i) * s2(i)) defines how to produce a single element per iteration.
The second ("reduce") function (_ + _) defines how to combine any two elements together. This includes both operation(s) used for how an element might be combined into an accumulator AND how elements might get combined together independent of the accumulator, e.g. in a hardware reduction tree.
Reduce gives us a nice abstraction which isolates the combination function, and therefore the "hard" part of parallelizing reductions (the accumulation cycle) in an isolated way.
This allows us to easily generate parallel implementations of the Reduce without mucking around with isolating the cycle, identifying whether it's a valid candidate for parallelization and figuring it how to duplicate it on other inputs.
This is particularly important because, in general, it's impossible to tell whether a series of operations are associative and, furthermore, floating point operations are NOT associative by nature. Using them in a Reduce and declaring the reduce tells the compiler to override "strict" behavior.
However, you're right, these separate functions does make analyzing the dataflow of the Reduce a pain. There's only a couple things you can do here:
1. Don't try to run the transformation here.
2. Wait until the graph is unrolled to transform - this is what the transformer that fuses multiplies and adds (RewriteTransformer) does.
3. Keep a table of what symbols will alias with the bound symbols (b22 and b23) and visit the reduce function while checking this table.
I would discourage 3 if you can avoid it. There is little you can transform this Reduce into while keeping the operation semantically the same, especially because the way the reduction function will be used varies depending on how the unrolling transformer runs.
Best,
David