1 witchel  1.1.2.1 // BypassLatchSchedule.java, created Wed Sep 27 20:01:40 EDT 2000 by witchel
  2 cananian 1.1.2.6 // Copyright (C) 1999 Emmett Witchel <witchel@mit.edu>
  3 witchel  1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 witchel  1.1.2.1 package harpoon.Backend.MIPS;
  5 witchel  1.1.2.1 
  6 witchel  1.1.2.1 import harpoon.Analysis.DataFlow.LiveTemps;
  7 witchel  1.1.2.1 import harpoon.Analysis.BasicBlock;
  8 witchel  1.1.2.1 import harpoon.Backend.Generic.Frame;
  9 witchel  1.1.2.1 import harpoon.Backend.Generic.Code;
 10 witchel  1.1.2.1 import harpoon.Backend.Generic.RegUseDefer;
 11 witchel  1.1.2.1 import harpoon.IR.Assem.Instr;
 12 witchel  1.1.2.1 import harpoon.IR.Properties.UseDefer;
 13 witchel  1.1.2.1 import harpoon.Temp.Temp;
 14 witchel  1.1.2.1 import harpoon.Util.Util;
 15 witchel  1.1.2.4 import java.util.Collections;
 16 witchel  1.1.2.1 import java.util.Iterator;
 17 witchel  1.1.2.1 import java.util.List;
 18 witchel  1.1.2.1 import java.util.Set;
 19 witchel  1.1.2.1 
 20 witchel  1.1.2.1 /**
 21 witchel  1.1.2.1  * <code>BypassLatchSchedule</code> is a transformation on low level,
 22 witchel  1.1.2.1  * register allocated assembly code that annotates opcode to indicate
 23 witchel  1.1.2.1  * if a given use is the last use of a register.  E.g.
 24 witchel  1.1.2.1  * add t0, t1, t2
 25 witchel  1.1.2.1  * xor t3, t0, t5
 26 witchel  1.1.2.1  * If t0 is not live out of xor, then we replace the xor instruction with
 27 witchel  1.1.2.1  * xor.l1 t3, t0, t5
 28 witchel  1.1.2.1  * which says that this use of operand 1 (RS) is the last use.  The
 29 witchel  1.1.2.1  * assembler will use this information to not write the t0 value
 30 witchel  1.1.2.1  * generated in the add instruction back to the register file.
 31 cananian 1.1.2.6  * @author  Emmett Witchel <witchel@mit.edu>
 32 witchel  1.1.2.1  * @version $Id: 
 33 witchel  1.1.2.1  */
 34 witchel  1.1.2.1 
 35 witchel  1.1.2.1 public class BypassLatchSchedule {
 36 witchel  1.1.2.1 
 37 witchel  1.1.2.1     /** Returns a new <code>Instr</code> if this instr needs to be
 38 witchel  1.1.2.1      * modified.  Otherwise, it returns null.
 39 witchel  1.1.2.1      */
 40 witchel  1.1.2.1    private Instr lastUseInstr(Instr instr) {
 41 witchel  1.1.2.1       Set lb = lt.getLiveBefore(instr);
 42 witchel  1.1.2.1       Set la = lt.getLiveAfter(instr);
 43 witchel  1.1.2.1       Temp[] tmp_use = instr.use();
 44 witchel  1.1.2.4       Temp[] tmp_def = instr.def();
 45 witchel  1.1.2.3       String assem = instr.getAssem();
 46 witchel  1.1.2.3       // XXX omit compound instructions for now
 47 witchel  1.1.2.4       if(assem.indexOf('\n') != -1) return null;
 48 witchel  1.1.2.3 
 49 witchel  1.1.2.4       // Omit calls, and remnants of move coalescing
 50 witchel  1.1.2.4       if(tmp_use.length > 0
 51 witchel  1.1.2.1          && tmp_use.length <= 2
 52 witchel  1.1.2.2          && instr.def().length <= 1 /* excludes jal _lookup_handler */
 53 witchel  1.1.2.3          && assem.length() > 0
 54 witchel  1.1.2.1          ) {
 55 cananian 1.3.2.1          assert tmp_use.length <= 2 : " tmp_use.len=" + tmp_use.length 
 56 cananian 1.3.2.1                      + " tmp_use=" + tmp_use + " isntr=" + instr;
 57 witchel  1.1.2.1          List reg_use0 = null;
 58 witchel  1.1.2.1          List reg_use1 = null;
 59 witchel  1.1.2.4          List reg_def  = tmp_def.length == 0 ? null
 60 witchel  1.1.2.4              : code.getRegisters(instr, tmp_def[0]);
 61 witchel  1.1.2.1          boolean oneLast = false;
 62 witchel  1.1.2.1          if(tmp_use.length > 0) {
 63 witchel  1.1.2.1             reg_use0 = code.getRegisters(instr, tmp_use[0]);
 64 witchel  1.1.2.3             oneLast = lb.containsAll(reg_use0) 
 65 witchel  1.1.2.4                && (la.containsAll(reg_use0) == false
 66 witchel  1.1.2.4                    || (reg_def != null && reg_use0.containsAll(reg_def)));
 67 witchel  1.1.2.1          }
 68 witchel  1.1.2.1          boolean twoLast = false;
 69 witchel  1.1.2.1          if(tmp_use.length > 1) {
 70 witchel  1.1.2.1             reg_use1 = code.getRegisters(instr, tmp_use[1]);
 71 witchel  1.1.2.3             twoLast = lb.containsAll(reg_use1) 
 72 witchel  1.1.2.4                && (la.containsAll(reg_use1) == false
 73 witchel  1.1.2.4                    || (reg_def != null && reg_use1.containsAll(reg_def)));
 74 witchel  1.1.2.1          }
 75 witchel  1.1.2.1          if(trace) {
 76 witchel  1.1.2.1             System.out.println(instr + "\n\tlb=" + lb + "\n\tla=" + la);
 77 witchel  1.1.2.4             if(tmp_def.length > 1) {
 78 witchel  1.1.2.4                System.out.print("\tdef multiple");
 79 witchel  1.1.2.4                for(int i = 0; i < tmp_def.length; ++i) {
 80 witchel  1.1.2.4                   System.out.print(" " + tmp_def[i] + " " 
 81 witchel  1.1.2.4                                    + code.getRegisters(instr, tmp_def[i]));
 82 witchel  1.1.2.4                }
 83 witchel  1.1.2.4                System.out.println();
 84 witchel  1.1.2.4             }
 85 witchel  1.1.2.4             if(tmp_def.length == 1) {
 86 witchel  1.1.2.4                System.out.println("\tdef " + tmp_def[0] + " " + reg_def);
 87 witchel  1.1.2.4             }
 88 witchel  1.1.2.1             if(tmp_use.length == 2) {
 89 witchel  1.1.2.1                System.out.println("\tuse(0) " + tmp_use[0] 
 90 witchel  1.1.2.1                                   + " " + reg_use0
 91 witchel  1.1.2.1                                   + " use(1) " + tmp_use[1]
 92 witchel  1.1.2.1                                   + " " + reg_use1
 93 witchel  1.1.2.1                   );
 94 witchel  1.1.2.1             } else if (tmp_use.length == 1) {
 95 witchel  1.1.2.1                System.out.println("\tuse(0) " + tmp_use[0] 
 96 witchel  1.1.2.1                                   + " " + reg_use0);
 97 witchel  1.1.2.1             }
 98 witchel  1.1.2.1          }
 99 witchel  1.1.2.2          if( oneLast || twoLast ) {
100 witchel  1.1.2.1             int space = assem.indexOf(' ');
101 witchel  1.1.2.2             String opcode = assem.substring(0, space);
102 witchel  1.1.2.2             boolean reverse = false;
103 witchel  1.1.2.5             if(opcode.startsWith("sw")
104 witchel  1.1.2.5                || opcode.startsWith("sh")
105 witchel  1.1.2.5                || opcode.startsWith("sb")
106 witchel  1.1.2.5                || opcode.startsWith("sc")
107 witchel  1.1.2.5                || opcode.startsWith("sdc1")
108 witchel  1.1.2.5                || opcode.startsWith("sllv")
109 witchel  1.1.2.5                || opcode.startsWith("sll")
110 witchel  1.1.2.5                || opcode.startsWith("sra")
111 witchel  1.1.2.5                || opcode.startsWith("srav")
112 witchel  1.1.2.5                || opcode.startsWith("srl")
113 witchel  1.1.2.5                || opcode.startsWith("srlv")
114 witchel  1.1.2.5                || opcode.startsWith("negu")
115 witchel  1.1.2.2                ) {
116 witchel  1.1.2.2                reverse = true;
117 witchel  1.1.2.2             }
118 witchel  1.1.2.2             String suffix = "";
119 witchel  1.1.2.2             if( oneLast && twoLast ) {
120 witchel  1.1.2.2                suffix = ".l12";
121 witchel  1.1.2.2             } else if( oneLast ) {
122 witchel  1.1.2.2                if(reverse)
123 witchel  1.1.2.2                   suffix = ".l2";
124 witchel  1.1.2.2                else
125 witchel  1.1.2.2                   suffix = ".l1";
126 witchel  1.1.2.2             } else if( twoLast ) {
127 witchel  1.1.2.2                if(reverse)
128 witchel  1.1.2.2                   suffix = ".l1";
129 witchel  1.1.2.2                else
130 witchel  1.1.2.2                   suffix = ".l2";
131 witchel  1.1.2.2             }
132 witchel  1.1.2.2             String new_assem = opcode + suffix + assem.substring(space);
133 witchel  1.1.2.1 
134 witchel  1.1.2.1             if(trace)
135 witchel  1.1.2.1                System.out.println("  " + instr.getAssem() + " ==> "+ new_assem);
136 witchel  1.1.2.5             Instr new_i = instr.cloneMutateAssem(new_assem);
137 witchel  1.1.2.2             // XXX This is a gross hack to manually copy register
138 witchel  1.1.2.2             // assignment information because the instr interface
139 witchel  1.1.2.2             // doesn't have a good copy method.
140 witchel  1.1.2.2             Temp[] refs = new_i.use();
141 witchel  1.1.2.2             for(int i = 0; i < refs.length; ++i) {
142 witchel  1.1.2.2                code.assignRegister(new_i, refs[i], 
143 witchel  1.1.2.2                                    code.getRegisters(instr, refs[i]));
144 witchel  1.1.2.2             }
145 witchel  1.1.2.2             refs = new_i.def();
146 witchel  1.1.2.2             for(int i = 0; i < refs.length; ++i) {
147 witchel  1.1.2.2                code.assignRegister(new_i, refs[i], 
148 witchel  1.1.2.2                                    code.getRegisters(instr, refs[i]));
149 witchel  1.1.2.2             }
150 witchel  1.1.2.1             return new_i;
151 witchel  1.1.2.1          }
152 witchel  1.1.2.1       }
153 witchel  1.1.2.1       return null;
154 witchel  1.1.2.1    }
155 witchel  1.1.2.1 
156 witchel  1.1.2.1    public BypassLatchSchedule(Code _code, Frame _frame) {
157 witchel  1.1.2.1       code  = _code;
158 witchel  1.1.2.1       frame = _frame;
159 witchel  1.1.2.1       RegUseDefer ud = new RegUseDefer(code);
160 witchel  1.1.2.1       lt = LiveTemps.make(code, ud,
161 witchel  1.1.2.1                           frame.getRegFileInfo().liveOnExit());
162 witchel  1.1.2.1       BasicBlock.Factory bbFact = new BasicBlock.Factory(code);
163 witchel  1.1.2.1       for(Iterator bbIt = bbFact.blocksIterator(); bbIt.hasNext();) {
164 witchel  1.1.2.1          BasicBlock bb = (BasicBlock)bbIt.next();
165 witchel  1.1.2.1          List instrs = bb.statements();
166 witchel  1.1.2.1          for(int i = 0; i < instrs.size(); ++i) {
167 witchel  1.1.2.1             Instr instr = (Instr)instrs.get(i);
168 witchel  1.1.2.1             Instr new_instr = lastUseInstr(instr);
169 witchel  1.1.2.1             if(new_instr != null) {
170 witchel  1.1.2.1                Instr.replace(instr, new_instr);
171 witchel  1.1.2.1             }
172 witchel  1.1.2.1          }
173 witchel  1.1.2.1       }
174 witchel  1.1.2.1    }
175 witchel  1.1.2.1    
176 witchel  1.1.2.1    private final Code code;
177 witchel  1.1.2.1    private final Frame frame;
178 witchel  1.1.2.1    private LiveTemps lt;
179 witchel  1.1.2.2    private boolean trace = false;
180 cananian 1.2     }