 In this example, we're going to be looking at this block of code to find dependencies, data hazards, and to overcome those data hazards using NOOP instructions again. So the first thing we'd like to do is go through and find all the dependencies. Our first instruction is dependent on stuff that's happening outside of our codes. We won't really need to worry about that one. Our second instruction has two source registers, t0 and a1. Since we updated t0 in the first instruction, we do have a dependency there. Our second instruction is only dependent on register 0. Since register 0 can't be changed, we don't really have any dependencies there. We clearly weren't trying to update register 0 before. So we won't have to worry about any there. Likewise, with the fourth instruction, the only source register is register 0, so that won't be a problem. In our fifth instruction, the shift left logical, we have one source register, which is t1. And that is dependent on the previous instance of t1, which was set up here. So we've got a dependency there. Then we've got our add instruction. Add instruction is dependent on t1, which we updated in the shift left logical instruction. So we'll have a dependency there. Then we've got a store word instruction. Our store word instruction is dependent both on the data in t2, as well as the address in t1. So we updated t1 here in the add instruction. So there's a dependency there. And then we updated t2 back here in our first add immediate instruction. So we'll also have a dependency there. Our last instruction is the jump register instruction. And that's not going to be dependent on any of the others that we've got here because we didn't update the return address. So now we'll go through and look for data hazards and add no op instructions to avoid those. Since our first instruction doesn't have any dependencies, we don't have any problems just running the load word instruction immediately. But our second instruction is dependent on the first one. So that means we're going to have to wait two cycles for our load word instruction to complete before we can run our add instruction. Since we don't have anything else to fill those cycles with, we'll use no op instructions. Our third instruction and our fourth instruction aren't dependent on any others. So we'll be able to run those immediately. Now we've got our shift left logical instruction. That is dependent on the previous add immediate instruction. So we're going to need to wait two cycles for the add immediate instruction to complete before we can get the results for T1 out. So that will mean we'll fill those two cycles with no op instructions. Next we have this add instruction which is dependent on the results of this shift left logical. So again, we're going to wait two cycles for shift left logical to store its results back into a register. Before we pull them out and use them in the add instruction. Next we've got this store word instruction. This one is dependent on two of our other instructions. We've got the add immediate as well as the add instruction. So first I need to wait two cycles after the add immediate instruction is completed before I can get the data from T2. So I look back here, I've had one, two, three, four, five, six, seven cycles since that instruction ran. So I'm pretty sure that data is available for me. But I also have to wait two cycles for the address T1 to be computed. So since that was computed in the previous instruction, I'm going to have to wait two more cycles for that data to be available for me. So I will add two no op instructions. Then I can have my store word instruction. And lastly I have the jump register instruction. This case it's not dependent on any of the previous instructions. So I'm going to be able to run my jump register instruction immediately. So that's what our sequence of instructions will look like this time. We've added two, four, six, eight no op instructions to work around the data hazards that we've got from this series of instructions.