mirror of https://github.com/aamine/cbc
* net/loveruby/cflat/asm/PeepholeOptimizer.java: unify insn optimization and jump elimination.
* net/loveruby/cflat/utils/ClonableIterator.java -> Cursor.java * net/loveruby/cflat/compiler/Options.java: use default optimization rule set for -O. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4052 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
parent
d32b629568
commit
df96fa80c7
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
||||||
|
Wed Sep 24 00:48:37 2008 Minero Aoki <aamine@loveruby.net>
|
||||||
|
|
||||||
|
* net/loveruby/cflat/asm/PeepholeOptimizer.java: unify insn
|
||||||
|
optimization and jump elimination.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/utils/ClonableIterator.java -> Cursor.java
|
||||||
|
|
||||||
|
* net/loveruby/cflat/compiler/Options.java: use default
|
||||||
|
optimization rule set for -O.
|
||||||
|
|
||||||
Tue Sep 23 22:50:52 2008 Minero Aoki <aamine@loveruby.net>
|
Tue Sep 23 22:50:52 2008 Minero Aoki <aamine@loveruby.net>
|
||||||
|
|
||||||
* net/loveruby/cflat/compiler/CodeGenerator.java: apply jump
|
* net/loveruby/cflat/compiler/CodeGenerator.java: apply jump
|
||||||
|
|
|
@ -1,26 +1,75 @@
|
||||||
package net.loveruby.cflat.asm;
|
package net.loveruby.cflat.asm;
|
||||||
import net.loveruby.cflat.utils.ClonableIterator;
|
import net.loveruby.cflat.utils.Cursor;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class PeepholeOptimizer implements AsmOptimizer {
|
public class PeepholeOptimizer implements AsmOptimizer {
|
||||||
protected List filters;
|
protected Map filterSet; // Map<String, List<Filter>>
|
||||||
|
|
||||||
public PeepholeOptimizer() {
|
public PeepholeOptimizer() {
|
||||||
this.filters = defaultFilterSet();
|
this.filterSet = new HashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Filter filter) {
|
||||||
|
String[] heads = filter.patternHeads();
|
||||||
|
for (int i = 0; i < heads.length; i++) {
|
||||||
|
String head = heads[i];
|
||||||
|
List list = (List)filterSet.get(head);
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList();
|
||||||
|
list.add(filter);
|
||||||
|
filterSet.put(head, list);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
list.add(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List optimize(List assemblies) {
|
public List optimize(List assemblies) {
|
||||||
return jumpElimination(insnOptimization(assemblies));
|
List result = new ArrayList();
|
||||||
|
Cursor cursor = new Cursor(assemblies);
|
||||||
|
while (cursor.hasNext()) {
|
||||||
|
Assembly asm = (Assembly)cursor.next();
|
||||||
|
if (asm.isInstruction()) {
|
||||||
|
Filter matched = matchFilter(cursor);
|
||||||
|
if (matched != null) {
|
||||||
|
matched.optimize(cursor, result);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.add(asm);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// List<Filter>
|
protected Filter matchFilter(Cursor asms) {
|
||||||
protected List defaultFilterSet() {
|
Instruction insn = (Instruction)asms.current();
|
||||||
List set = new ArrayList();
|
List filters = (List)filterSet.get(insn.mnemonic());
|
||||||
|
if (filters == null) return null;
|
||||||
|
if (filters.isEmpty()) return null;
|
||||||
|
Iterator it = filters.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Filter filter = (Filter)it.next();
|
||||||
|
if (filter.match(asms)) {
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public PeepholeOptimizer defaultSet() {
|
||||||
|
PeepholeOptimizer set = new PeepholeOptimizer();
|
||||||
|
set.loadDefaultFilters();
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void loadDefaultFilters() {
|
||||||
|
PeepholeOptimizer set = this;
|
||||||
|
|
||||||
// mov
|
// mov
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("mov", imm(0), reg()),
|
new InsnPattern("mov", imm(0), reg()),
|
||||||
new InsnTemplate() {
|
new InsnTransform() {
|
||||||
public Instruction apply(Instruction insn) {
|
public Instruction apply(Instruction insn) {
|
||||||
return insn.build("xor", insn.operand2(), insn.operand2());
|
return insn.build("xor", insn.operand2(), insn.operand2());
|
||||||
}
|
}
|
||||||
|
@ -28,21 +77,21 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
||||||
));
|
));
|
||||||
|
|
||||||
// add
|
// add
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("add", imm(-1), reg()),
|
new InsnPattern("add", imm(-1), reg()),
|
||||||
new InsnTemplate() {
|
new InsnTransform() {
|
||||||
public Instruction apply(Instruction insn) {
|
public Instruction apply(Instruction insn) {
|
||||||
return insn.build("dec", insn.operand2());
|
return insn.build("dec", insn.operand2());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("add", imm(0), reg()),
|
new InsnPattern("add", imm(0), reg()),
|
||||||
null
|
null
|
||||||
));
|
));
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("add", imm(1), reg()),
|
new InsnPattern("add", imm(1), reg()),
|
||||||
new InsnTemplate() {
|
new InsnTransform() {
|
||||||
public Instruction apply(Instruction insn) {
|
public Instruction apply(Instruction insn) {
|
||||||
return insn.build("inc", insn.operand2());
|
return insn.build("inc", insn.operand2());
|
||||||
}
|
}
|
||||||
|
@ -50,21 +99,21 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
||||||
));
|
));
|
||||||
|
|
||||||
// sub
|
// sub
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("sub", imm(-1), reg()),
|
new InsnPattern("sub", imm(-1), reg()),
|
||||||
new InsnTemplate() {
|
new InsnTransform() {
|
||||||
public Instruction apply(Instruction insn) {
|
public Instruction apply(Instruction insn) {
|
||||||
return insn.build("inc", insn.operand2());
|
return insn.build("inc", insn.operand2());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("sub", imm(0), reg()),
|
new InsnPattern("sub", imm(0), reg()),
|
||||||
null
|
null
|
||||||
));
|
));
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("sub", imm(1), reg()),
|
new InsnPattern("sub", imm(1), reg()),
|
||||||
new InsnTemplate() {
|
new InsnTransform() {
|
||||||
public Instruction apply(Instruction insn) {
|
public Instruction apply(Instruction insn) {
|
||||||
return insn.build("dec", insn.operand2());
|
return insn.build("dec", insn.operand2());
|
||||||
}
|
}
|
||||||
|
@ -72,52 +121,53 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
||||||
));
|
));
|
||||||
|
|
||||||
// imul
|
// imul
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("imul", imm(0), reg()),
|
new InsnPattern("imul", imm(0), reg()),
|
||||||
new InsnTemplate() {
|
new InsnTransform() {
|
||||||
public Instruction apply(Instruction insn) {
|
public Instruction apply(Instruction insn) {
|
||||||
return insn.build("xorl", insn.operand2(), insn.operand2());
|
return insn.build("xorl", insn.operand2(), insn.operand2());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("imul", imm(1), reg()),
|
new InsnPattern("imul", imm(1), reg()),
|
||||||
null
|
null
|
||||||
));
|
));
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("imul", imm(2), reg()),
|
new InsnPattern("imul", imm(2), reg()),
|
||||||
new InsnTemplate() {
|
new InsnTransform() {
|
||||||
public Instruction apply(Instruction insn) {
|
public Instruction apply(Instruction insn) {
|
||||||
return insn.build("sal", imm(1), insn.operand2());
|
return insn.build("sal", imm(1), insn.operand2());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("imul", imm(4), reg()),
|
new InsnPattern("imul", imm(4), reg()),
|
||||||
new InsnTemplate() {
|
new InsnTransform() {
|
||||||
public Instruction apply(Instruction insn) {
|
public Instruction apply(Instruction insn) {
|
||||||
return insn.build("sal", imm(2), insn.operand2());
|
return insn.build("sal", imm(2), insn.operand2());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("imul", imm(8), reg()),
|
new InsnPattern("imul", imm(8), reg()),
|
||||||
new InsnTemplate() {
|
new InsnTransform() {
|
||||||
public Instruction apply(Instruction insn) {
|
public Instruction apply(Instruction insn) {
|
||||||
return insn.build("sal", imm(3), insn.operand2());
|
return insn.build("sal", imm(3), insn.operand2());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
set.add(new Filter(
|
set.add(new SingleInsnFilter(
|
||||||
new InsnPattern("imul", imm(16), reg()),
|
new InsnPattern("imul", imm(16), reg()),
|
||||||
new InsnTemplate() {
|
new InsnTransform() {
|
||||||
public Instruction apply(Instruction insn) {
|
public Instruction apply(Instruction insn) {
|
||||||
return insn.build("sal", imm(4), insn.operand2());
|
return insn.build("sal", imm(4), insn.operand2());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
return set;
|
// jmp
|
||||||
|
set.add(new JumpEliminationFilter());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ImmediateValue imm(long n) {
|
protected ImmediateValue imm(long n) {
|
||||||
|
@ -128,57 +178,40 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
||||||
return new AnyRegisterPattern();
|
return new AnyRegisterPattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List insnOptimization(List assemblies) {
|
abstract class Filter {
|
||||||
List result = new ArrayList();
|
abstract public String[] patternHeads();
|
||||||
Iterator asms = assemblies.iterator();
|
abstract public boolean match(Cursor asms);
|
||||||
while (asms.hasNext()) {
|
abstract public void optimize(Cursor src, List dest);
|
||||||
Assembly asm = (Assembly)asms.next();
|
|
||||||
if (! asm.isInstruction()) {
|
|
||||||
result.add(asm);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Assembly optAsm = optimizeInstruction((Instruction)asm);
|
|
||||||
if (optAsm == null) {
|
|
||||||
// remove instruction
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result.add(optAsm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Assembly optimizeInstruction(Instruction insn) {
|
//
|
||||||
Iterator it = filters.iterator();
|
// single instruction optimization
|
||||||
while (it.hasNext()) {
|
//
|
||||||
Filter filter = (Filter)it.next();
|
|
||||||
if (filter.match(insn)) {
|
|
||||||
return filter.optimize(insn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return insn;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Filter {
|
class SingleInsnFilter extends Filter {
|
||||||
protected InsnPattern pattern;
|
protected InsnPattern pattern;
|
||||||
protected InsnTemplate template;
|
protected InsnTransform transform;
|
||||||
|
|
||||||
public Filter(InsnPattern pattern, InsnTemplate template) {
|
public SingleInsnFilter(InsnPattern pattern, InsnTransform transform) {
|
||||||
this.pattern = pattern;
|
this.pattern = pattern;
|
||||||
this.template = template;
|
this.transform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean match(Instruction insn) {
|
/** Matching mnemonic of InstructionPattern */
|
||||||
return pattern.match(insn);
|
public String[] patternHeads() {
|
||||||
|
return new String[] { pattern.name };
|
||||||
}
|
}
|
||||||
|
|
||||||
public Instruction optimize(Instruction insn) {
|
public boolean match(Cursor asms) {
|
||||||
if (template == null) {
|
return pattern.match((Instruction)asms.current());
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
public void optimize(Cursor src, List dest) {
|
||||||
|
if (transform == null) {
|
||||||
|
; // remove instruction
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return template.apply(insn);
|
dest.add(transform.apply((Instruction)src.current()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,7 +240,7 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InsnTemplate {
|
interface InsnTransform {
|
||||||
abstract public Instruction apply(Instruction insn);
|
abstract public Instruction apply(Instruction insn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,25 +248,24 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
||||||
// jumpElimination
|
// jumpElimination
|
||||||
//
|
//
|
||||||
|
|
||||||
public List jumpElimination(List assemblies) {
|
class JumpEliminationFilter extends Filter {
|
||||||
List result = new ArrayList();
|
public JumpEliminationFilter() {
|
||||||
ClonableIterator asms = new ClonableIterator(assemblies);
|
|
||||||
while (asms.hasNext()) {
|
|
||||||
Assembly asm = (Assembly)asms.next();
|
|
||||||
if (isUselessJump(asm, asms)) {
|
|
||||||
; // remove useless jump
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result.add(asm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isUselessJump(Assembly asm, ClonableIterator asms) {
|
protected String[] jmpInsns() {
|
||||||
if (! asm.isInstruction()) return false;
|
return new String[] { "jmp", "jz", "jne", "je", "jne" };
|
||||||
Instruction insn = (Instruction)asm;
|
}
|
||||||
if (! insn.isJumpInstruction()) return false;
|
|
||||||
|
public String[] patternHeads() {
|
||||||
|
return jmpInsns();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void optimize(Cursor src, List dest) {
|
||||||
|
; // remove jump
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean match(Cursor asms) {
|
||||||
|
Instruction insn = (Instruction)asms.current();
|
||||||
return doesLabelFollows(asms.dup(), insn.jmpDestination());
|
return doesLabelFollows(asms.dup(), insn.jmpDestination());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +281,7 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
||||||
* mov
|
* mov
|
||||||
* add
|
* add
|
||||||
*/
|
*/
|
||||||
protected boolean doesLabelFollows(ClonableIterator asms, Label jmpDest) {
|
protected boolean doesLabelFollows(Cursor asms, Label jmpDest) {
|
||||||
while (asms.hasNext()) {
|
while (asms.hasNext()) {
|
||||||
Assembly asm = (Assembly)asms.next();
|
Assembly asm = (Assembly)asms.next();
|
||||||
if (asm.isLabel()) {
|
if (asm.isLabel()) {
|
||||||
|
@ -265,9 +297,11 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// instructions or directives
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ class Options {
|
||||||
return new NullAsmOptimizer();
|
return new NullAsmOptimizer();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new PeepholeOptimizer();
|
return PeepholeOptimizer.defaultSet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
package net.loveruby.cflat.utils;
|
package net.loveruby.cflat.utils;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ClonableIterator implements Iterator {
|
public class Cursor implements Iterator {
|
||||||
protected List list;
|
protected List list;
|
||||||
protected int index;
|
protected int index;
|
||||||
|
|
||||||
public ClonableIterator(List list) {
|
public Cursor(List list) {
|
||||||
this(list, 0);
|
this(list, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ClonableIterator(List list, int index) {
|
protected Cursor(List list, int index) {
|
||||||
this.list = list;
|
this.list = list;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object clone() {
|
public Object clone() {
|
||||||
return new ClonableIterator(list, index);
|
return new Cursor(list, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClonableIterator dup() {
|
public Cursor dup() {
|
||||||
return new ClonableIterator(list, index);
|
return new Cursor(list, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
|
@ -30,11 +30,18 @@ public class ClonableIterator implements Iterator {
|
||||||
return list.get(index++);
|
return list.get(index++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object current() {
|
||||||
|
if (index == 0) {
|
||||||
|
throw new Error("must not happen: Cursor#current");
|
||||||
|
}
|
||||||
|
return list.get(index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
list.remove(index);
|
list.remove(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "#<ClonableIterator list=" + list + " index=" + index + ">";
|
return "#<Cursor list=" + list + " index=" + index + ">";
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue