public boolean optimizeRegisterAllocation(RegAllocContext context, int nMaxRegisters) {
    boolean bChanges = false;

    ArrayList<Instruction> removeList = new ArrayList<Instruction>();

    // Iterate through instructions
    for (int i = 0; i < getLines().getNumItems(); i++) {
      Line line = getLines().getItemAtIndex(i);

      Instruction nextInstr = getNextInstr(getLines(), i);

      if (Line.Type.INSTRUCTION == line.getType()) {
        Instruction instr = (Instruction) line;

        // If this is a LI instruction
        if (0 == instr.getInstruction().compareTo("li")) {
          // If the register is $v0, do nothing
          if (0 != instr.getArgument1().getName().compareTo("$v0")) {
            // Allocate Free register for dest
            String strFreeReg = findFirstFreeReg(context, instr.getLiveSet(), nMaxRegisters);

            // Map old register to this instruction
            context.mapRegToInstruction.put(instr.getArgument1().getName(), instr);

            context.regMap.put(strFreeReg, instr.getArgument2().getName());
            context.variableLocs.put(instr.getArgument2().getName(), strFreeReg);

            // Rewrite Argument1 with new register
            instr.getArgument1().setOrigName(strFreeReg);
          }
        }
        // If this is a LW instruction
        else if (0 == instr.getInstruction().compareTo("lw")) {
          // If the variable is in a register, then remove this instruction
          if (0 != context.variableLocs.get(instr.getArgument2().getName()).compareTo("m")) {
            Line nextLine = getLines().getItemAtIndex(i + 1);
            Instruction next = null;

            if (Line.Type.INSTRUCTION == nextLine.getType()) next = (Instruction) nextLine;

            if (null == next || 0 != next.getInstruction().compareTo("sw")) removeList.add(instr);
          }
          // else if the variable is live,
          else // if(instr.getLiveSet().contains(instr.getArgument2().getName()))
          {
            // 1) allocate free register
            String strFreeReg = findFirstFreeReg(context, instr.getLiveSet(), nMaxRegisters);

            // 2) patch instruction
            if (null != strFreeReg) {
              context.regMap.put(strFreeReg, instr.getArgument2().getName());
              context.variableLocs.put(instr.getArgument2().getName(), strFreeReg);

              instr.getArgument1().setOrigName(strFreeReg);
            }
          }
        }
        // If this is a SW instruction
        else if (0 == instr.getInstruction().compareTo("sw")) {
          // If the register is $v0, do nothing
          if (0 != instr.getArgument1().getName().compareTo("$v0")) {
            // If the instruction that is mapped to the register is an LW, then use the register
            // from that instruction.
            Line prevLine = getLines().getItemAtIndex(i - 1);
            Instruction prevInstr = null;

            if (Line.Type.INSTRUCTION == prevLine.getType()) prevInstr = (Instruction) prevLine;

            // context.mapRegToInstruction.get(instr.getArgument1().getOrigName());
            if (null != prevInstr && 0 == prevInstr.getInstruction().compareTo("lw")) {
              String strReg = prevInstr.getArgument1().getOrigName();
              instr.getArgument1().setOrigName(strReg);

              context.regMap.put(strReg, instr.getArgument2().getName());
              context.variableLocs.put(instr.getArgument2().getName(), strReg);
            }
            // If the variable is live
            else if (null != nextInstr
                && nextInstr.getLiveSet().contains(instr.getArgument2().getName())) {
              // Add the variable to the live set
              instr.getLiveSet().add(instr.getArgument2().getName());

              String strOldReg = instr.getArgument1().getOrigName();
              String strNewReg = "";

              // If the variable is already in a register
              if (0 != context.variableLocs.get(instr.getArgument2().getName()).compareTo("m")) {
                // Patch current instruction to use that register
                strNewReg = context.variableLocs.get(instr.getArgument2().getName());

                instr.getArgument1().setOrigName(strNewReg);
              }
              // Else
              else {
                // Allocate free register
                strNewReg = findFirstFreeReg(context, instr.getLiveSet(), nMaxRegisters);

                // patch instruction
                if (null != strNewReg) {
                  context.regMap.put(strNewReg, instr.getArgument2().getName());
                  context.variableLocs.put(instr.getArgument2().getName(), strNewReg);

                  instr.getArgument1().setOrigName(strNewReg);
                }
              }

              // Patch register's last-used instruction
              Instruction oldInstr = context.mapRegToInstruction.get(strOldReg);

              if (null != oldInstr) oldInstr.getArgument1().setOrigName(strNewReg);
            }
            // If the previous instruction is an operation...
            else if (null != prevInstr && prevInstr.isOperation()) {
              String strReg = prevInstr.getArgument1().getOrigName();
              instr.getArgument1().setOrigName(strReg);

              // Remove the mapping from the register to the instruction
              context.mapRegToInstruction.remove(prevInstr.getArgument1().getName());

              //							context.regMap.put(strReg, instr.getArgument2().getName());
              //							context.variableLocs.put(instr.getArgument2().getName(), strReg);
            }
            // If the register is mapped to a variable held in a register
            else if (instr.getMapRegToValue().containsKey(instr.getArgument1().getName())) {
              String strOldReg = instr.getArgument1().getName();

              String strVar = instr.getMapRegToValue().get(instr.getArgument1().getName());

              String strNewReg = context.variableLocs.get(strVar);

              if (null != strNewReg && 0 != strNewReg.compareTo("m")) {
                // Update the register
                instr.getArgument1().setOrigName(strNewReg);

                // Find last instruction that referenced old reg
                Instruction oldInstr = context.mapRegToInstruction.get(strOldReg);

                if (null != oldInstr) {
                  oldInstr.getArgument1().setOrigName(strNewReg);
                }
              }
            } else
            // Use temp
            {
              String strOldReg = instr.getArgument1().getName();

              // Allocate temp register for dest
              String strTempReg = getTempRegister(nMaxRegisters);

              // Update the register
              instr.getArgument1().setOrigName(strTempReg);

              // Find last instruction that referenced old reg
              Instruction oldInstr = context.mapRegToInstruction.get(strOldReg);

              if (null != oldInstr) {
                oldInstr.getArgument1().setOrigName(strTempReg);
              }
            }
          }
        }
        // If it is the NEG function
        else if (0 == instr.getInstruction().compareTo("neg")) {
          remapRegister(context, instr, instr.getArgument1());
        }
        // If this is another non-jump instruction
        else if (!instr.getIsJump()
            && 0 != instr.getInstruction().compareTo("syscall")
            && 0 != instr.getInstruction().compareTo("move")) {
          // Allocate temp register for dest
          String strTempReg = getTempRegister(nMaxRegisters);

          // Map old register to this instruction
          context.mapRegToInstruction.put(instr.getArgument1().getName(), instr);

          // Rewrite Argument1 with temp register
          instr.getArgument1().setOrigName(strTempReg);

          remapRegister(context, instr, instr.getArgument2());
          remapRegister(context, instr, instr.getArgument3());
        } else if (0 == instr.getInstruction().compareTo("move")) {
          remapRegister(context, instr, instr.getArgument2());
        }
        // If this is a jump instruction
        else if (instr.getIsJump() && Instruction.BranchType.JUMP != instr.getBranchType()) {
          String strTempReg = getTempRegister(nMaxRegisters);

          // Rewrite Argument1 with temp register
          instr.getArgument1().setOrigName(strTempReg);
        }
      }

      deallocateNonLiveVars(line, context, nMaxRegisters);
    }

    // Remove lines
    for (int i = 0; i < removeList.size(); i++) {
      getLines().removeLine(removeList.get(i));
    }

    return bChanges;
  }