1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-10-11 12:23:45 +00:00

Implemented PhiMemCoalesce.

This commit is contained in:
jespergravgaard 2017-07-26 19:44:51 +02:00
parent 16d4ab93f0
commit 13c84a1741
9 changed files with 874 additions and 9 deletions

View File

@ -101,22 +101,29 @@ public class Compiler {
Pass3BlockSequencePlanner pass3BlockSequencePlanner = new Pass3BlockSequencePlanner(program, log);
pass3BlockSequencePlanner.plan();
//Pass3PhiLifting pass3PhiLifting = new Pass3PhiLifting(program, log);
//pass3PhiLifting.perform();
//pass3BlockSequencePlanner.plan();
//log.append("CONTROL FLOW GRAPH - PHI LIFTED");
//log.append(program.getGraph().toString(program.getScope()));
//pass2AssertSSA(program, log);
Pass3PhiLifting pass3PhiLifting = new Pass3PhiLifting(program, log);
pass3PhiLifting.perform();
pass3BlockSequencePlanner.plan();
log.append("CONTROL FLOW GRAPH - PHI LIFTED");
log.append(program.getGraph().toString(program.getScope()));
pass2AssertSSA(program, log);
Pass3IdentifyAliveRanges pass3IdentifyAliveRanges = new Pass3IdentifyAliveRanges(program, log);
pass3IdentifyAliveRanges.findLiveRanges();
log.append("CONTROL FLOW GRAPH - LIVE RANGES");
log.append(program.getGraph().toString(program.getScope()));
pass2AssertSSA(program, log);
Pass3PhiMemCoalesce pass3PhiMemCoalesce = new Pass3PhiMemCoalesce(program, log);
pass3PhiMemCoalesce.optimize();
Pass2CullEmptyBlocks cullEmptyBlocks = new Pass2CullEmptyBlocks(program, log);
cullEmptyBlocks.optimize();
pass3BlockSequencePlanner.plan();
pass3IdentifyAliveRanges.findLiveRanges();
log.append("CONTROL FLOW GRAPH - PHI MEM COALESCED");
log.append(program.getGraph().toString(program.getScope()));
pass2AssertSSA(program, log);
}
public void pass2OptimizeSSA(Program program, CompileLog log) {

View File

@ -109,6 +109,37 @@ public class LiveRange {
return true;
}
/**
* Determines if this live range overlaps another live range
* @param other The other live range
* @return true if there is an overlap
*/
public boolean overlaps(LiveRange other) {
if(this.getMaxIndex()==-1 || other.getMaxIndex()==-1) {
return false;
}
int maxIdx = getMaxIndex();
for(int i=0;i<=maxIdx; i++) {
if(contains(i) && other.contains(i)) {
return true;
}
}
return false;
}
/**
* Adds another live range to this one - extending this live range to include the other one.
* @param other The live range to add
*/
public void add(LiveRange other) {
int otherMaxIndex = other.getMaxIndex();
for(int i=0;i<=otherMaxIndex; i++) {
if(other.contains(i)) {
add(i);
}
}
}
/**
* Determines if the live range contains a statement
* @param statement The statement to examine
@ -136,5 +167,16 @@ public class LiveRange {
return false;
}
/**
* Get the maximal index contained in the live range
* @return The max index. -1 if the range is empty.
*/
int getMaxIndex() {
if(intervals.isEmpty()) {
return -1;
}
return intervals.get(intervals.size()-1).lastStatementIdx;
}
}

View File

@ -44,4 +44,13 @@ public class VariableLiveRanges {
return aliveVars;
}
/**
* Get the alive range of a variable
* @param variable The variable reference
* @return The alive range for the variable
*/
public LiveRange getLiveRange(VariableRef variable) {
return liveRanges.get(variable);
}
}

View File

