LW t1, 0(t4) ; t1 ← address (0+t4)
ADDI t1, t1, #8 ; t1 ← t1+8
MULT t3, t1, t1 ; t3 ← t1*t1
SW t3, 4(t2) ; address(4+t2) ← t3
I'm currently unable to tell how many true dependencies this code has. For me, there are two ways of looking at it. Instruction 1 (I1) has a true dependency with (I2), looking at the t1 that was first the output and now the input in the next instruction. However, the register t1 now has a new value (after I2). My question is, is there only one more true dependency... that being I2 and I3 (t1) or is I1 and I3 (t1) also considered to be a true dependency even though t1 has been used as the output in I2?
Sounds like you're confusing the term dependency with the term hazard.
A true or flow dependency is condition where a value is assigned to a variable or storage earlier and that value is read/used/consumed from that same variable or storage later. This is a fundamental principle in programming, both in high level languages and assembly language/machine code — programmers rely on this, and frequently write dependencies.
When a variable is reassigned or register is repurposed (happens a lot in assembly) the old value is lost, and, the programmer's expectation (and architecture's promise) is that when later read, the new value is what is obtained.
Thus, since
t1
is repurposed at I2 there can be not1
dependency between I1 and I3.Hazards, by contrast, are internal implementation concerns of pipelined and other advanced processors. A processor implementation must observe the architectural requirements of the instruction set it claims adherence to, regardless of internal implementation details, or else the claim is false, and software written for the instruction set won't work properly on the implementation.
Hazards often involve various kinds of dependencies. One very notable hazard, RAW (read after write), happens in pipelined processors when dependencies occur within small instruction distances (e.g. shorter than (a portion of) the pipeline).