some opt
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package midend.optimize;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import midend.llvm.instr.IrInstr;
|
||||
import midend.llvm.instr.IrInstrType;
|
||||
@@ -16,7 +17,81 @@ public class CfgMake extends Optimizer {
|
||||
bb.clearCfg();
|
||||
}
|
||||
}
|
||||
deleteUselessInstrs();
|
||||
deleteUnreachedBlocks();
|
||||
makeCfg();
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
func.deleteDeadBlock();
|
||||
}
|
||||
makeDomination();
|
||||
makeDirectDomi();
|
||||
makeDomiFrontier();
|
||||
}
|
||||
|
||||
public void deleteUselessInstrs() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
ArrayList<IrInstr> toDelete = new ArrayList<>();
|
||||
boolean deleteUseless = false;
|
||||
for (IrInstr instr : bb.getInstrs()) {
|
||||
if (!deleteUseless) {
|
||||
if (instr.getInstrType() == IrInstrType.RET ||
|
||||
instr.getInstrType() == IrInstrType.BR ||
|
||||
instr.getInstrType() == IrInstrType.JUMP) {
|
||||
deleteUseless = true;
|
||||
}
|
||||
} else {
|
||||
toDelete.add(instr);
|
||||
}
|
||||
}
|
||||
for (IrInstr instr : toDelete) {
|
||||
bb.deleteInstr(instr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteUnreachedBlocks() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
HashSet<IrBasicBlock> canArrive = new HashSet<>();
|
||||
IrBasicBlock entryBlock = func.getBBlock(0);
|
||||
dfsArrive(entryBlock, canArrive);
|
||||
ArrayList<IrBasicBlock> toDelete = new ArrayList<>();
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
if (!canArrive.contains(bb)) {
|
||||
toDelete.add(bb);
|
||||
}
|
||||
}
|
||||
for (IrBasicBlock bb : toDelete) {
|
||||
func.deleteBBlock(bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dfsArrive(IrBasicBlock bb, HashSet<IrBasicBlock> canArrive) {
|
||||
if (!canArrive.contains(bb)) {
|
||||
canArrive.add(bb);
|
||||
}
|
||||
IrInstr lastInstr = bb.getLastInstr();
|
||||
if (lastInstr != null) {
|
||||
if (lastInstr.getInstrType() == IrInstrType.BR) {
|
||||
BranchInstr branchInstr = (BranchInstr) lastInstr;
|
||||
IrBasicBlock trueBlock = branchInstr.getTrueBB();
|
||||
IrBasicBlock falseBlock = branchInstr.getFalseBB();
|
||||
if (!canArrive.contains(trueBlock)) {
|
||||
dfsArrive(trueBlock, canArrive);
|
||||
}
|
||||
if (!canArrive.contains(falseBlock)) {
|
||||
dfsArrive(falseBlock, canArrive);
|
||||
}
|
||||
} else if (lastInstr.getInstrType() == IrInstrType.JUMP) {
|
||||
JumpInstr jumpInstr = (JumpInstr) lastInstr;
|
||||
IrBasicBlock jumpBlock = jumpInstr.getTargetBlock();
|
||||
if (!canArrive.contains(jumpBlock)) {
|
||||
dfsArrive(jumpBlock, canArrive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void makeCfg() {
|
||||
@@ -76,8 +151,8 @@ public class CfgMake extends Optimizer {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
for (IrBasicBlock domi : bb.getDomied()) {
|
||||
HashSet<IrBasicBlock> bbDomi = bb.getDomied();
|
||||
HashSet<IrBasicBlock> domiDomi = domi.getDomied();
|
||||
HashSet<IrBasicBlock> bbDomi = new HashSet<>(bb.getDomied());
|
||||
HashSet<IrBasicBlock> domiDomi = new HashSet<>(domi.getDomied());
|
||||
for (IrBasicBlock domiDomiBB : domiDomi) {
|
||||
if (bbDomi.contains(domiDomiBB)) {
|
||||
bbDomi.remove(domiDomiBB);
|
||||
|
||||
20
midend/optimize/DeleteDead.java
Normal file
20
midend/optimize/DeleteDead.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package midend.optimize;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
|
||||
public class DeleteDead extends Optimizer {
|
||||
public void optimize() {
|
||||
|
||||
}
|
||||
|
||||
public void deleteDeadFunc() {
|
||||
IrFuncValue mainFunc = getIrModule().getMainFunc();
|
||||
HashSet<IrFuncValue> liveFuncs = new HashSet<>();
|
||||
liveFuncs.add(mainFunc);
|
||||
findLiveFuncs(mainFunc, liveFuncs);
|
||||
}
|
||||
|
||||
public void findLiveFuncs()
|
||||
}
|
||||
36
midend/optimize/MemToReg.java
Normal file
36
midend/optimize/MemToReg.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package midend.optimize;
|
||||
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import midend.llvm.instr.AllocateInstr;
|
||||
import midend.llvm.instr.IrInstr;
|
||||
import midend.llvm.type.IrArrayType;
|
||||
|
||||
public class MemToReg extends Optimizer {
|
||||
public void optimize() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
IrBasicBlock entryBlock = func.getBBlock(0);
|
||||
for (IrBasicBlock block : func.getBBlocks()) {
|
||||
ArrayList<IrInstr> instrs = new ArrayList<>(block.getInstrs());
|
||||
for (IrInstr instr : instrs) {
|
||||
if (normalAlloca(instr)) {
|
||||
AllocateInstr allocInstr = (AllocateInstr) instr;
|
||||
PhiInsert phiInsert = new PhiInsert(allocInstr, entryBlock);
|
||||
phiInsert.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean normalAlloca(IrInstr instr) {
|
||||
if (!(instr instanceof AllocateInstr)) {
|
||||
return false;
|
||||
}
|
||||
AllocateInstr allocInstr = (AllocateInstr) instr;
|
||||
return !(allocInstr.getPointeeType() instanceof IrArrayType);
|
||||
}
|
||||
}
|
||||
23
midend/optimize/Optimize.java
Normal file
23
midend/optimize/Optimize.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package midend.optimize;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import midend.llvm.IrModule;
|
||||
|
||||
public class Optimize {
|
||||
private ArrayList<Optimizer> optimizers;
|
||||
|
||||
public Optimize(IrModule module) {
|
||||
Optimizer.setIrModule(module);
|
||||
optimizers = new ArrayList<>();
|
||||
optimizers.add(new CfgMake());
|
||||
optimizers.add(new MemToReg());
|
||||
optimizers.add(new CfgMake());
|
||||
}
|
||||
|
||||
public void run() {
|
||||
for (Optimizer optimizer : optimizers) {
|
||||
optimizer.optimize();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import midend.llvm.IrModule;
|
||||
public class Optimizer {
|
||||
private static IrModule irModule;
|
||||
|
||||
public void setIrModule(IrModule irModule) {
|
||||
public static void setIrModule(IrModule irModule) {
|
||||
Optimizer.irModule = irModule;
|
||||
}
|
||||
|
||||
|
||||
133
midend/optimize/PhiInsert.java
Normal file
133
midend/optimize/PhiInsert.java
Normal file
@@ -0,0 +1,133 @@
|
||||
package midend.optimize;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Stack;
|
||||
|
||||
import midend.llvm.IrBuilder;
|
||||
import midend.llvm.constant.IrConstantInt;
|
||||
import midend.llvm.instr.AllocateInstr;
|
||||
import midend.llvm.instr.IrInstr;
|
||||
import midend.llvm.instr.StoreInstr;
|
||||
import midend.llvm.instr.LoadInstr;
|
||||
import midend.llvm.instr.PhiInstr;
|
||||
import midend.llvm.use.IrUser;
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class PhiInsert {
|
||||
private ArrayList<IrInstr> defineInstrs;
|
||||
private ArrayList<IrInstr> useInstrs;
|
||||
private AllocateInstr allocInstr;
|
||||
private IrBasicBlock entryBlock;
|
||||
private ArrayList<IrBasicBlock> defBlocks;
|
||||
private ArrayList<IrBasicBlock> useBlocks;
|
||||
private Stack<IrValue> workList;
|
||||
|
||||
public PhiInsert(AllocateInstr allocInstr, IrBasicBlock entryBlock) {
|
||||
this.defineInstrs = new ArrayList<>();
|
||||
this.useInstrs = new ArrayList<>();
|
||||
this.allocInstr = allocInstr;
|
||||
this.entryBlock = entryBlock;
|
||||
this.defBlocks = new ArrayList<>();
|
||||
this.useBlocks = new ArrayList<>();
|
||||
this.workList = new Stack<>();
|
||||
}
|
||||
|
||||
public IrValue getNewValue() {
|
||||
if (workList.isEmpty()) {
|
||||
return new IrConstantInt(0);
|
||||
}
|
||||
return workList.peek();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
makeDefAndUse();
|
||||
insertPhiNodes();
|
||||
changeLoadAndStoreToReg(entryBlock);
|
||||
}
|
||||
|
||||
public void makeDefAndUse() {
|
||||
ArrayList<IrUser> users = new ArrayList<>(allocInstr.getUsers());
|
||||
for (IrUser user : users) {
|
||||
IrInstr instr = (IrInstr) user;
|
||||
if (instr instanceof StoreInstr) {
|
||||
defineInstrs.add(instr);
|
||||
IrBasicBlock defBlock = instr.getBBlock();
|
||||
if (!defBlocks.contains(defBlock)) {
|
||||
defBlocks.add(defBlock);
|
||||
}
|
||||
} else if (instr instanceof LoadInstr){
|
||||
useInstrs.add(instr);
|
||||
IrBasicBlock useBlock = instr.getBBlock();
|
||||
if (!useBlocks.contains(useBlock)) {
|
||||
useBlocks.add(useBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void insertPhiNodes() {
|
||||
HashSet<IrBasicBlock> hasPhiBlocks = new HashSet<>();
|
||||
Stack<IrBasicBlock> defStack = new Stack<>();
|
||||
for (IrBasicBlock defBlock : defBlocks) {
|
||||
defStack.push(defBlock);
|
||||
}
|
||||
while (!defStack.isEmpty()) {
|
||||
IrBasicBlock currBlock = defStack.pop();
|
||||
for (IrBasicBlock frontierBlock : currBlock.getDomiFrontier()) {
|
||||
if (hasPhiBlocks.contains(frontierBlock)) {
|
||||
continue;
|
||||
}
|
||||
//插入phi节点
|
||||
insertPhiNode(frontierBlock);
|
||||
hasPhiBlocks.add(frontierBlock);
|
||||
if (!defBlocks.contains(frontierBlock)) {
|
||||
defStack.push(frontierBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void insertPhiNode(IrBasicBlock block) {
|
||||
PhiInstr phiInstr = new PhiInstr(allocInstr.getPointeeType(), block, IrBuilder.getLocalName(block.getFunc()));
|
||||
block.addInstr(phiInstr, 0);
|
||||
defineInstrs.add(phiInstr);
|
||||
useInstrs.add(phiInstr);
|
||||
}
|
||||
|
||||
public void changeLoadAndStoreToReg(IrBasicBlock block) {
|
||||
Stack<IrValue> workListCopy = new Stack<>();
|
||||
workListCopy.addAll(workList);
|
||||
ArrayList<IrInstr> deleteInstrs = new ArrayList<>();
|
||||
for(IrInstr instr : block.getInstrs()) {
|
||||
if (instr instanceof LoadInstr && useInstrs.contains(instr)) {
|
||||
instr.replaceUserToAnother(getNewValue());
|
||||
deleteInstrs.add(instr);
|
||||
} else if (instr instanceof StoreInstr && defineInstrs.contains(instr)) {
|
||||
StoreInstr storeInstr = (StoreInstr) instr;
|
||||
IrValue value = storeInstr.getValue();
|
||||
workList.push(value);
|
||||
deleteInstrs.add(instr);
|
||||
} else if (instr instanceof PhiInstr && defineInstrs.contains(instr)) {
|
||||
workList.push(instr);
|
||||
} else if (instr == allocInstr) {
|
||||
deleteInstrs.add(instr);
|
||||
}
|
||||
}
|
||||
for (IrInstr instr : deleteInstrs) {
|
||||
block.deleteInstr(instr);
|
||||
}
|
||||
for (IrBasicBlock succ : block.getSuccs()) {
|
||||
IrInstr firstInstr = succ.getFirstInstr();
|
||||
if (firstInstr instanceof PhiInstr && useInstrs.contains(firstInstr)) {
|
||||
PhiInstr phiInstr = (PhiInstr) firstInstr;
|
||||
phiInstr.setValueForPred(block, getNewValue());
|
||||
}
|
||||
}
|
||||
for (IrBasicBlock domiBB : block.getDirectDomies()) {
|
||||
changeLoadAndStoreToReg(domiBB);
|
||||
}
|
||||
workList = workListCopy;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user