@ -0,0 +1,239 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.icl.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Eliminate virtual variables introduced by PhiLifting if they do not have overlapping live ranges with other phi equivalent variables.
* (This pass requires variable alive ranges).
* <p>
* See http://compilers.cs.ucla.edu/fernando/projects/soc/reports/short_tech.pdf
*/
public class Pass3PhiMemCoalesce extends Pass2SsaOptimization {
public Pass3PhiMemCoalesce(Program program, CompileLog log) {
super(program, log);
}
@Override
public boolean optimize() {
PhiEquivalenceClassInitializer phiEquivalenceClassInitializer = new PhiEquivalenceClassInitializer();
phiEquivalenceClassInitializer.visitGraph(getGraph());
ProgramPhiEquivalenceClasses phiEquivalenceClasses = phiEquivalenceClassInitializer.getPhiEquivalenceClasses();
log.append("Created " +phiEquivalenceClasses.size()+ " initial phi equivalence classes");
PhiMemCoalescer phiMemCoalescer = new PhiMemCoalescer(phiEquivalenceClasses);
phiMemCoalescer.visitGraph(getGraph());
removeAssignments(phiMemCoalescer.getRemove());
replaceVariables(phiMemCoalescer.getReplace());
deleteVariables(phiMemCoalescer.getRemove());
log.append("Coalesced down to " +phiEquivalenceClasses.size()+ " phi equivalence classes");
return false;
}
/** Coalesces phi equivalence classes when they do not overlap based on assignments to variables in phi statements. */
private class PhiMemCoalescer extends ControlFlowGraphBaseVisitor<Void> {
private ProgramPhiEquivalenceClasses phiEquivalenceClasses;
private List<VariableRef> remove;
private Map<VariableRef, VariableRef> replace;
public PhiMemCoalescer(ProgramPhiEquivalenceClasses phiEquivalenceClasses) {
this.phiEquivalenceClasses = phiEquivalenceClasses;
this.remove = new ArrayList<>();
this.replace = new HashMap<>();
}
public List<VariableRef> getRemove() {
return remove;
}
public Map<VariableRef, VariableRef> getReplace() {
return replace;
}
@Override
public Void visitAssignment(StatementAssignment assignment) {
if (assignment.getlValue() instanceof VariableRef) {
PhiEquivalenceClass lValEquivalenceClass =
phiEquivalenceClasses.getPhiEquivalenceClass((VariableRef) assignment.getlValue());
if (lValEquivalenceClass != null && assignment.getOperator() == null && assignment.getrValue1() == null && assignment.getrValue2() instanceof VariableRef) {
// Found copy assignment to a variable in an equivalence class - attempt to coalesce
VariableRef assignVar = (VariableRef) assignment.getrValue2();
PhiEquivalenceClass assignVarEquivalenceClass = phiEquivalenceClasses.getOrCreateEquivalenceClass(assignVar);
if(lValEquivalenceClass.equals(assignVarEquivalenceClass)) {
remove.add((VariableRef) assignment.getlValue());
replace.put((VariableRef) assignment.getlValue(), assignVar);
log.append("Coalesced (already) "+assignment);
} else if (!lValEquivalenceClass.getLiveRange().overlaps(assignVarEquivalenceClass.getLiveRange())) {
lValEquivalenceClass.addAll(assignVarEquivalenceClass);
phiEquivalenceClasses.remove(assignVarEquivalenceClass);
remove.add((VariableRef) assignment.getlValue());
replace.put((VariableRef) assignment.getlValue(), assignVar);
log.append("Coalesced "+assignment);
} else {
log.append("Not coalescing "+assignment);
}
}
}
return null;
}
}
/** Creates initial phi equivalence classes from program phi statements.*/
private class PhiEquivalenceClassInitializer extends ControlFlowGraphBaseVisitor<Void> {
private ProgramPhiEquivalenceClasses phiEquivalenceClasses;
public PhiEquivalenceClassInitializer() {
this.phiEquivalenceClasses = new ProgramPhiEquivalenceClasses();
}
@Override
public Void visitPhiBlock(StatementPhiBlock phi) {
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
VariableRef variable = phiVariable.getVariable();
PhiEquivalenceClass equivalenceClass = phiEquivalenceClasses.getOrCreateEquivalenceClass(variable);
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
if(!(phiRValue.getrValue() instanceof Constant)) {
VariableRef phiRVar = (VariableRef) phiRValue.getrValue();
equivalenceClass.addVariable(phiRVar);
}
}
}
return null;
}
public ProgramPhiEquivalenceClasses getPhiEquivalenceClasses() {
return phiEquivalenceClasses;
}
}
/** The entire set of phi equivalence classes in the pgogram. */
public class ProgramPhiEquivalenceClasses {
List<PhiEquivalenceClass> equivalenceClasses;
public ProgramPhiEquivalenceClasses() {
this.equivalenceClasses = new ArrayList<>();
}
/**
* Get the phi equivalence class for a specific variable.
* If the equivalence class does not exist it is created.
*
* @param variable The variable
* @return The existing or new phi equivalence class
*/
public PhiEquivalenceClass getOrCreateEquivalenceClass(VariableRef variable) {
PhiEquivalenceClass equivalenceClass1 = getPhiEquivalenceClass(variable);
if (equivalenceClass1 != null) return equivalenceClass1;
// Not found - create it
PhiEquivalenceClass equivalenceClass = new PhiEquivalenceClass();
equivalenceClasses.add(equivalenceClass);
equivalenceClass.addVariable(variable);
return equivalenceClass;
}
/**
* Get the phi equivalence class for a specific variable.
*
* @param variable The variable
* @return The existing phi equivalence class. null if no equivalence class contains the variable.
*/
private PhiEquivalenceClass getPhiEquivalenceClass(VariableRef variable) {
for (PhiEquivalenceClass equivalenceClass : equivalenceClasses) {
if(equivalenceClass.contains(variable)) {
return equivalenceClass;
}
}
return null;
}
public int size() {
return equivalenceClasses.size();
}
public void remove(PhiEquivalenceClass equivalenceClass) {
equivalenceClasses.remove(equivalenceClass);
}
}
/**
* A phi equivalence class contains all varialbes connected in by phi statements.
* In the phi statement <code>va = phi(vb, vc)</code> all 3 variables are in the same equivalence class.
* The equivalence class is the closure over all phi statements in the program.
* The set of equivalence classes is a disjoint partition of all variables uses in phi statements
* (ie. those variables crossing non-trivial block transitions).
* <p>
* See http://compilers.cs.ucla.edu/fernando/projects/soc/reports/short_tech.pdf
**/
public class PhiEquivalenceClass {
/** The variables of the equivalence class. */
List<VariableRef> variables;
/** The combined live range of the variables. */
LiveRange classLiveRange;
public PhiEquivalenceClass() {
this.variables = new ArrayList<>();
this.classLiveRange = new LiveRange();
}
/**
* Add a variable to the equivalence class
* @param variable The variable to add
*/
public void addVariable(VariableRef variable) {
VariableLiveRanges liveRanges = getSymbols().getLiveRanges();
LiveRange varLiveRange = liveRanges.getLiveRange(variable);
if(classLiveRange.overlaps(varLiveRange)) {
throw new RuntimeException("Compilation error! Variable live range overlaps phi equivalence class live range. "+variable);
}
classLiveRange.add(varLiveRange);
variables.add(variable);
}
/**
* Determines if the phi equivalence class contains a variable
* @param variable The variable to look for
* @return true if the equivalence class contains the variable
*/
public boolean contains(VariableRef variable) {
return variables.contains(variable);
}
public LiveRange getLiveRange() {
return classLiveRange;
}
public void addAll(PhiEquivalenceClass other) {
variables.addAll(other.variables);
classLiveRange.add(other.classLiveRange);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PhiEquivalenceClass that = (PhiEquivalenceClass) o;
return variables.equals(that.variables);
}
@Override
public int hashCode() {
return variables.hashCode();
}
}
}

