Solution (source code)

= Solution

The target's <register-offset addressing> already performs the <addition> of the array base and a scaled index as part of each load or store. Materializing a maximal common address expression into a <processor register> introduces an explicit `ADD` that this addressing mode could have supplied. Here the extra address <temporary variables> save no arithmetic that the memory instructions need to perform separately.

Instead keep the scaled indices, share the loaded old value of `a[i]`, and fold the base <addition> into each memory operand:

``
MOV  rb, #A
LD   ri, [fp + I]
LSL  rj, ri, #2
LD   rv, [rb + rj]
LSL  rk, rv, #2
LD   rt, [rb + rk]
ST   rv, [rb + rk]
ST   rt, [rb + rj]
``

`rj` remains the original index's byte offset, `rv` is its old element, and `rk` remains the second element's byte offset. Both stores use those saved offsets. \b[Folding address <additions> into the memory instructions removes two instructions, reducing ten to eight], or eleven to nine if the local load requires the alternative sequence described in part (c). Therefore
$$
\boxed{N_{\mathrm{folded}}=N_{\mathrm{direct}}-2=8\quad\text{(or 9)}.}
$$

This illustrates why <common subexpression elimination> must interact with <instruction selection>: a larger repeated tree is not automatically a better value to materialize. A useful refinement retains common scaled-index trees, or propagates the address <addition> trees back into their memory uses. The calculation establishes an instruction-count improvement under the stated <instruction set architecture>; scheduling and actual timing depend on further machine details.