RegAllocAno.java 72.08 KiB
package backend;
import Utils.CustomList;
import backend.asmInstr.AsmInstr;
import backend.asmInstr.asmBinary.AsmAdd;
import backend.asmInstr.asmBr.AsmJ;
import backend.asmInstr.asmLS.*;
import backend.asmInstr.asmTermin.AsmCall;
import backend.itemStructure.*;
import backend.regs.*;
import frontend.ir.Value;
import java.util.*;
/*todo*/ //load指令偏移量超过32位
public class RegAllocAno {
    private RegAllocAno(HashMap<AsmOperand, Value> downOperandMap) {
        // 初始化逻辑
        this.downOperandMap = downOperandMap;
    private HashMap<AsmOperand, Value> downOperandMap;
    // 单例模式下的私有静态成员变量
    private static RegAllocAno instance = null;
    // 提供一个公共的静态方法,用于获取单例对象
    public static RegAllocAno getInstance(HashMap<AsmOperand, Value> downOperandMap) {
        if (instance == null) {
            instance = new RegAllocAno(downOperandMap);
        return instance;
    private static int tryN = 0;
    private int Float_G = 12;
    private int Int_G = 11;
    private int Float_T = 27;
    private int Int_T = 20;
    private int FI = 0;//0代表处理Int型,1代表处理Float型
    private static int K = 27;
    private int procedure = 0;
    HashMap<AsmOperand, Integer> loopDepths = new HashMap<>();
    private HashMap<AsmReg, Integer> preColored = new HashMap<>();
    private HashMap<AsmOperand, HashSet<AsmOperand>> adjList = new HashMap<>();
    private HashMap<AsmOperand, HashSet<AsmOperand>> adjSet = new HashMap<>();
    private HashMap<AsmOperand, Integer> degree = new HashMap<>();
    private HashMap<AsmOperand, HashSet<AsmInstr>> moveList = new HashMap<>();//与该结点相关的传送指令集合
    private HashMap<AsmOperand, AsmOperand> alias = new HashMap<>();//传送指令(u,v)已被合并,v已经放到已合并结点集合,alias(v) = u
    private HashMap<AsmOperand, Integer> color = new HashMap<>();
    //@1
    private HashSet<AsmOperand> all = new HashSet<>(); // 临时寄存器集合
    private HashSet<AsmOperand> global = new HashSet<>();
    private HashSet<AsmOperand> temp = new HashSet<>();
    private HashSet<AsmOperand> simplifyWorklist = new HashSet<>();//低度数的传送无关的节点
    private HashSet<AsmOperand> freezeWorkList = new HashSet<>();//低度数的传送有关的指令
    private HashSet<AsmOperand> spillWorkList = new HashSet<>();//高度数节点
    private HashSet<AsmOperand> spilledNodes = new HashSet<>();//本轮中要被溢出的结点集合
    private HashSet<AsmOperand> coalescedNodes = new HashSet<>();//已合并的的传送指令集合
    private HashSet<AsmOperand> coloredNodes = new HashSet<>();//已经成功着色的结点集合
    private Stack<AsmOperand> selectStack = new Stack<>();//一个包含从图中删除的临时变量的栈
    //@1 这部分,结点只能存在于其中一张表
    //@2
    private HashSet<AsmInstr> coalescedMoves = new HashSet<>();//已经合并的传送指令集合
    private HashSet<AsmInstr> constrainedMoves = new HashSet<>();//源操作数和目标操作数冲突的传送指令集合
    private HashSet<AsmInstr> frozenMoves = new HashSet<>();//不再考虑合并的传送指令
    private HashSet<AsmInstr> worklistMoves = new HashSet<>();//有可能合并的传送指令
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
private HashSet<AsmInstr> activeMoves = new HashSet<>();//还未做好合并准备的传送指令集合 //@2 传送指令集合,传送指令只能存在在其中一张表中 private static int addOffSet = 0; public void run(AsmModule module) { PreColor(); for (AsmFunction function : module.getFunctions()) { addOffSet = 0; if (((AsmBlock) function.getBlocks().getHead()).getInstrs().getSize() == 0) { continue; } K = 64; FI = 1; procedure = 0; while (true) { initial(); LivenessAnalysis(function); findLoopDepth(function); build(function); makeWorkList(); while (!simplifyWorklist.isEmpty() || !worklistMoves.isEmpty() || !freezeWorkList.isEmpty() || !spillWorkList.isEmpty()) { if (!simplifyWorklist.isEmpty()) { simplify(); } else if (!worklistMoves.isEmpty()) { Coalesce(); } else if (!freezeWorkList.isEmpty()) { Freeze(); } else if (!spillWorkList.isEmpty()) { SelectSpill(); } } AssignColors(); if (spilledNodes.isEmpty()) { for (AsmOperand vreg : color.keySet()) { AsmFVirReg vreg1 = (AsmFVirReg) vreg; vreg1.color = color.get(vreg); } //LivenessAnalysis(function);//不确定是否要这样//删了 allocRealReg(function); break; } else { addOffSet += RewriteProgram(function); } } K = 64; FI = 1; procedure = 1; while (true) { initial(); LivenessAnalysis(function); findLoopDepth(function); build(function); makeWorkList(); while (!simplifyWorklist.isEmpty() || !worklistMoves.isEmpty() || !freezeWorkList.isEmpty() || !spillWorkList.isEmpty()) { if (!simplifyWorklist.isEmpty()) { simplify(); } else if (!worklistMoves.isEmpty()) { Coalesce(); } else if (!freezeWorkList.isEmpty()) { Freeze(); } else if (!spillWorkList.isEmpty()) { SelectSpill(); } } AssignColors(); if (spilledNodes.isEmpty()) {
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
for (AsmOperand vreg : color.keySet()) { AsmFVirReg vreg1 = (AsmFVirReg) vreg; vreg1.color = color.get(vreg); } //LivenessAnalysis(function);//不确定是否要这样//删了 addOffSet += callerSave(function); if (!function.getName().equals("main")) { addOffSet += calleeSave(function); } allocRealReg(function); break; } else { addOffSet += RewriteProgram(function); } } K = 32; FI = 0; procedure = 0; while (true) { initial(); LivenessAnalysis(function); findLoopDepth(function); build(function); makeWorkList(); while (!simplifyWorklist.isEmpty() || !worklistMoves.isEmpty() || !freezeWorkList.isEmpty() || !spillWorkList.isEmpty()) { if (!simplifyWorklist.isEmpty()) { simplify(); } else if (!worklistMoves.isEmpty()) { Coalesce(); } else if (!freezeWorkList.isEmpty()) { Freeze(); } else if (!spillWorkList.isEmpty()) { SelectSpill(); } } AssignColors(); if (spilledNodes.isEmpty()) { for (AsmOperand vreg : color.keySet()) { AsmVirReg vreg1 = (AsmVirReg) vreg; vreg1.color = color.get(vreg); } //不确定是否要这样 allocRealReg(function); break; } else { addOffSet += RewriteProgram(function); } } procedure = 1; while (true) { initial(); LivenessAnalysis(function); findLoopDepth(function); build(function); makeWorkList(); while (!simplifyWorklist.isEmpty() || !worklistMoves.isEmpty() || !freezeWorkList.isEmpty() || !spillWorkList.isEmpty()) { if (!simplifyWorklist.isEmpty()) { simplify(); } else if (!worklistMoves.isEmpty()) { Coalesce(); } else if (!freezeWorkList.isEmpty()) { Freeze(); } else if (!spillWorkList.isEmpty()) { SelectSpill(); } } AssignColors();
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
if (spilledNodes.isEmpty()) { for (AsmOperand vreg : color.keySet()) { AsmVirReg vreg1 = (AsmVirReg) vreg; vreg1.color = color.get(vreg); } //不确定是否要这样 addOffSet += callerSave(function); if (!function.getName().equals("main")) { addOffSet += calleeSave(function); } allocRealReg(function); break; } else { //System.out.println("spilledNodes.size() = " + spilledNodes.size() + " " + spilledNodes + " " + function.getName()); addOffSet += RewriteProgram(function); } } allocAndRecycleSP(function); changeLoads(function); changeStores(function); deleteMove(function); } } private void deleteMove(AsmFunction function) { AsmBlock blockHead = (AsmBlock) function.getBlocks().getHead(); while (blockHead != null) { AsmInstr instrHead = (AsmInstr) blockHead.getInstrs().getHead(); while (instrHead != null) { if (instrHead instanceof AsmMove) { if (((AsmMove) instrHead).getDst() == ((AsmMove) instrHead).getSrc()) { instrHead.removeFromList(); } } instrHead = (AsmInstr) instrHead.getNext(); } blockHead = (AsmBlock) blockHead.getNext(); } } private void changeLoads(AsmFunction function) { int a = 1; for (CustomList.Node asmBlock : function.getBlocks()) { AsmInstr firstInstr = (AsmInstr) ((AsmBlock) asmBlock).getInstrs().getHead(); while (firstInstr != null) { if (firstInstr instanceof AsmL) { if (firstInstr instanceof AsmLw) { if (((AsmLw) firstInstr).isPassIarg == 1) { int originOffset = ((AsmImm32) (((AsmLw) firstInstr).getOffset())).getValue(); int newOffset = addOffSet + originOffset; FI = 0; storeOrLoadFromMemory(newOffset, (AsmReg) (((AsmL) firstInstr).getDst()), firstInstr, "load", 1, 0); firstInstr.removeFromList(); } } if (firstInstr instanceof AsmLd) { if (((AsmLd) firstInstr).isPassIarg == 1) { int originOffset = ((AsmImm32) (((AsmLd) firstInstr).getOffset())).getValue(); int newOffset = addOffSet + originOffset; FI = 0; storeDOrLoadDFromMemory(newOffset, (AsmReg) (((AsmL) firstInstr).getDst()), firstInstr, "load", 1, 0); firstInstr.removeFromList(); } } if (firstInstr instanceof AsmFlw) { if (((AsmFlw) firstInstr).isPassIarg == 1) { int originOffset = ((AsmImm32) (((AsmFlw) firstInstr).getOffset())).getValue(); int newOffset = addOffSet + originOffset; FI = 1;
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
storeOrLoadFromMemory(newOffset, (AsmReg) (((AsmL) firstInstr).getDst()), firstInstr, "load", 1, 0); firstInstr.removeFromList(); } } } firstInstr = (AsmInstr) firstInstr.getNext(); } } } public void changeStores(AsmFunction function) { for (CustomList.Node asmBlock : function.getBlocks()) { AsmInstr instrHead = (AsmInstr) ((AsmBlock) asmBlock).getInstrs().getHead(); while (instrHead != null) { if (instrHead instanceof AsmSw) { if (((AsmSw) instrHead).isPassIarg == 1) { int originOffset = ((AsmImm32) (((AsmSw) instrHead).getOffset())).getValue(); int newOffset = addOffSet + originOffset; FI = 0; storeOrLoadFromMemory(newOffset, (AsmReg) (((AsmS) instrHead).getSrc()), instrHead, "store", 1, 0); instrHead.removeFromList(); } } if (instrHead instanceof AsmSd) { if (((AsmSd) instrHead).isPassIarg == 1) { int originOffset = ((AsmImm32) (((AsmSd) instrHead).getOffset())).getValue(); int newOffset = addOffSet + originOffset; FI = 0; storeDOrLoadDFromMemory(newOffset, (AsmReg) (((AsmS) instrHead).getSrc()), instrHead, "store", 1, 0); instrHead.removeFromList(); } } if (instrHead instanceof AsmFsw) { if (((AsmFsw) instrHead).isPassIarg == 1) { int originOffset = ((AsmImm32) (((AsmFsw) instrHead).getOffset())).getValue(); int newOffset = addOffSet + originOffset; FI = 1; storeOrLoadFromMemory(newOffset, (AsmReg) (((AsmS) instrHead).getSrc()), instrHead, "store", 1, 0); instrHead.removeFromList(); } } instrHead = (AsmInstr) instrHead.getNext(); } } } private void allocAndRecycleSP(AsmFunction function) { int offset = 0; offset = function.getWholeSize(); if (offset % 8 != 0) { function.addAllocaSize(4); addOffSet += 4; } offset = function.getWholeSize() - 8; if (function.getRaSize() != 0) { if (offset >= -2048 && offset <= 2047) { AsmSd asmSd = new AsmSd(RegGeter.RA, RegGeter.SP, new AsmImm12(offset)); ((AsmBlock) function.getBlocks().getHead()).addInstrHead(asmSd); } else { AsmReg tmpMove = RegGeter.AllRegsInt.get(5); AsmMove asmMove = new AsmMove(tmpMove, new AsmImm32(offset)); AsmOperand tmpAdd = RegGeter.AllRegsInt.get(5); AsmAdd asmAdd = new AsmAdd(tmpAdd, RegGeter.SP, tmpMove); AsmSd asmSd = new AsmSd(RegGeter.RA, tmpAdd, new AsmImm12(0)); ((AsmBlock) function.getBlocks().getHead()).addInstrHead(asmSd); ((AsmBlock) function.getBlocks().getHead()).addInstrHead(asmAdd); ((AsmBlock) function.getBlocks().getHead()).addInstrHead(asmMove); } }
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
offset = -function.getWholeSize(); if (offset >= -2048 && offset <= 2047) { AsmAdd asmAdd = new AsmAdd(RegGeter.SP, RegGeter.SP, new AsmImm12(offset)); ((AsmBlock) function.getBlocks().getHead()).addInstrHead(asmAdd); } else { AsmOperand tmpMove = RegGeter.AllRegsInt.get(5); AsmMove asmMove = new AsmMove(tmpMove, new AsmImm32(offset)); AsmAdd asmAdd = new AsmAdd(RegGeter.SP, RegGeter.SP, tmpMove); ((AsmBlock) function.getBlocks().getHead()).addInstrHead(asmAdd); ((AsmBlock) function.getBlocks().getHead()).addInstrHead(asmMove); } offset = function.getWholeSize() - 8; if (function.getRaSize() != 0) { if (offset >= -2048 && offset <= 2047) { AsmLd asmLd = new AsmLd(RegGeter.RA, RegGeter.SP, new AsmImm12(offset)); asmLd.insertBefore(function.getTailBlock().getInstrTail()); } else { AsmOperand tmpMove = RegGeter.AllRegsInt.get(5); AsmMove asmMove = new AsmMove(tmpMove, new AsmImm32(offset)); AsmOperand tmpAdd = RegGeter.AllRegsInt.get(5); AsmAdd asmAdd = new AsmAdd(tmpAdd, RegGeter.SP, tmpMove); AsmLd asmLd = new AsmLd(RegGeter.RA, tmpAdd, new AsmImm12(0)); asmMove.insertBefore(function.getTailBlock().getInstrTail()); asmAdd.insertBefore(function.getTailBlock().getInstrTail()); asmLd.insertBefore(function.getTailBlock().getInstrTail()); } AsmAdd asmAddd = new AsmAdd(RegGeter.SP, RegGeter.SP, parseConstIntOperand(function.getWholeSize(), 12, function)); asmAddd.insertBefore(function.getTailBlock().getInstrTail()); } } private AsmOperand parseConstIntOperand(int value, int maxImm, AsmFunction function) { AsmImm32 asmImm32 = new AsmImm32(value); AsmImm12 asmImm12 = new AsmImm12(value); if (maxImm == 32) { return asmImm32; } if (maxImm == 12 && (value >= -2048 && value <= 2047)) { return asmImm12; } AsmOperand tmpReg = RegGeter.AllRegsInt.get(5); AsmMove asmMove = new AsmMove(tmpReg, asmImm32); asmMove.insertBefore(function.getTailBlock().getInstrTail()); return tmpReg; } //调用规约的完成是假定我们已经成功实现活跃性分析的基础上的,此阶段的调用规约我们先只实现整数寄存器的 //callerSave的寄存器有x1(ra),x5-7(t0-2),x10-11(a0-a1),x12-17(a2-7),x28-31(t3-6) private void storeOrLoadFromMemory(int spillPlace, AsmReg reg, AsmInstr nowInstr, String type, int foreOrBack, int needVir) { if (spillPlace >= -2048 && spillPlace <= 2047) { AsmImm12 place = new AsmImm12(spillPlace); if (type.equals("store")) { if (foreOrBack == 0) { if (FI == 0) { AsmSw store = new AsmSw(reg, RegGeter.SP, place); store.insertBefore(nowInstr); } else { AsmFsw store = new AsmFsw(reg, RegGeter.SP, place); store.insertBefore(nowInstr); } } else { if (FI == 0) { AsmSw store = new AsmSw(reg, RegGeter.SP, place); store.insertAfter(nowInstr); } else { AsmFsw store = new AsmFsw(reg, RegGeter.SP, place); store.insertAfter(nowInstr);
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
} } } else if (type.equals("load")) { if (foreOrBack == 0) { if (FI == 0) { AsmLw load = new AsmLw(reg, RegGeter.SP, place); load.insertBefore(nowInstr); } else { AsmFlw load = new AsmFlw(reg, RegGeter.SP, place); load.insertBefore(nowInstr); } } else { if (FI == 0) { AsmLw load = new AsmLw(reg, RegGeter.SP, place); load.insertAfter(nowInstr); } else { AsmFlw load = new AsmFlw(reg, RegGeter.SP, place); load.insertAfter(nowInstr); } } } else { throw new RuntimeException("storeOrLoadFromMemory type error"); } } else { AsmReg tmpMove = null; AsmReg tmpAdd = null; if (needVir == 0) { tmpMove = RegGeter.AllRegsInt.get(5); tmpAdd = RegGeter.AllRegsInt.get(5); } else { tmpMove = new AsmVirReg(); tmpAdd = tmpMove; } AsmMove asmMove = new AsmMove(tmpMove, new AsmImm32(spillPlace)); AsmAdd asmAdd = new AsmAdd(tmpAdd, RegGeter.SP, tmpMove); if (foreOrBack == 0) { asmMove.insertBefore(nowInstr); asmAdd.insertBefore(nowInstr); if (type.equals("load")) { if (FI == 0) { AsmLw load = new AsmLw(reg, tmpAdd, new AsmImm12(0)); load.insertBefore(nowInstr); } else { AsmFlw load = new AsmFlw(reg, tmpAdd, new AsmImm12(0)); load.insertBefore(nowInstr); } } else if (type.equals("store")) { if (FI == 0) { AsmSw store = new AsmSw(reg, tmpAdd, new AsmImm12(0)); store.insertBefore(nowInstr); } else { AsmFsw store = new AsmFsw(reg, tmpAdd, new AsmImm12(0)); store.insertBefore(nowInstr); } } else { throw new RuntimeException("storeOrLoadFromMemory type error"); } } else { if (type.equals("load")) { if (FI == 0) { AsmLw load = new AsmLw(reg, tmpAdd, new AsmImm12(0)); load.insertAfter(nowInstr); } else { AsmFlw load = new AsmFlw(reg, tmpAdd, new AsmImm12(0)); load.insertAfter(nowInstr); } } else if (type.equals("store")) { if (FI == 0) { AsmSw store = new AsmSw(reg, tmpAdd, new AsmImm12(0)); store.insertAfter(nowInstr);