View File

@ -844,6 +844,52 @@ Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1
Multiple usages for variable. Not optimizing sub-constant (byte) y#2
Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1
Block Sequence Planned @BEGIN @1 @3 @END @2
Added new block during phi lifting @7(between @3 and @1)
Added new block during phi lifting @8(between @1 and @3)
Block Sequence Planned @BEGIN @1 @8 @3 @END @7 @2
CONTROL FLOW GRAPH - PHI LIFTED
@BEGIN: from
to:@1
@1: from @7 @BEGIN
(byte) y#2 ← phi( @7/(byte~) y#5 @BEGIN/(byte) 0 )
(byte) e#3 ← phi( @7/(byte~) e#6 @BEGIN/(byte) 12 )
(byte) x#2 ← phi( @7/(byte~) x#5 @BEGIN/(byte) 0 )
(byte*) cursor#3 ← phi( @7/(byte*~) cursor#6 @BEGIN/(word) 1024 )
*((byte*) cursor#3) ← (byte) 81
(byte) x#1 ← (byte) x#2 + (byte) 1
(byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1
(byte) e#1 ← (byte) e#3 + (byte) 24
if((byte) 39<(byte) e#1) goto @2
to:@8
@8: from @1
(byte*~) cursor#7 ← (byte*) cursor#1
(byte~) e#7 ← (byte) e#1
(byte~) y#6 ← (byte) y#2
to:@3
@3: from @2 @8
(byte) y#4 ← phi( @8/(byte~) y#6 @2/(byte~) y#7 )
(byte) e#5 ← phi( @8/(byte~) e#7 @2/(byte~) e#8 )
(byte*) cursor#5 ← phi( @8/(byte*~) cursor#7 @2/(byte*~) cursor#8 )
if((byte) x#1<(byte) 40) goto @7
to:@END
@END: from @3
@7: from @3
(byte*~) cursor#6 ← (byte*) cursor#5
(byte~) x#5 ← (byte) x#1
(byte~) e#6 ← (byte) e#5
(byte~) y#5 ← (byte) y#4
to:@1
@2: from @1
(byte) y#1 ← (byte) y#2 + (byte) 1
(byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40
(byte) e#2 ← (byte) e#1 - (byte) 39
(byte*~) cursor#8 ← (byte*) cursor#2
(byte~) e#8 ← (byte) e#2
(byte~) y#7 ← (byte) y#1
to:@3
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
@ -851,6 +897,68 @@ Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
CONTROL FLOW GRAPH - LIVE RANGES
@BEGIN: from
to:@1
@1: from @7 @BEGIN
[0] (byte) y#2 ← phi( @7/(byte~) y#5 @BEGIN/(byte) 0 ) [ cursor#3 x#2 e#3 y#2 ]
[0] (byte) e#3 ← phi( @7/(byte~) e#6 @BEGIN/(byte) 12 ) [ cursor#3 x#2 e#3 y#2 ]
[0] (byte) x#2 ← phi( @7/(byte~) x#5 @BEGIN/(byte) 0 ) [ cursor#3 x#2 e#3 y#2 ]
[0] (byte*) cursor#3 ← phi( @7/(byte*~) cursor#6 @BEGIN/(word) 1024 ) [ cursor#3 x#2 e#3 y#2 ]
[1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ]
[2] (byte) x#1 ← (byte) x#2 + (byte) 1 [ cursor#3 e#3 y#2 x#1 ]
[3] (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 [ e#3 cursor#1 y#2 x#1 ]
[4] (byte) e#1 ← (byte) e#3 + (byte) 24 [ e#1 cursor#1 y#2 x#1 ]
[5] if((byte) 39<(byte) e#1) goto @2 [ e#1 cursor#1 y#2 x#1 ]
to:@8
@8: from @1
[6] (byte*~) cursor#7 ← (byte*) cursor#1 [ e#1 y#2 cursor#7 x#1 ]
[7] (byte~) e#7 ← (byte) e#1 [ y#2 cursor#7 e#7 x#1 ]
[8] (byte~) y#6 ← (byte) y#2 [ cursor#7 e#7 y#6 x#1 ]
to:@3
@3: from @2 @8
[9] (byte) y#4 ← phi( @8/(byte~) y#6 @2/(byte~) y#7 ) [ x#1 cursor#5 e#5 y#4 ]
[9] (byte) e#5 ← phi( @8/(byte~) e#7 @2/(byte~) e#8 ) [ x#1 cursor#5 e#5 y#4 ]
[9] (byte*) cursor#5 ← phi( @8/(byte*~) cursor#7 @2/(byte*~) cursor#8 ) [ x#1 cursor#5 e#5 y#4 ]
[10] if((byte) x#1<(byte) 40) goto @7 [ x#1 cursor#5 e#5 y#4 ]
to:@END
@END: from @3
@7: from @3
[11] (byte*~) cursor#6 ← (byte*) cursor#5 [ cursor#6 x#1 e#5 y#4 ]
[12] (byte~) x#5 ← (byte) x#1 [ cursor#6 x#5 e#5 y#4 ]
[13] (byte~) e#6 ← (byte) e#5 [ cursor#6 x#5 e#6 y#4 ]
[14] (byte~) y#5 ← (byte) y#4 [ cursor#6 x#5 e#6 y#5 ]
to:@1
@2: from @1
[15] (byte) y#1 ← (byte) y#2 + (byte) 1 [ e#1 cursor#1 x#1 y#1 ]
[16] (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 [ e#1 x#1 cursor#2 y#1 ]
[17] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ]
[18] (byte*~) cursor#8 ← (byte*) cursor#2 [ cursor#8 x#1 e#2 y#1 ]
[19] (byte~) e#8 ← (byte) e#2 [ cursor#8 e#8 x#1 y#1 ]
[20] (byte~) y#7 ← (byte) y#1 [ cursor#8 e#8 y#7 x#1 ]
to:@3
Created 7 initial phi equivalence classes
Coalesced [6] cursor#7 ← cursor#1
Coalesced [7] e#7 ← e#1
Coalesced [8] y#6 ← y#2
Coalesced [11] cursor#6 ← cursor#5
Coalesced [12] x#5 ← x#1
Coalesced [13] e#6 ← e#5
Coalesced (already) [14] y#5 ← y#4
Coalesced [18] cursor#8 ← cursor#2
Coalesced [19] e#8 ← e#2
Coalesced [20] y#7 ← y#1
Coalesced down to 4 phi equivalence classes
Culled Empty Block (label) @8
Culled Empty Block (label) @7
Block Sequence Planned @BEGIN @1 @3 @END @2
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
CONTROL FLOW GRAPH - PHI MEM COALESCED
@BEGIN: from
to:@1
@1: from @3 @BEGIN

View File

@ -3310,6 +3310,149 @@ Multiple usages for variable. Not optimizing sub-constant (byte) flip::i#2
Multiple usages for variable. Not optimizing sub-constant (byte) flip::i#2
Multiple usages for variable. Not optimizing sub-constant (byte) plot::i#2
Block Sequence Planned @BEGIN @END main main::@3 main::@4 main::@6 main::@7 main::@10 main::@11 main::@return plot plot::@1 plot::@2 plot::@3 plot::@return flip flip::@1 flip::@2 flip::@4 flip::@3 flip::@return prepare prepare::@1 prepare::@return
Added new block during phi lifting main::@12(between main::@6 and main::@3)
Added new block during phi lifting plot::@5(between plot::@3 and plot::@1)
Added new block during phi lifting plot::@6(between plot::@2 and plot::@2)
Added new block during phi lifting flip::@7(between flip::@4 and flip::@1)
Added new block during phi lifting flip::@8(between flip::@2 and flip::@2)
Added new block during phi lifting flip::@9(between flip::@3 and flip::@3)
Added new block during phi lifting prepare::@3(between prepare::@1 and prepare::@1)
Block Sequence Planned @BEGIN @END main main::@3 main::@4 main::@6 main::@7 main::@10 main::@11 main::@return main::@12 plot plot::@1 plot::@2 plot::@3 plot::@return plot::@5 plot::@6 flip flip::@1 flip::@2 flip::@4 flip::@3 flip::@return flip::@9 flip::@7 flip::@8 prepare prepare::@1 prepare::@return prepare::@3
CONTROL FLOW GRAPH - PHI LIFTED
@BEGIN: from
call main param-assignment
to:@END
@END: from @BEGIN
main: from @BEGIN
call prepare param-assignment
to:main::@3
main::@3: from main main::@11 main::@12 main::@3
(byte) main::c#2 ← phi( main/(byte) 25 main::@12/(byte~) main::c#6 main::@11/(byte) 25 )
(byte~) main::$1 ← * (word) 53266
if((byte~) main::$1!=(byte) 254) goto main::@3
to:main::@4
main::@4: from main::@3 main::@4
(byte~) main::$3 ← * (word) 53266
if((byte~) main::$3!=(byte) 255) goto main::@4
to:main::@6
main::@6: from main::@4
(byte) main::c#1 ← -- (byte) main::c#2
if((byte) main::c#1!=(byte) 0) goto main::@12
to:main::@7
main::@7: from main::@6
call flip param-assignment
to:main::@10
main::@10: from main::@7
call plot param-assignment
to:main::@11
main::@11: from main::@10
if(true) goto main::@3
to:main::@return
main::@return: from main::@11
return
to:@RETURN
main::@12: from main::@6
(byte~) main::c#6 ← (byte) main::c#1
to:main::@3
plot: from main::@10
to:plot::@1
plot::@1: from plot plot::@5
(byte) plot::y#2 ← phi( plot/(byte) 16 plot::@5/(byte~) plot::y#5 )
(byte*) plot::line#2 ← phi( plot/(word) 1236 plot::@5/(byte*~) plot::line#5 )
(byte) plot::i#3 ← phi( plot/(byte) 0 plot::@5/(byte~) plot::i#5 )
(byte~) plot::i#6 ← (byte) plot::i#3
to:plot::@2
plot::@2: from plot::@1 plot::@6
(byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@6/(byte~) plot::x#3 )
(byte) plot::i#2 ← phi( plot::@1/(byte~) plot::i#6 plot::@6/(byte~) plot::i#7 )
(byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2
*((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3
(byte) plot::i#1 ← ++ (byte) plot::i#2
(byte) plot::x#1 ← ++ (byte) plot::x#2
if((byte) plot::x#1<(byte) 16) goto plot::@6
to:plot::@3
plot::@3: from plot::@2
(byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40
(byte) plot::y#1 ← -- (byte) plot::y#2
if((byte) plot::y#1!=(byte) 0) goto plot::@5
to:plot::@return
plot::@return: from plot::@3
return
to:@RETURN
plot::@5: from plot::@3
(byte~) plot::i#5 ← (byte) plot::i#1
(byte*~) plot::line#5 ← (byte*) plot::line#1
(byte~) plot::y#5 ← (byte) plot::y#1
to:plot::@1
plot::@6: from plot::@2
(byte~) plot::i#7 ← (byte) plot::i#1
(byte~) plot::x#3 ← (byte) plot::x#1
to:plot::@2
flip: from main::@7
to:flip::@1
flip::@1: from flip flip::@7
(byte) flip::r#2 ← phi( flip/(byte) 16 flip::@7/(byte~) flip::r#5 )
(byte) flip::dstIdx#5 ← phi( flip/(byte) 15 flip::@7/(byte~) flip::dstIdx#6 )
(byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@7/(byte~) flip::srcIdx#5 )
(byte~) flip::srcIdx#6 ← (byte) flip::srcIdx#3
(byte~) flip::dstIdx#7 ← (byte) flip::dstIdx#5
to:flip::@2
flip::@2: from flip::@1 flip::@8
(byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@8/(byte~) flip::c#3 )
(byte) flip::dstIdx#3 ← phi( flip::@1/(byte~) flip::dstIdx#7 flip::@8/(byte~) flip::dstIdx#8 )
(byte) flip::srcIdx#2 ← phi( flip::@1/(byte~) flip::srcIdx#6 flip::@8/(byte~) flip::srcIdx#7 )
(byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2
*((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0
(byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2
(byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16
(byte) flip::c#1 ← -- (byte) flip::c#2
if((byte) flip::c#1!=(byte) 0) goto flip::@8
to:flip::@4
flip::@4: from flip::@2
(byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1
(byte) flip::r#1 ← -- (byte) flip::r#2
if((byte) flip::r#1!=(byte) 0) goto flip::@7
to:flip::@3
flip::@3: from flip::@4 flip::@9
(byte) flip::i#2 ← phi( flip::@9/(byte~) flip::i#3 flip::@4/(byte) 0 )
(byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2
*((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4
(byte) flip::i#1 ← ++ (byte) flip::i#2
if((byte) flip::i#1!=(byte) 0) goto flip::@9
to:flip::@return
flip::@return: from flip::@3
return
to:@RETURN
flip::@9: from flip::@3
(byte~) flip::i#3 ← (byte) flip::i#1
to:flip::@3
flip::@7: from flip::@4
(byte~) flip::srcIdx#5 ← (byte) flip::srcIdx#1
(byte~) flip::dstIdx#6 ← (byte) flip::dstIdx#2
(byte~) flip::r#5 ← (byte) flip::r#1
to:flip::@1
flip::@8: from flip::@2
(byte~) flip::srcIdx#7 ← (byte) flip::srcIdx#1
(byte~) flip::dstIdx#8 ← (byte) flip::dstIdx#1
(byte~) flip::c#3 ← (byte) flip::c#1
to:flip::@2
prepare: from main
to:prepare::@1
prepare::@1: from prepare prepare::@3
(byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@3/(byte~) prepare::i#3 )
*((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2
(byte) prepare::i#1 ← ++ (byte) prepare::i#2
if((byte) prepare::i#1!=(byte) 0) goto prepare::@3
to:prepare::@return
prepare::@return: from prepare::@1
return
to:@RETURN
prepare::@3: from prepare::@1
(byte~) prepare::i#3 ← (byte) prepare::i#1
to:prepare::@1
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
@ -3324,6 +3467,175 @@ CONTROL FLOW GRAPH - LIVE RANGES
[0] call main param-assignment [ ]
to:@END
@END: from @BEGIN
main: from @BEGIN
[1] call prepare param-assignment [ ]
to:main::@3
main::@3: from main main::@11 main::@12 main::@3
[2] (byte) main::c#2 ← phi( main/(byte) 25 main::@12/(byte~) main::c#6 main::@11/(byte) 25 ) [ main::c#2 ]
[3] (byte~) main::$1 ← * (word) 53266 [ main::$1 main::c#2 ]
[4] if((byte~) main::$1!=(byte) 254) goto main::@3 [ main::c#2 ]
to:main::@4
main::@4: from main::@3 main::@4
[5] (byte~) main::$3 ← * (word) 53266 [ main::$3 main::c#2 ]
[6] if((byte~) main::$3!=(byte) 255) goto main::@4 [ main::c#2 ]
to:main::@6
main::@6: from main::@4
[7] (byte) main::c#1 ← -- (byte) main::c#2 [ main::c#1 ]
[8] if((byte) main::c#1!=(byte) 0) goto main::@12 [ main::c#1 ]
to:main::@7
main::@7: from main::@6
[9] call flip param-assignment [ ]
to:main::@10
main::@10: from main::@7
[10] call plot param-assignment [ ]
to:main::@11
main::@11: from main::@10
[11] if(true) goto main::@3 [ ]
to:main::@return
main::@return: from main::@11
[12] return [ ]
to:@RETURN
main::@12: from main::@6
[13] (byte~) main::c#6 ← (byte) main::c#1 [ main::c#6 ]
to:main::@3
plot: from main::@10
to:plot::@1
plot::@1: from plot plot::@5
[14] (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@5/(byte~) plot::y#5 ) [ plot::i#3 plot::line#2 plot::y#2 ]
[14] (byte*) plot::line#2 ← phi( plot/(word) 1236 plot::@5/(byte*~) plot::line#5 ) [ plot::i#3 plot::line#2 plot::y#2 ]
[14] (byte) plot::i#3 ← phi( plot/(byte) 0 plot::@5/(byte~) plot::i#5 ) [ plot::i#3 plot::line#2 plot::y#2 ]
[15] (byte~) plot::i#6 ← (byte) plot::i#3 [ plot::i#6 plot::line#2 plot::y#2 ]
to:plot::@2
plot::@2: from plot::@1 plot::@6
[16] (byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@6/(byte~) plot::x#3 ) [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ]
[16] (byte) plot::i#2 ← phi( plot::@1/(byte~) plot::i#6 plot::@6/(byte~) plot::i#7 ) [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ]
[17] (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 [ plot::i#2 plot::line#2 plot::x#2 plot::$3 plot::y#2 ]
[18] *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ]
[19] (byte) plot::i#1 ← ++ (byte) plot::i#2 [ plot::line#2 plot::x#2 plot::y#2 plot::i#1 ]
[20] (byte) plot::x#1 ← ++ (byte) plot::x#2 [ plot::line#2 plot::x#1 plot::y#2 plot::i#1 ]
[21] if((byte) plot::x#1<(byte) 16) goto plot::@6 [ plot::line#2 plot::x#1 plot::y#2 plot::i#1 ]
to:plot::@3
plot::@3: from plot::@2
[22] (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 [ plot::y#2 plot::i#1 plot::line#1 ]
[23] (byte) plot::y#1 ← -- (byte) plot::y#2 [ plot::y#1 plot::i#1 plot::line#1 ]
[24] if((byte) plot::y#1!=(byte) 0) goto plot::@5 [ plot::y#1 plot::i#1 plot::line#1 ]
to:plot::@return
plot::@return: from plot::@3
[25] return [ ]
to:@RETURN
plot::@5: from plot::@3
[26] (byte~) plot::i#5 ← (byte) plot::i#1 [ plot::i#5 plot::y#1 plot::line#1 ]
[27] (byte*~) plot::line#5 ← (byte*) plot::line#1 [ plot::i#5 plot::line#5 plot::y#1 ]
[28] (byte~) plot::y#5 ← (byte) plot::y#1 [ plot::i#5 plot::line#5 plot::y#5 ]
to:plot::@1
plot::@6: from plot::@2
[29] (byte~) plot::i#7 ← (byte) plot::i#1 [ plot::i#7 plot::line#2 plot::x#1 plot::y#2 ]
[30] (byte~) plot::x#3 ← (byte) plot::x#1 [ plot::i#7 plot::x#3 plot::line#2 plot::y#2 ]
to:plot::@2
flip: from main::@7
to:flip::@1
flip::@1: from flip flip::@7
[31] (byte) flip::r#2 ← phi( flip/(byte) 16 flip::@7/(byte~) flip::r#5 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ]
[31] (byte) flip::dstIdx#5 ← phi( flip/(byte) 15 flip::@7/(byte~) flip::dstIdx#6 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ]
[31] (byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@7/(byte~) flip::srcIdx#5 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ]
[32] (byte~) flip::srcIdx#6 ← (byte) flip::srcIdx#3 [ flip::dstIdx#5 flip::srcIdx#6 flip::r#2 ]
[33] (byte~) flip::dstIdx#7 ← (byte) flip::dstIdx#5 [ flip::srcIdx#6 flip::dstIdx#7 flip::r#2 ]
to:flip::@2
flip::@2: from flip::@1 flip::@8
[34] (byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@8/(byte~) flip::c#3 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ]
[34] (byte) flip::dstIdx#3 ← phi( flip::@1/(byte~) flip::dstIdx#7 flip::@8/(byte~) flip::dstIdx#8 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ]
[34] (byte) flip::srcIdx#2 ← phi( flip::@1/(byte~) flip::srcIdx#6 flip::@8/(byte~) flip::srcIdx#7 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ]
[35] (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 [ flip::srcIdx#2 flip::dstIdx#3 flip::$0 flip::c#2 flip::r#2 ]
[36] *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ]
[37] (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 [ flip::dstIdx#3 flip::c#2 flip::r#2 flip::srcIdx#1 ]
[38] (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 [ flip::c#2 flip::dstIdx#1 flip::r#2 flip::srcIdx#1 ]
[39] (byte) flip::c#1 ← -- (byte) flip::c#2 [ flip::c#1 flip::dstIdx#1 flip::r#2 flip::srcIdx#1 ]
[40] if((byte) flip::c#1!=(byte) 0) goto flip::@8 [ flip::c#1 flip::dstIdx#1 flip::r#2 flip::srcIdx#1 ]
to:flip::@4
flip::@4: from flip::@2
[41] (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 [ flip::r#2 flip::srcIdx#1 flip::dstIdx#2 ]
[42] (byte) flip::r#1 ← -- (byte) flip::r#2 [ flip::r#1 flip::srcIdx#1 flip::dstIdx#2 ]
[43] if((byte) flip::r#1!=(byte) 0) goto flip::@7 [ flip::r#1 flip::srcIdx#1 flip::dstIdx#2 ]
to:flip::@3
flip::@3: from flip::@4 flip::@9
[44] (byte) flip::i#2 ← phi( flip::@9/(byte~) flip::i#3 flip::@4/(byte) 0 ) [ flip::i#2 ]
[45] (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 [ flip::i#2 flip::$4 ]
[46] *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 [ flip::i#2 ]
[47] (byte) flip::i#1 ← ++ (byte) flip::i#2 [ flip::i#1 ]
[48] if((byte) flip::i#1!=(byte) 0) goto flip::@9 [ flip::i#1 ]
to:flip::@return
flip::@return: from flip::@3
[49] return [ ]
to:@RETURN
flip::@9: from flip::@3
[50] (byte~) flip::i#3 ← (byte) flip::i#1 [ flip::i#3 ]
to:flip::@3
flip::@7: from flip::@4
[51] (byte~) flip::srcIdx#5 ← (byte) flip::srcIdx#1 [ flip::srcIdx#5 flip::r#1 flip::dstIdx#2 ]
[52] (byte~) flip::dstIdx#6 ← (byte) flip::dstIdx#2 [ flip::srcIdx#5 flip::dstIdx#6 flip::r#1 ]
[53] (byte~) flip::r#5 ← (byte) flip::r#1 [ flip::srcIdx#5 flip::dstIdx#6 flip::r#5 ]
to:flip::@1
flip::@8: from flip::@2
[54] (byte~) flip::srcIdx#7 ← (byte) flip::srcIdx#1 [ flip::srcIdx#7 flip::c#1 flip::dstIdx#1 flip::r#2 ]
[55] (byte~) flip::dstIdx#8 ← (byte) flip::dstIdx#1 [ flip::srcIdx#7 flip::dstIdx#8 flip::c#1 flip::r#2 ]
[56] (byte~) flip::c#3 ← (byte) flip::c#1 [ flip::srcIdx#7 flip::dstIdx#8 flip::c#3 flip::r#2 ]
to:flip::@2
prepare: from main
to:prepare::@1
prepare::@1: from prepare prepare::@3
[57] (byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@3/(byte~) prepare::i#3 ) [ prepare::i#2 ]
[58] *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 [ prepare::i#2 ]
[59] (byte) prepare::i#1 ← ++ (byte) prepare::i#2 [ prepare::i#1 ]
[60] if((byte) prepare::i#1!=(byte) 0) goto prepare::@3 [ prepare::i#1 ]
to:prepare::@return
prepare::@return: from prepare::@1
[61] return [ ]
to:@RETURN
prepare::@3: from prepare::@1
[62] (byte~) prepare::i#3 ← (byte) prepare::i#1 [ prepare::i#3 ]
to:prepare::@1
Created 14 initial phi equivalence classes
Coalesced [13] main::c#6 ← main::c#1
Coalesced [15] plot::i#6 ← plot::i#3
Coalesced [26] plot::i#5 ← plot::i#1
Coalesced [27] plot::line#5 ← plot::line#1
Coalesced [28] plot::y#5 ← plot::y#1
Coalesced (already) [29] plot::i#7 ← plot::i#1
Coalesced [30] plot::x#3 ← plot::x#1
Coalesced [32] flip::srcIdx#6 ← flip::srcIdx#3
Coalesced [33] flip::dstIdx#7 ← flip::dstIdx#5
Coalesced [50] flip::i#3 ← flip::i#1
Coalesced [51] flip::srcIdx#5 ← flip::srcIdx#1
Coalesced [52] flip::dstIdx#6 ← flip::dstIdx#2
Coalesced [53] flip::r#5 ← flip::r#1
Coalesced (already) [54] flip::srcIdx#7 ← flip::srcIdx#1
Coalesced [55] flip::dstIdx#8 ← flip::dstIdx#1
Coalesced [56] flip::c#3 ← flip::c#1
Coalesced [62] prepare::i#3 ← prepare::i#1
Coalesced down to 11 phi equivalence classes
Culled Empty Block (label) main::@12
Culled Empty Block (label) plot::@5
Culled Empty Block (label) plot::@6
Culled Empty Block (label) flip::@9
Culled Empty Block (label) flip::@7
Culled Empty Block (label) flip::@8
Culled Empty Block (label) prepare::@3
Block Sequence Planned @BEGIN @END main main::@3 main::@4 main::@6 main::@7 main::@10 main::@11 main::@return plot plot::@1 plot::@2 plot::@3 plot::@return flip flip::@1 flip::@2 flip::@4 flip::@3 flip::@return prepare prepare::@1 prepare::@return
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
CONTROL FLOW GRAPH - PHI MEM COALESCED
@BEGIN: from
[0] call main param-assignment [ ]
to:@END
@END: from @BEGIN
main: from @BEGIN
[1] call prepare param-assignment [ ]
to:main::@3

View File

@ -252,10 +252,78 @@ CONTROL FLOW GRAPH
@END: from @3
Block Sequence Planned @BEGIN @1 @3 @END @2
Added new block during phi lifting @7(between @3 and @1)
Added new block during phi lifting @8(between @1 and @3)
Block Sequence Planned @BEGIN @1 @8 @3 @END @7 @2
CONTROL FLOW GRAPH - PHI LIFTED
@BEGIN: from
to:@1
@1: from @7 @BEGIN
(byte) s#2 ← phi( @7/(byte~) s#5 @BEGIN/(byte) 0 )
(byte) i#2 ← phi( @7/(byte~) i#5 @BEGIN/(byte) 10 )
if((byte) i#2>(byte) 5) goto @2
to:@8
@8: from @1
(byte~) s#6 ← (byte) s#2
to:@3
@3: from @2 @8
(byte) s#4 ← phi( @8/(byte~) s#6 @2/(byte~) s#7 )
(byte) i#1 ← -- (byte) i#2
if((byte) i#1>(byte) 0) goto @7
to:@END
@END: from @3
@7: from @3
(byte~) i#5 ← (byte) i#1
(byte~) s#5 ← (byte) s#4
to:@1
@2: from @1
(byte) s#1 ← (byte) s#2 + (byte) i#2
(byte~) s#7 ← (byte) s#1
to:@3
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
CONTROL FLOW GRAPH - LIVE RANGES
@BEGIN: from
to:@1
@1: from @7 @BEGIN
[0] (byte) s#2 ← phi( @7/(byte~) s#5 @BEGIN/(byte) 0 ) [ i#2 s#2 ]
[0] (byte) i#2 ← phi( @7/(byte~) i#5 @BEGIN/(byte) 10 ) [ i#2 s#2 ]
[1] if((byte) i#2>(byte) 5) goto @2 [ i#2 s#2 ]
to:@8
@8: from @1
[2] (byte~) s#6 ← (byte) s#2 [ i#2 s#6 ]
to:@3
@3: from @2 @8
[3] (byte) s#4 ← phi( @8/(byte~) s#6 @2/(byte~) s#7 ) [ i#2 s#4 ]
[4] (byte) i#1 ← -- (byte) i#2 [ i#1 s#4 ]
[5] if((byte) i#1>(byte) 0) goto @7 [ i#1 s#4 ]
to:@END
@END: from @3
@7: from @3
[6] (byte~) i#5 ← (byte) i#1 [ i#5 s#4 ]
[7] (byte~) s#5 ← (byte) s#4 [ i#5 s#5 ]
to:@1
@2: from @1
[8] (byte) s#1 ← (byte) s#2 + (byte) i#2 [ i#2 s#1 ]
[9] (byte~) s#7 ← (byte) s#1 [ i#2 s#7 ]
to:@3
Created 3 initial phi equivalence classes
Coalesced [2] s#6 ← s#2
Coalesced [6] i#5 ← i#1
Coalesced (already) [7] s#5 ← s#4
Coalesced [9] s#7 ← s#1
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) @8
Culled Empty Block (label) @7
Block Sequence Planned @BEGIN @1 @3 @END @2
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
CONTROL FLOW GRAPH - PHI MEM COALESCED
@BEGIN: from
to:@1
@1: from @3 @BEGIN

View File

@ -207,9 +207,50 @@ Multiple usages for variable. Not optimizing sub-constant (byte) i#2
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
Block Sequence Planned @BEGIN @1 @END
Added new block during phi lifting @3(between @1 and @1)
Block Sequence Planned @BEGIN @1 @END @3
CONTROL FLOW GRAPH - PHI LIFTED
@BEGIN: from
to:@1
@1: from @3 @BEGIN
(byte) i#2 ← phi( @3/(byte~) i#3 @BEGIN/(byte) 5 )
(byte~) $0 ← (byte) 2 + (byte) i#2
(byte~) $1 ← (byte~) $0 + (byte) 2
*((word) 4352 + (byte) i#2) ← (byte~) $1
(byte) i#1 ← (byte) i#2 + (byte) 1
if((byte) i#1<(byte) 10) goto @3
to:@END
@END: from @1
@3: from @1
(byte~) i#3 ← (byte) i#1
to:@1
Propagating live ranges...
Propagating live ranges...
CONTROL FLOW GRAPH - LIVE RANGES
@BEGIN: from
to:@1
@1: from @3 @BEGIN
[0] (byte) i#2 ← phi( @3/(byte~) i#3 @BEGIN/(byte) 5 ) [ i#2 ]
[1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ]
[2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ]
[3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ]
[4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ]
[5] if((byte) i#1<(byte) 10) goto @3 [ i#1 ]
to:@END
@END: from @1
@3: from @1
[6] (byte~) i#3 ← (byte) i#1 [ i#3 ]
to:@1
Created 1 initial phi equivalence classes
Coalesced [6] i#3 ← i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @3
Block Sequence Planned @BEGIN @1 @END
Propagating live ranges...
Propagating live ranges...
CONTROL FLOW GRAPH - PHI MEM COALESCED
@BEGIN: from
to:@1
@1: from @1 @BEGIN

View File

@ -241,6 +241,24 @@ sum::@return: from sum
@END: from @2
Block Sequence Planned @BEGIN @2 @END sum sum::@return
Block Sequence Planned @BEGIN @2 @END sum sum::@return
CONTROL FLOW GRAPH - PHI LIFTED
@BEGIN: from
call sum param-assignment
to:@2
@2: from @BEGIN
call sum param-assignment
to:@END
@END: from @2
sum: from @2 @BEGIN
(byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 )
(byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 )
(byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2
to:sum::@return
sum::@return: from sum
return (byte) s1#0
to:@RETURN
Propagating live ranges...
CONTROL FLOW GRAPH - LIVE RANGES
@BEGIN: from
@ -259,6 +277,27 @@ sum::@return: from sum
[4] return (byte) s1#0 [ ]
to:@RETURN
Created 2 initial phi equivalence classes
Coalesced down to 2 phi equivalence classes
Block Sequence Planned @BEGIN @2 @END sum sum::@return
Propagating live ranges...
CONTROL FLOW GRAPH - PHI MEM COALESCED
@BEGIN: from
[0] call sum param-assignment [ ]
to:@2
@2: from @BEGIN
[1] call sum param-assignment [ ]
to:@END
@END: from @2
sum: from @2 @BEGIN
[2] (byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 ) [ sum::a#2 sum::b#2 ]
[2] (byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 ) [ sum::a#2 sum::b#2 ]
[3] (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 [ s1#0 ]
to:sum::@return
sum::@return: from sum
[4] return (byte) s1#0 [ ]
to:@RETURN
INITIAL ASM
BBEGIN:
sum_from_BBEGIN: