package synthesijer.scheduler.opt; import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; import synthesijer.scheduler.Op; import synthesijer.scheduler.Operand; import synthesijer.scheduler.SchedulerBoard; import synthesijer.scheduler.SchedulerInfo; import synthesijer.scheduler.SchedulerItem; import synthesijer.scheduler.SchedulerSlot; import synthesijer.scheduler.VariableOperand; public class BasicParallelizer2 implements SchedulerInfoOptimizer{ public static final boolean DEBUG = false; public SchedulerInfo opt(SchedulerInfo info){ // SchedulerInfo result = new SchedulerInfo(info.getName()); // result.addModuleVarList(info.getModuleVarList()); SchedulerInfo result = info.getSameInfo(); for(SchedulerBoard b: info.getBoardsList()){ result.addBoard(conv(b)); } return result; } public String getKey(){ return "basic_parallelize2"; } private SchedulerSlot copySlots(SchedulerSlot slot){ SchedulerSlot newSlot = new SchedulerSlot(slot.getStepId()); for(SchedulerItem item: slot.getItems()){ newSlot.addItem(item); item.setSlot(newSlot); } return newSlot; } private Hashtable<SchedulerSlot, ArrayList<SchedulerSlot>> analyze(ArrayList<SchedulerSlot> bb){ Hashtable<Operand, ArrayList<SchedulerSlot>> writing = new Hashtable<>(); Hashtable<Operand, ArrayList<SchedulerSlot>> reading = new Hashtable<>(); Hashtable<SchedulerSlot, ArrayList<SchedulerSlot>> dependents = new Hashtable<>(); for(SchedulerSlot s: bb){ ArrayList<SchedulerSlot> dependent = new ArrayList<>(); dependents.put(s, dependent); for(Operand src: s.getSrcOperands()){ // should read after previous write if(writing.containsKey(src)){ ArrayList<SchedulerSlot> l = writing.get(src); for(SchedulerSlot ll: l){ dependent.add(ll); } } } for(Operand dest: s.getDestOperands()){ // should write after previous write if(dest != null && writing.containsKey(dest)){ ArrayList<SchedulerSlot> l = writing.get(dest); for(SchedulerSlot ll: l){ dependent.add(ll); } } } for(Operand dest: s.getDestOperands()){ // should write after previous read if(dest != null && reading.containsKey(dest)){ ArrayList<SchedulerSlot> l = reading.get(dest); for(SchedulerSlot ll: l){ dependent.add(ll); } } } for(Operand dest: s.getDestOperands()){ if(dest == null) continue; ArrayList<SchedulerSlot> l = writing.get(dest); if(l == null) l = new ArrayList<>(); if(dest instanceof VariableOperand){ l.add(s); writing.put(dest, l); } } for(Operand src: s.getSrcOperands()){ ArrayList<SchedulerSlot> l = reading.get(src); if(l == null) l = new ArrayList<>(); if(src instanceof VariableOperand){ l.add(s); reading.put(src, l); } } } return dependents; } private boolean isReady(SchedulerSlot slot, ArrayList<SchedulerSlot> dependent, ArrayList<SchedulerSlot> restList){ if(dependent == null) return true; for(SchedulerSlot s: dependent){ if(restList.contains(s) == true){ return false; } } return true; } private SchedulerSlot parallelize(SchedulerBoard board, ArrayList<SchedulerSlot> bb, Hashtable<Integer, Integer> id_map){ SchedulerSlot target = null; SchedulerSlot prev = null; Hashtable<SchedulerSlot, ArrayList<SchedulerSlot>> dependents = analyze(bb); ArrayList<SchedulerSlot> restList = bb; ArrayList<SchedulerSlot> genList = new ArrayList<>(); while(restList.size() > 0){ ArrayList<SchedulerSlot> tmpList = new ArrayList<>(); for(SchedulerSlot s: restList){ if(target == null){ target = copySlots(s); board.addSlot(target); genList.add(target); if(s.getStepId() != target.getStepId()){ id_map.put(s.getStepId(), target.getStepId()); } }else{ if(isReady(s, dependents.get(s), restList)){ if(s.getStepId() != target.getStepId()){ id_map.put(s.getStepId(), target.getStepId()); } for(SchedulerItem item: s.getItems()){ target.addItem(item); item.setSlot(target); } }else{ tmpList.add(s); } } } restList = tmpList; if(prev != null && target != null) for(SchedulerItem item: prev.getItems()){ item.setBranchId(target.getStepId());} prev = target; target = null; // next } // for(SchedulerSlot s: genList){ // for(SchedulerItem i: s.getItems()){ // i.remapBranchIds(id_map); // } // } return prev; } private boolean isExcept(SchedulerItem item){ Op op = item.getOp(); switch(op){ case METHOD_ENTRY: case METHOD_EXIT: case MUL32: case MUL64: case DIV32: case DIV64: case MOD32: case MOD64: case LSHIFT32: case LOGIC_RSHIFT32: case ARITH_RSHIFT32: case LSHIFT64: case LOGIC_RSHIFT64: case ARITH_RSHIFT64: case JP: case JT: case RETURN: case SELECT: // case ARRAY_ACCESS: // case ARRAY_INDEX: case CALL: case EXT_CALL: case FIELD_ACCESS: case BREAK: case CONTINUE: case FADD32: case FSUB32: case FMUL32: case FDIV32: case FADD64: case FSUB64: case FMUL64: case FDIV64: case CONV_F2I: case CONV_I2F: case CONV_D2L: case CONV_L2D: case CONV_F2D: case CONV_D2F: case FLT32: case FLEQ32: case FGT32: case FGEQ32: case FCOMPEQ32: case FNEQ32: case FLT64: case FLEQ64: case FGT64: case FGEQ64: case FCOMPEQ64: case FNEQ64: case UNDEFINED: return true; default: return false; } } private boolean isExcept(SchedulerItem[] items){ boolean flag = false; for(SchedulerItem i: items){ flag |= isExcept(i); } return flag; } private boolean isConflicted(SchedulerSlot s, SchedulerItem item){ boolean f = false; for(SchedulerItem prev: s.getItems()){ f |= item.isConflicted(prev); } return f; } private boolean isConflicted(ArrayList<SchedulerSlot> bb, SchedulerItem item){ if(bb == null) return false; boolean f = false; for(SchedulerSlot s: bb){ f |= isConflicted(s, item); } return f; } private boolean isConflicted(ArrayList<SchedulerSlot> bb, SchedulerSlot s){ if(bb == null) return false; boolean flag = false; for(SchedulerItem item : s.getItems()){ flag |= isConflicted(bb, item); } return flag; } private void dumpDegree(String name, Hashtable<SchedulerSlot, Integer> degrees){ System.out.println("**** " + name); Enumeration<SchedulerSlot> e = degrees.keys(); while(e.hasMoreElements()){ SchedulerSlot s = e.nextElement(); System.out.println(s.getStepId() + " -> " + degrees.get(s)); } } public SchedulerBoard conv(SchedulerBoard src){ SchedulerBoard ret = src.genSameEnvBoard(); SchedulerSlot[] slots = src.getSlots(); Hashtable<SchedulerSlot, Integer> degrees = src.getEntryDegrees(); if(DEBUG){ dumpDegree(src.getName(), degrees); } ArrayList<SchedulerSlot> bb = null; Hashtable<Integer, Integer> id_map = new Hashtable<>(); SchedulerSlot prev = null; for(int i = 0; i < slots.length; i++){ SchedulerSlot slot = slots[i]; Integer d = degrees.get(slot); if(d == null){ System.out.println("d==null: " + slot.getItems()[0].toSexp() + "@" + slot); } if(slot.hasBranchOp() || slot.getNextStep().length > 1 //|| slot.getLatency() > 0 || d > 1 || slot.getItems().length > 1 || isExcept(slot.getItems()) || isConflicted(bb, slot)){ if(bb != null && bb.size() > 0){ prev = parallelize(ret, bb, id_map); } // the slot should be registered as a new slot SchedulerSlot newSlot = copySlots(slot); ret.addSlot(newSlot); if(bb != null && prev != null) for(SchedulerItem item: prev.getItems()){ item.setBranchId(newSlot.getStepId());} for(SchedulerItem item: newSlot.getItems()){ item.remapBranchIds(id_map); } bb = null; // reset prev = newSlot; }else{ if(bb == null){ bb = new ArrayList<>(); } bb.add(slot); } } if(bb != null && bb.size() > 0){ parallelize(ret, bb, id_map); } return ret; } }