Skip to content

Commit

Permalink
add aggressive dead code elimination
Browse files Browse the repository at this point in the history
  • Loading branch information
1024th committed Feb 4, 2023
1 parent d201b80 commit c84abc0
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 6 deletions.
6 changes: 6 additions & 0 deletions src/ir/BasicBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ public void addInstBeforeTerminator(BaseInst inst) {
insts.add(insts.size() - 1, inst);
}

public BaseInst getTerminator() {
if (!this.terminated)
throw new Error("get terminator of unterminated block");
return insts.getLast();
}

public void addAlloca(AllocaInst allocaInst) {
for (int i = 0; i < insts.size(); ++i) {
var inst = insts.get(i);
Expand Down
100 changes: 100 additions & 0 deletions src/middleend/ADCE.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package middleend;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;

import ir.BasicBlock;
import ir.inst.BaseInst;
import ir.inst.CallInst;
import ir.inst.RetInst;
import ir.inst.StoreInst;

/**
* Aggressive Dead Code Elimination
*/
public class ADCE {
void runOnModule(ir.Module module) {
module.funcs.forEach(this::runOnFunc);
}

void runOnFunc(ir.Function func) {
new CFGBuilder().runOnFunc(func);
new DomTreeBuilder(true).runOnFunc(func);
markLive(func);

for (var block : func.blocks) {
var iter = block.insts.iterator();
while (iter.hasNext()) {
var inst = iter.next();
if (liveInst.contains(inst))
continue;
if (inst.isTerminator()) {
continue;
}
iter.remove();
}
}
}

Queue<BaseInst> worklist = new LinkedList<>();

HashSet<BaseInst> liveInst = new HashSet<>();
HashSet<BasicBlock> liveBlock = new HashSet<>();

void markLive(ir.Function func) {
for (var block : func.blocks) {
for (var inst : block.insts)
if (isAlwaysLive(inst))
markInstLive(inst);
}

while (!worklist.isEmpty()) {
var inst = worklist.poll();
markInstLive(inst);
markBlockLive(inst.parent);

for (var operand : inst.operands) {
if (operand instanceof BaseInst i) {
markInstLive(i);
} else if (operand instanceof BasicBlock b) {
markTerminatorLive(b);
}
}
}
}

/**
* We do not perform function-level side effect analysis, i.e.,
* we assume every function call to be live.
*/
boolean isAlwaysLive(BaseInst inst) {
if (inst instanceof RetInst)
return true;
if (inst instanceof StoreInst)
return true;
if (inst instanceof CallInst)
return true;
return false;
}

void markInstLive(BaseInst inst) {
if (liveInst.contains(inst))
return;
liveInst.add(inst);
worklist.offer(inst);
}

void markTerminatorLive(BasicBlock block) {
markInstLive(block.getTerminator());
}

void markBlockLive(BasicBlock block) {
if (liveBlock.contains(block))
return;
liveBlock.add(block);
for (var dependence : block.dtNode.domFrontier) {
markTerminatorLive(dependence.origin);
}
}
}
38 changes: 32 additions & 6 deletions src/middleend/DomTreeBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,35 @@

/** Dominator Tree Builder */
public class DomTreeBuilder {
boolean reversed;

/**
* @param reversed use reversed control flow graph
*/
public DomTreeBuilder(boolean reversed) {
this.reversed = reversed;
}

public DomTreeBuilder() {
this(false);
}

BasicBlock entry(ir.Function func) {
return reversed ? func.exitBlock : func.entryBlock;
}

ArrayList<BasicBlock> predecessor(Node node) {
return reversed ? node.origin.nexts : node.origin.prevs;
}

ArrayList<BasicBlock> successor(Node node) {
return reversed ? node.origin.prevs : node.origin.nexts;
}

public void runOnFunc(ir.Function func) {
computeIDom(func);
computeChlidren(func);
computeDF(func.entryBlock.dtNode);
computeDF(entry(func).dtNode);

// func.blocks.forEach(this::debugPrint);
}
Expand All @@ -37,7 +61,7 @@ void computeChlidren(ir.Function func) {

void computeDF(Node node) {
var S = new HashSet<Node>();
for (var nxtBlock : node.origin.nexts) {
for (var nxtBlock : successor(node)) {
var nxt = nxtBlock.dtNode;
if (nxt.idom != node)
S.add(nxt);
Expand Down Expand Up @@ -69,8 +93,10 @@ public Node(BasicBlock origin) {

public void clear() {
dfn = -1;
semi = samedom = idom = ancestor = best = null;
parent = semi = samedom = idom = ancestor = best = null;
bucket.clear();
children.clear();
domFrontier.clear();
}

public boolean isDominatorOf(Node o) {
Expand Down Expand Up @@ -99,7 +125,7 @@ private void dfs(Node p, Node n) {
dfnOrder.add(n);
n.parent = p;
dfn++;
for (var succ : n.origin.nexts) {
for (var succ : successor(n)) {
dfs(n, succ.dtNode);
}
}
Expand All @@ -110,12 +136,12 @@ void computeIDom(ir.Function func) {
for (var b : func.blocks) {
b.dtNode.clear();
}
dfs(null, func.entryBlock.dtNode);
dfs(null, entry(func).dtNode);
for (int i = dfn - 1; i >= 1; --i) {
var n = dfnOrder.get(i);
var p = n.parent;
var s = p;
for (var v : n.origin.prevs) {
for (var v : predecessor(n)) {
if (v.dtNode.dfn < 0)
continue;
Node ss;
Expand Down
3 changes: 3 additions & 0 deletions src/middleend/MiddleEnd.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ public MiddleEnd(FrontEnd frontEnd, boolean debug) throws Exception {
this.irModule.funcs.forEach(func -> mem2reg.runOnFunc(func));
debugPrint("out-mem2reg.ll");

new ADCE().runOnModule(irModule);
debugPrint("out-adce.ll");

new PhiElimination().runOnModule(irModule);
debugPrint("out-phi-elim.ll");
}
Expand Down

0 comments on commit c84abc0

Please sign in to comment.