Consider the following matrix multiplication program:
begin
for i := 1 to n do
for j := 1 to n do
c[i,j] := 0
for i := 1 to n do
for j := 1 to n do
for k := 1 to n do
c[i,j] := c[i,j] + a[i,k] * b[k,j]
As you complete the numbered tasks found a little ways below, use the
following bulleted guidelines.

Assume that the arrays
a
, b
, and
c
are indexed from 1 to n
in each dimension.
Assume that you know at compile time that n
is 300 and
that the arrays a
, b
, and c
start at addresses 10000, 4000000, and 6000000, respectively.
 Because you know that
n
≥1, you know that each loop
will execute at least once. Take advantage of this fact by having
each loop execute its test only after it has made it through the loop
body.
 In your three address code, do not use the bracket notation, but
rather do the address addition explicitly.

Create a new temporary for each value, rather than trying to be
frugal and reuse temporaries. That is, do something like
t1 := i * n
t2 := t1 + j
not
t1 := i * n
t1 := t1 + j
Here are your tasks:
 Assuming
a
, b
, and
c
are allocated static storage and there are four bytes
per word in a byteaddressed memory, produce threeaddress statements
for the program.
 Construct a flow graph from the threeaddress statements.
 Eliminate the common subexpressions from each basic block.
 Move the loopinvariant computations out of the loops.
 Find the induction variables of each loop and eliminate them
where possible.
 Briefly describe any major opportunities for optimizing this
routine that are not covered by the exercise. Keep in mind that on
contemporary machines, it is memory accesses that are generally the
most time consuming operations.