From df96fa80c7a20ec4d5a4d8cf0f00dbc36a0f5090 Mon Sep 17 00:00:00 2001 From: Minero Aoki Date: Tue, 23 Sep 2008 15:48:39 +0000 Subject: [PATCH] * 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 --- ChangeLog | 10 + net/loveruby/cflat/asm/PeepholeOptimizer.java | 268 ++++++++++-------- net/loveruby/cflat/compiler/Options.java | 2 +- .../{ClonableIterator.java => Cursor.java} | 21 +- 4 files changed, 176 insertions(+), 125 deletions(-) rename net/loveruby/cflat/utils/{ClonableIterator.java => Cursor.java} (51%) diff --git a/ChangeLog b/ChangeLog index e2ebdb1..f18d7e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Wed Sep 24 00:48:37 2008 Minero Aoki + + * 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 * net/loveruby/cflat/compiler/CodeGenerator.java: apply jump diff --git a/net/loveruby/cflat/asm/PeepholeOptimizer.java b/net/loveruby/cflat/asm/PeepholeOptimizer.java index 6510c9a..7be0ff5 100644 --- a/net/loveruby/cflat/asm/PeepholeOptimizer.java +++ b/net/loveruby/cflat/asm/PeepholeOptimizer.java @@ -1,26 +1,75 @@ package net.loveruby.cflat.asm; -import net.loveruby.cflat.utils.ClonableIterator; +import net.loveruby.cflat.utils.Cursor; import java.util.*; public class PeepholeOptimizer implements AsmOptimizer { - protected List filters; + protected Map filterSet; // Map> 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) { - 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 - protected List defaultFilterSet() { - List set = new ArrayList(); + protected Filter matchFilter(Cursor asms) { + Instruction insn = (Instruction)asms.current(); + 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 - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("mov", imm(0), reg()), - new InsnTemplate() { + new InsnTransform() { public Instruction apply(Instruction insn) { return insn.build("xor", insn.operand2(), insn.operand2()); } @@ -28,21 +77,21 @@ public class PeepholeOptimizer implements AsmOptimizer { )); // add - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("add", imm(-1), reg()), - new InsnTemplate() { + new InsnTransform() { public Instruction apply(Instruction insn) { return insn.build("dec", insn.operand2()); } } )); - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("add", imm(0), reg()), null )); - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("add", imm(1), reg()), - new InsnTemplate() { + new InsnTransform() { public Instruction apply(Instruction insn) { return insn.build("inc", insn.operand2()); } @@ -50,21 +99,21 @@ public class PeepholeOptimizer implements AsmOptimizer { )); // sub - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("sub", imm(-1), reg()), - new InsnTemplate() { + new InsnTransform() { public Instruction apply(Instruction insn) { return insn.build("inc", insn.operand2()); } } )); - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("sub", imm(0), reg()), null )); - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("sub", imm(1), reg()), - new InsnTemplate() { + new InsnTransform() { public Instruction apply(Instruction insn) { return insn.build("dec", insn.operand2()); } @@ -72,52 +121,53 @@ public class PeepholeOptimizer implements AsmOptimizer { )); // imul - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("imul", imm(0), reg()), - new InsnTemplate() { + new InsnTransform() { public Instruction apply(Instruction insn) { return insn.build("xorl", insn.operand2(), insn.operand2()); } } )); - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("imul", imm(1), reg()), null )); - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("imul", imm(2), reg()), - new InsnTemplate() { + new InsnTransform() { public Instruction apply(Instruction insn) { return insn.build("sal", imm(1), insn.operand2()); } } )); - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("imul", imm(4), reg()), - new InsnTemplate() { + new InsnTransform() { public Instruction apply(Instruction insn) { return insn.build("sal", imm(2), insn.operand2()); } } )); - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("imul", imm(8), reg()), - new InsnTemplate() { + new InsnTransform() { public Instruction apply(Instruction insn) { return insn.build("sal", imm(3), insn.operand2()); } } )); - set.add(new Filter( + set.add(new SingleInsnFilter( new InsnPattern("imul", imm(16), reg()), - new InsnTemplate() { + new InsnTransform() { public Instruction apply(Instruction insn) { return insn.build("sal", imm(4), insn.operand2()); } } )); - return set; + // jmp + set.add(new JumpEliminationFilter()); } protected ImmediateValue imm(long n) { @@ -128,57 +178,40 @@ public class PeepholeOptimizer implements AsmOptimizer { return new AnyRegisterPattern(); } - public List insnOptimization(List assemblies) { - List result = new ArrayList(); - Iterator asms = assemblies.iterator(); - while (asms.hasNext()) { - 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; + abstract class Filter { + abstract public String[] patternHeads(); + abstract public boolean match(Cursor asms); + abstract public void optimize(Cursor src, List dest); } - protected Assembly optimizeInstruction(Instruction insn) { - Iterator it = filters.iterator(); - while (it.hasNext()) { - Filter filter = (Filter)it.next(); - if (filter.match(insn)) { - return filter.optimize(insn); - } - } - return insn; - } + // + // single instruction optimization + // - class Filter { + class SingleInsnFilter extends Filter { 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.template = template; + this.transform = transform; } - public boolean match(Instruction insn) { - return pattern.match(insn); + /** Matching mnemonic of InstructionPattern */ + public String[] patternHeads() { + return new String[] { pattern.name }; } - public Instruction optimize(Instruction insn) { - if (template == null) { - return null; + public boolean match(Cursor asms) { + return pattern.match((Instruction)asms.current()); + } + + public void optimize(Cursor src, List dest) { + if (transform == null) { + ; // remove instruction } 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); } @@ -215,59 +248,60 @@ public class PeepholeOptimizer implements AsmOptimizer { // jumpElimination // - public List jumpElimination(List assemblies) { - List result = new ArrayList(); - ClonableIterator asms = new ClonableIterator(assemblies); - while (asms.hasNext()) { - Assembly asm = (Assembly)asms.next(); - if (isUselessJump(asm, asms)) { - ; // remove useless jump - } - else { - result.add(asm); - } + class JumpEliminationFilter extends Filter { + public JumpEliminationFilter() { } - return result; - } - protected boolean isUselessJump(Assembly asm, ClonableIterator asms) { - if (! asm.isInstruction()) return false; - Instruction insn = (Instruction)asm; - if (! insn.isJumpInstruction()) return false; - return doesLabelFollows(asms.dup(), insn.jmpDestination()); - } + protected String[] jmpInsns() { + return new String[] { "jmp", "jz", "jne", "je", "jne" }; + } - /** - * Returns true if jmpDest is found in asms before any instruction - * or directives. For example, this method returns true if contents - * of asms are: - * - * if_end3: - * # comment - * jmpDest: - * mov - * mov - * add - */ - protected boolean doesLabelFollows(ClonableIterator asms, Label jmpDest) { - while (asms.hasNext()) { - Assembly asm = (Assembly)asms.next(); - if (asm.isLabel()) { - Label label = (Label)asm; - if (label.equals(jmpDest)) { - return true; + 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()); + } + + /** + * Returns true if jmpDest is found in asms before any instruction + * or directives. For example, this method returns true if contents + * of asms are: + * + * if_end3: + * # comment + * jmpDest: + * mov + * mov + * add + */ + protected boolean doesLabelFollows(Cursor asms, Label jmpDest) { + while (asms.hasNext()) { + Assembly asm = (Assembly)asms.next(); + if (asm.isLabel()) { + Label label = (Label)asm; + if (label.equals(jmpDest)) { + return true; + } + else { + continue; + } } - else { + else if (asm.isComment()) { continue; } + else { + // instructions or directives + return false; + } } - else if (asm.isComment()) { - continue; - } - else { - return false; - } + return false; } - return false; } } diff --git a/net/loveruby/cflat/compiler/Options.java b/net/loveruby/cflat/compiler/Options.java index 072dc12..1da2c3d 100644 --- a/net/loveruby/cflat/compiler/Options.java +++ b/net/loveruby/cflat/compiler/Options.java @@ -119,7 +119,7 @@ class Options { return new NullAsmOptimizer(); } else { - return new PeepholeOptimizer(); + return PeepholeOptimizer.defaultSet(); } } diff --git a/net/loveruby/cflat/utils/ClonableIterator.java b/net/loveruby/cflat/utils/Cursor.java similarity index 51% rename from net/loveruby/cflat/utils/ClonableIterator.java rename to net/loveruby/cflat/utils/Cursor.java index e2a8c45..3fa2431 100644 --- a/net/loveruby/cflat/utils/ClonableIterator.java +++ b/net/loveruby/cflat/utils/Cursor.java @@ -1,25 +1,25 @@ package net.loveruby.cflat.utils; import java.util.*; -public class ClonableIterator implements Iterator { +public class Cursor implements Iterator { protected List list; protected int index; - public ClonableIterator(List list) { + public Cursor(List list) { this(list, 0); } - protected ClonableIterator(List list, int index) { + protected Cursor(List list, int index) { this.list = list; this.index = index; } public Object clone() { - return new ClonableIterator(list, index); + return new Cursor(list, index); } - public ClonableIterator dup() { - return new ClonableIterator(list, index); + public Cursor dup() { + return new Cursor(list, index); } public boolean hasNext() { @@ -30,11 +30,18 @@ public class ClonableIterator implements Iterator { 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() { list.remove(index); } public String toString() { - return "#"; + return "#"; } }