1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Working on better live ranges that take into account the call-path taken to the current statement and any aliases on that path (due to phi statements)

This commit is contained in:
jespergravgaard 2017-11-06 08:20:33 +01:00
parent 9d3c8afdf0
commit b20327590f
10 changed files with 292 additions and 180 deletions

View File

@ -262,9 +262,9 @@ public class Compiler {
//program.getLog().setVerboseUplift(true); //program.getLog().setVerboseUplift(true);
new Pass4RegisterUpliftCombinations(program).performUplift(10_000); new Pass4RegisterUpliftCombinations(program).performUplift(10_000);
//program.getLog().setVerboseUplift(true); program.getLog().setVerboseUplift(true);
//new Pass4RegisterUpliftStatic(program).performUplift(); new Pass4RegisterUpliftStatic(program).performUplift();
//program.getLog().setVerboseUplift(false); program.getLog().setVerboseUplift(false);
// Attempt uplifting registers one at a time to catch remaining potential not realized by combination search // Attempt uplifting registers one at a time to catch remaining potential not realized by combination search
new Pass4RegisterUpliftRemains(program).performUplift(10_000); new Pass4RegisterUpliftRemains(program).performUplift(10_000);

View File

@ -0,0 +1,6 @@
lda {zpptrby1}
asl
sta {zpptrby1}
lda {zpptrby1}+1
rol
sta {zpptrby1}+1

View File

@ -8,23 +8,76 @@ import java.util.*;
public class LiveRangeVariablesEffective { public class LiveRangeVariablesEffective {
/** Effectively alive variables by statement index. */ /** Effectively alive variables by statement index. */
Map<Integer, Collection<VariableRef>> effectiveLiveVariables; Map<Integer, AliveCombinations> effectiveLiveCombinations;
public LiveRangeVariablesEffective(Map<Integer, Collection<VariableRef>> effectiveLiveVariables) { public LiveRangeVariablesEffective(Map<Integer, AliveCombinations> effectiveLiveCombinations) {
this.effectiveLiveVariables = effectiveLiveVariables; this.effectiveLiveCombinations = effectiveLiveCombinations;
} }
/** /**
* Get all variables alive at a statement. * Get all variables potentially alive at a statement.
* If the statement is inside a method this also includes all variables alive at the exit of the calls. * If the statement is inside a method this also includes all variables alive at the exit of any call.
* <p>
* This method requires a number of other analysis to be present and updated in the (global) program - especailly the Call Graph.
* </p> * </p>
* @param statement The statement to examine * @param statement The statement to examine
* @return All variables alive at the statement * @return All variables potentially alive at the statement
*/ */
public Collection<VariableRef> getAliveEffective(Statement statement) { public Collection<VariableRef> getAliveEffective(Statement statement) {
return effectiveLiveVariables.get(statement.getIndex()); Set<VariableRef> effectiveAliveTotal = new LinkedHashSet<>();
AliveCombinations aliveCombinations = effectiveLiveCombinations.get(statement.getIndex());
for (AliveCombination aliveCombination : aliveCombinations.getCombinations()) {
effectiveAliveTotal.addAll(aliveCombination.getAlive());
}
return effectiveAliveTotal;
}
/**
* Get all combinations of variables alive at a statement.
* If the statement is inside a method the different combinations in the result arises from different calls of the method
* (recursively up til the main()-method.
* Each combination includes all variables alive at the exit of any surrounding call.
* </p>
* @param statement The statement to examine
* @return All combinations of variables alive at the statement
*/
public AliveCombinations getAliveCombinations(Statement statement) {
return effectiveLiveCombinations.get(statement.getIndex());
}
/** Combinations of variables effectively alive at a specific statement.
* If the statement is inside a method the combinations are the live variables inside the method combined with each calling statements alive vars.
* As each caller might also be inside a methos there may be a large amount of combinations.
*/
public static class AliveCombinations {
private Collection<AliveCombination> combinations;
public AliveCombinations(Collection<Collection<VariableRef>> aliveCombinations) {
ArrayList<AliveCombination> combinations = new ArrayList<>();
for (Collection<VariableRef> aliveCombination : aliveCombinations) {
combinations.add(new AliveCombination(aliveCombination));
}
this.combinations = combinations;
}
public Collection<AliveCombination> getCombinations() {
return combinations;
}
}
/** One single combinations of variables effectively alive at a specific statement. */
public static class AliveCombination {
private Collection<VariableRef> alive;
public AliveCombination(Collection<VariableRef> alive) {
this.alive = alive;
}
public Collection<VariableRef> getAlive() {
return alive;
}
} }

View File

@ -1,5 +1,6 @@
package dk.camelot64.kickc.model; package dk.camelot64.kickc.model;
import java.util.Collection;
import java.util.List; import java.util.List;
/** Statement base class implementing shared properties and logic */ /** Statement base class implementing shared properties and logic */
@ -48,7 +49,22 @@ public abstract class StatementBase implements Statement {
return ""; return "";
} }
LiveRangeVariables liveRanges = program.getLiveRangeVariables(); LiveRangeVariables liveRanges = program.getLiveRangeVariables();
List<VariableRef> alive = liveRanges.getAlive(this); StringBuilder alive = new StringBuilder();
alive.append(getAliveString(liveRanges.getAlive(this)));
LiveRangeVariablesEffective liveRangeVariablesEffective = program.getLiveRangeVariablesEffective();
if(liveRangeVariablesEffective!=null) {
LiveRangeVariablesEffective.AliveCombinations aliveCombinations = liveRangeVariablesEffective.getAliveCombinations(this);
alive.append(" ( ");
for (LiveRangeVariablesEffective.AliveCombination aliveCombination : aliveCombinations.getCombinations()) {
alive.append(getAliveString(aliveCombination.getAlive()));
alive.append(" ");
}
alive.append(")");
}
return alive.toString();
}
private String getAliveString(Collection<VariableRef> alive) {
StringBuilder str = new StringBuilder(); StringBuilder str = new StringBuilder();
str.append(" [ "); str.append(" [ ");
for (VariableRef variableRef : alive) { for (VariableRef variableRef : alive) {

View File

@ -90,7 +90,7 @@ parameterList
; ;
asmLines asmLines
: asmLine ( asmLine )* : asmLine*
; ;
asmLine asmLine

View File

@ -2315,19 +2315,17 @@ public class KickCParser extends Parser {
try { try {
enterOuterAlt(_localctx, 1); enterOuterAlt(_localctx, 1);
{ {
setState(288); setState(291);
asmLine();
setState(292);
_errHandler.sync(this); _errHandler.sync(this);
_la = _input.LA(1); _la = _input.LA(1);
while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__26) | (1L << MNEMONIC) | (1L << NAME))) != 0)) { while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__26) | (1L << MNEMONIC) | (1L << NAME))) != 0)) {
{ {
{ {
setState(289); setState(288);
asmLine(); asmLine();
} }
} }
setState(294); setState(293);
_errHandler.sync(this); _errHandler.sync(this);
_la = _input.LA(1); _la = _input.LA(1);
} }
@ -2374,21 +2372,21 @@ public class KickCParser extends Parser {
AsmLineContext _localctx = new AsmLineContext(_ctx, getState()); AsmLineContext _localctx = new AsmLineContext(_ctx, getState());
enterRule(_localctx, 28, RULE_asmLine); enterRule(_localctx, 28, RULE_asmLine);
try { try {
setState(297); setState(296);
_errHandler.sync(this); _errHandler.sync(this);
switch (_input.LA(1)) { switch (_input.LA(1)) {
case T__26: case T__26:
case NAME: case NAME:
enterOuterAlt(_localctx, 1); enterOuterAlt(_localctx, 1);
{ {
setState(295); setState(294);
asmLabel(); asmLabel();
} }
break; break;
case MNEMONIC: case MNEMONIC:
enterOuterAlt(_localctx, 2); enterOuterAlt(_localctx, 2);
{ {
setState(296); setState(295);
asmInstruction(); asmInstruction();
} }
break; break;
@ -2432,24 +2430,24 @@ public class KickCParser extends Parser {
AsmLabelContext _localctx = new AsmLabelContext(_ctx, getState()); AsmLabelContext _localctx = new AsmLabelContext(_ctx, getState());
enterRule(_localctx, 30, RULE_asmLabel); enterRule(_localctx, 30, RULE_asmLabel);
try { try {
setState(303); setState(302);
_errHandler.sync(this); _errHandler.sync(this);
switch (_input.LA(1)) { switch (_input.LA(1)) {
case NAME: case NAME:
enterOuterAlt(_localctx, 1); enterOuterAlt(_localctx, 1);
{ {
setState(299); setState(298);
match(NAME); match(NAME);
setState(300); setState(299);
match(T__14); match(T__14);
} }
break; break;
case T__26: case T__26:
enterOuterAlt(_localctx, 2); enterOuterAlt(_localctx, 2);
{ {
setState(301); setState(300);
match(T__26); match(T__26);
setState(302); setState(301);
match(T__14); match(T__14);
} }
break; break;
@ -2498,14 +2496,14 @@ public class KickCParser extends Parser {
try { try {
enterOuterAlt(_localctx, 1); enterOuterAlt(_localctx, 1);
{ {
setState(305); setState(304);
match(MNEMONIC); match(MNEMONIC);
setState(307); setState(306);
_errHandler.sync(this); _errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,30,_ctx) ) { switch ( getInterpreter().adaptivePredict(_input,30,_ctx) ) {
case 1: case 1:
{ {
setState(306); setState(305);
asmParamMode(); asmParamMode();
} }
break; break;
@ -2656,14 +2654,14 @@ public class KickCParser extends Parser {
AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState()); AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState());
enterRule(_localctx, 34, RULE_asmParamMode); enterRule(_localctx, 34, RULE_asmParamMode);
try { try {
setState(332); setState(331);
_errHandler.sync(this); _errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,31,_ctx) ) { switch ( getInterpreter().adaptivePredict(_input,31,_ctx) ) {
case 1: case 1:
_localctx = new AsmModeAbsContext(_localctx); _localctx = new AsmModeAbsContext(_localctx);
enterOuterAlt(_localctx, 1); enterOuterAlt(_localctx, 1);
{ {
setState(309); setState(308);
asmExpr(0); asmExpr(0);
} }
break; break;
@ -2671,9 +2669,9 @@ public class KickCParser extends Parser {
_localctx = new AsmModeImmContext(_localctx); _localctx = new AsmModeImmContext(_localctx);
enterOuterAlt(_localctx, 2); enterOuterAlt(_localctx, 2);
{ {
setState(310); setState(309);
match(T__44); match(T__44);
setState(311); setState(310);
asmExpr(0); asmExpr(0);
} }
break; break;
@ -2681,11 +2679,11 @@ public class KickCParser extends Parser {
_localctx = new AsmModeAbsXYContext(_localctx); _localctx = new AsmModeAbsXYContext(_localctx);
enterOuterAlt(_localctx, 3); enterOuterAlt(_localctx, 3);
{ {
setState(312); setState(311);
asmExpr(0); asmExpr(0);
setState(313); setState(312);
match(T__16); match(T__16);
setState(314); setState(313);
match(NAME); match(NAME);
} }
break; break;
@ -2693,15 +2691,15 @@ public class KickCParser extends Parser {
_localctx = new AsmModeIndIdxXYContext(_localctx); _localctx = new AsmModeIndIdxXYContext(_localctx);
enterOuterAlt(_localctx, 4); enterOuterAlt(_localctx, 4);
{ {
setState(316); setState(315);
match(T__2); match(T__2);
setState(317); setState(316);
asmExpr(0); asmExpr(0);
setState(318); setState(317);
match(T__3); match(T__3);
setState(319); setState(318);
match(T__16); match(T__16);
setState(320); setState(319);
match(NAME); match(NAME);
} }
break; break;
@ -2709,15 +2707,15 @@ public class KickCParser extends Parser {
_localctx = new AsmModeIdxIndXYContext(_localctx); _localctx = new AsmModeIdxIndXYContext(_localctx);
enterOuterAlt(_localctx, 5); enterOuterAlt(_localctx, 5);
{ {
setState(322); setState(321);
match(T__2); match(T__2);
setState(323); setState(322);
asmExpr(0); asmExpr(0);
setState(324); setState(323);
match(T__16); match(T__16);
setState(325); setState(324);
match(NAME); match(NAME);
setState(326); setState(325);
match(T__3); match(T__3);
} }
break; break;
@ -2725,11 +2723,11 @@ public class KickCParser extends Parser {
_localctx = new AsmModeIndContext(_localctx); _localctx = new AsmModeIndContext(_localctx);
enterOuterAlt(_localctx, 6); enterOuterAlt(_localctx, 6);
{ {
setState(328); setState(327);
match(T__2); match(T__2);
setState(329); setState(328);
asmExpr(0); asmExpr(0);
setState(330); setState(329);
match(T__3); match(T__3);
} }
break; break;
@ -2900,7 +2898,7 @@ public class KickCParser extends Parser {
int _alt; int _alt;
enterOuterAlt(_localctx, 1); enterOuterAlt(_localctx, 1);
{ {
setState(344); setState(343);
_errHandler.sync(this); _errHandler.sync(this);
switch (_input.LA(1)) { switch (_input.LA(1)) {
case T__20: case T__20:
@ -2912,7 +2910,7 @@ public class KickCParser extends Parser {
_ctx = _localctx; _ctx = _localctx;
_prevctx = _localctx; _prevctx = _localctx;
setState(335); setState(334);
_la = _input.LA(1); _la = _input.LA(1);
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__20) | (1L << T__21) | (1L << T__24) | (1L << T__25))) != 0)) ) { if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__20) | (1L << T__21) | (1L << T__24) | (1L << T__25))) != 0)) ) {
_errHandler.recoverInline(this); _errHandler.recoverInline(this);
@ -2922,7 +2920,7 @@ public class KickCParser extends Parser {
_errHandler.reportMatch(this); _errHandler.reportMatch(this);
consume(); consume();
} }
setState(336); setState(335);
asmExpr(8); asmExpr(8);
} }
break; break;
@ -2931,7 +2929,7 @@ public class KickCParser extends Parser {
_localctx = new AsmExprLabelContext(_localctx); _localctx = new AsmExprLabelContext(_localctx);
_ctx = _localctx; _ctx = _localctx;
_prevctx = _localctx; _prevctx = _localctx;
setState(337); setState(336);
match(NAME); match(NAME);
} }
break; break;
@ -2940,7 +2938,7 @@ public class KickCParser extends Parser {
_localctx = new AsmExprLabelRelContext(_localctx); _localctx = new AsmExprLabelRelContext(_localctx);
_ctx = _localctx; _ctx = _localctx;
_prevctx = _localctx; _prevctx = _localctx;
setState(338); setState(337);
match(ASMREL); match(ASMREL);
} }
break; break;
@ -2949,11 +2947,11 @@ public class KickCParser extends Parser {
_localctx = new AsmExprReplaceContext(_localctx); _localctx = new AsmExprReplaceContext(_localctx);
_ctx = _localctx; _ctx = _localctx;
_prevctx = _localctx; _prevctx = _localctx;
setState(339); setState(338);
match(T__0); match(T__0);
setState(340); setState(339);
match(NAME); match(NAME);
setState(341); setState(340);
match(T__1); match(T__1);
} }
break; break;
@ -2962,7 +2960,7 @@ public class KickCParser extends Parser {
_localctx = new AsmExprIntContext(_localctx); _localctx = new AsmExprIntContext(_localctx);
_ctx = _localctx; _ctx = _localctx;
_prevctx = _localctx; _prevctx = _localctx;
setState(342); setState(341);
match(NUMBER); match(NUMBER);
} }
break; break;
@ -2971,7 +2969,7 @@ public class KickCParser extends Parser {
_localctx = new AsmExprCharContext(_localctx); _localctx = new AsmExprCharContext(_localctx);
_ctx = _localctx; _ctx = _localctx;
_prevctx = _localctx; _prevctx = _localctx;
setState(343); setState(342);
match(CHAR); match(CHAR);
} }
break; break;
@ -2979,7 +2977,7 @@ public class KickCParser extends Parser {
throw new NoViableAltException(this); throw new NoViableAltException(this);
} }
_ctx.stop = _input.LT(-1); _ctx.stop = _input.LT(-1);
setState(354); setState(353);
_errHandler.sync(this); _errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,34,_ctx); _alt = getInterpreter().adaptivePredict(_input,34,_ctx);
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
@ -2987,16 +2985,16 @@ public class KickCParser extends Parser {
if ( _parseListeners!=null ) triggerExitRuleEvent(); if ( _parseListeners!=null ) triggerExitRuleEvent();
_prevctx = _localctx; _prevctx = _localctx;
{ {
setState(352); setState(351);
_errHandler.sync(this); _errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,33,_ctx) ) { switch ( getInterpreter().adaptivePredict(_input,33,_ctx) ) {
case 1: case 1:
{ {
_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
setState(346); setState(345);
if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
setState(347); setState(346);
_la = _input.LA(1); _la = _input.LA(1);
if ( !(_la==T__17 || _la==T__31) ) { if ( !(_la==T__17 || _la==T__31) ) {
_errHandler.recoverInline(this); _errHandler.recoverInline(this);
@ -3006,7 +3004,7 @@ public class KickCParser extends Parser {
_errHandler.reportMatch(this); _errHandler.reportMatch(this);
consume(); consume();
} }
setState(348); setState(347);
asmExpr(8); asmExpr(8);
} }
break; break;
@ -3014,9 +3012,9 @@ public class KickCParser extends Parser {
{ {
_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState)); _localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_asmExpr); pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
setState(349); setState(348);
if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
setState(350); setState(349);
_la = _input.LA(1); _la = _input.LA(1);
if ( !(_la==T__24 || _la==T__25) ) { if ( !(_la==T__24 || _la==T__25) ) {
_errHandler.recoverInline(this); _errHandler.recoverInline(this);
@ -3026,14 +3024,14 @@ public class KickCParser extends Parser {
_errHandler.reportMatch(this); _errHandler.reportMatch(this);
consume(); consume();
} }
setState(351); setState(350);
asmExpr(7); asmExpr(7);
} }
break; break;
} }
} }
} }
setState(356); setState(355);
_errHandler.sync(this); _errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,34,_ctx); _alt = getInterpreter().adaptivePredict(_input,34,_ctx);
} }
@ -3117,7 +3115,7 @@ public class KickCParser extends Parser {
} }
public static final String _serializedATN = public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3B\u0168\4\2\t\2\4"+ "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3B\u0167\4\2\t\2\4"+
"\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+
"\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\3\2\3\2\3\2\3\3\3\3\3\3\3\4\6\4\60\n\4\r\4\16\4\61"+ "\4\23\t\23\4\24\t\24\3\2\3\2\3\2\3\3\3\3\3\3\3\4\6\4\60\n\4\r\4\16\4\61"+
@ -3137,29 +3135,29 @@ public class KickCParser extends Parser {
"\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3"+ "\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3"+
"\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\7\r"+ "\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\7\r"+
"\u0116\n\r\f\r\16\r\u0119\13\r\3\16\3\16\3\16\7\16\u011e\n\16\f\16\16"+ "\u0116\n\r\f\r\16\r\u0119\13\r\3\16\3\16\3\16\7\16\u011e\n\16\f\16\16"+
"\16\u0121\13\16\3\17\3\17\7\17\u0125\n\17\f\17\16\17\u0128\13\17\3\20"+ "\16\u0121\13\16\3\17\7\17\u0124\n\17\f\17\16\17\u0127\13\17\3\20\3\20"+
"\3\20\5\20\u012c\n\20\3\21\3\21\3\21\3\21\5\21\u0132\n\21\3\22\3\22\5"+ "\5\20\u012b\n\20\3\21\3\21\3\21\3\21\5\21\u0131\n\21\3\22\3\22\5\22\u0135"+
"\22\u0136\n\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23"+ "\n\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23"+
"\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u014f"+ "\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u014e\n\23\3\24"+
"\n\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\5\24\u015b\n\24"+ "\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\5\24\u015a\n\24\3\24\3\24"+
"\3\24\3\24\3\24\3\24\3\24\3\24\7\24\u0163\n\24\f\24\16\24\u0166\13\24"+ "\3\24\3\24\3\24\3\24\7\24\u0162\n\24\f\24\16\24\u0165\13\24\3\24\2\6\22"+
"\3\24\2\6\22\26\30&\25\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&\2\13"+ "\26\30&\25\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&\2\13\3\2\27\30"+
"\3\2\27\30\3\2\31\32\5\2\24\24\27\30\33\37\3\2 !\4\2\24\24\"#\3\2\33\34"+ "\3\2\31\32\5\2\24\24\27\30\33\37\3\2 !\4\2\24\24\"#\3\2\33\34\4\2\27\30"+
"\4\2\27\30$*\4\2\27\30\33\34\4\2\24\24\"\"\2\u019b\2(\3\2\2\2\4+\3\2\2"+ "$*\4\2\27\30\33\34\4\2\24\24\"\"\2\u019a\2(\3\2\2\2\4+\3\2\2\2\6/\3\2"+
"\2\6/\3\2\2\2\b\u0082\3\2\2\2\n\u0085\3\2\2\2\f\u0097\3\2\2\2\16\u0099"+ "\2\2\b\u0082\3\2\2\2\n\u0085\3\2\2\2\f\u0097\3\2\2\2\16\u0099\3\2\2\2"+
"\3\2\2\2\20\u00a1\3\2\2\2\22\u00a4\3\2\2\2\24\u00c0\3\2\2\2\26\u00cc\3"+ "\20\u00a1\3\2\2\2\22\u00a4\3\2\2\2\24\u00c0\3\2\2\2\26\u00cc\3\2\2\2\30"+
"\2\2\2\30\u00f1\3\2\2\2\32\u011a\3\2\2\2\34\u0122\3\2\2\2\36\u012b\3\2"+ "\u00f1\3\2\2\2\32\u011a\3\2\2\2\34\u0125\3\2\2\2\36\u012a\3\2\2\2 \u0130"+
"\2\2 \u0131\3\2\2\2\"\u0133\3\2\2\2$\u014e\3\2\2\2&\u015a\3\2\2\2()\5"+ "\3\2\2\2\"\u0132\3\2\2\2$\u014d\3\2\2\2&\u0159\3\2\2\2()\5\6\4\2)*\7\2"+
"\6\4\2)*\7\2\2\3*\3\3\2\2\2+,\5\34\17\2,-\7\2\2\3-\5\3\2\2\2.\60\5\b\5"+ "\2\3*\3\3\2\2\2+,\5\34\17\2,-\7\2\2\3-\5\3\2\2\2.\60\5\b\5\2/.\3\2\2\2"+
"\2/.\3\2\2\2\60\61\3\2\2\2\61/\3\2\2\2\61\62\3\2\2\2\62\7\3\2\2\2\63\65"+ "\60\61\3\2\2\2\61/\3\2\2\2\61\62\3\2\2\2\62\7\3\2\2\2\63\65\7\3\2\2\64"+
"\7\3\2\2\64\66\5\6\4\2\65\64\3\2\2\2\65\66\3\2\2\2\66\67\3\2\2\2\67\u0083"+ "\66\5\6\4\2\65\64\3\2\2\2\65\66\3\2\2\2\66\67\3\2\2\2\67\u0083\7\4\2\2"+
"\7\4\2\289\5\22\n\29:\7>\2\2:<\7\5\2\2;=\5\16\b\2<;\3\2\2\2<=\3\2\2\2"+ "89\5\22\n\29:\7>\2\2:<\7\5\2\2;=\5\16\b\2<;\3\2\2\2<=\3\2\2\2=>\3\2\2"+
"=>\3\2\2\2>?\7\6\2\2?A\7\3\2\2@B\5\6\4\2A@\3\2\2\2AB\3\2\2\2BC\3\2\2\2"+ "\2>?\7\6\2\2?A\7\3\2\2@B\5\6\4\2A@\3\2\2\2AB\3\2\2\2BC\3\2\2\2CD\7\4\2"+
"CD\7\4\2\2D\u0083\3\2\2\2EG\7\7\2\2FE\3\2\2\2FG\3\2\2\2GH\3\2\2\2HI\5"+ "\2D\u0083\3\2\2\2EG\7\7\2\2FE\3\2\2\2FG\3\2\2\2GH\3\2\2\2HI\5\22\n\2I"+
"\22\n\2IL\7>\2\2JK\7\b\2\2KM\5\24\13\2LJ\3\2\2\2LM\3\2\2\2MN\3\2\2\2N"+ "L\7>\2\2JK\7\b\2\2KM\5\24\13\2LJ\3\2\2\2LM\3\2\2\2MN\3\2\2\2NO\7\t\2\2"+
"O\7\t\2\2O\u0083\3\2\2\2PQ\5\26\f\2QR\7\b\2\2RS\5\30\r\2ST\7\t\2\2T\u0083"+ "O\u0083\3\2\2\2PQ\5\26\f\2QR\7\b\2\2RS\5\30\r\2ST\7\t\2\2T\u0083\3\2\2"+
"\3\2\2\2UV\5\30\r\2VW\7\t\2\2W\u0083\3\2\2\2XY\7\n\2\2YZ\7\5\2\2Z[\5\30"+ "\2UV\5\30\r\2VW\7\t\2\2W\u0083\3\2\2\2XY\7\n\2\2YZ\7\5\2\2Z[\5\30\r\2"+
"\r\2[\\\7\6\2\2\\_\5\b\5\2]^\7\13\2\2^`\5\b\5\2_]\3\2\2\2_`\3\2\2\2`\u0083"+ "[\\\7\6\2\2\\_\5\b\5\2]^\7\13\2\2^`\5\b\5\2_]\3\2\2\2_`\3\2\2\2`\u0083"+
"\3\2\2\2ab\7\f\2\2bc\7\5\2\2cd\5\30\r\2de\7\6\2\2ef\5\b\5\2f\u0083\3\2"+ "\3\2\2\2ab\7\f\2\2bc\7\5\2\2cd\5\30\r\2de\7\6\2\2ef\5\b\5\2f\u0083\3\2"+
"\2\2gh\7\r\2\2hi\5\b\5\2ij\7\f\2\2jk\7\5\2\2kl\5\30\r\2lm\7\6\2\2mn\7"+ "\2\2gh\7\r\2\2hi\5\b\5\2ij\7\f\2\2jk\7\5\2\2kl\5\30\r\2lm\7\6\2\2mn\7"+
"\t\2\2n\u0083\3\2\2\2op\7\16\2\2pr\7\5\2\2qs\5\n\6\2rq\3\2\2\2rs\3\2\2"+ "\t\2\2n\u0083\3\2\2\2op\7\16\2\2pr\7\5\2\2qs\5\n\6\2rq\3\2\2\2rs\3\2\2"+
@ -3224,33 +3222,32 @@ public class KickCParser extends Parser {
"\31\3\2\2\2\u0119\u0117\3\2\2\2\u011a\u011f\5\30\r\2\u011b\u011c\7\23"+ "\31\3\2\2\2\u0119\u0117\3\2\2\2\u011a\u011f\5\30\r\2\u011b\u011c\7\23"+
"\2\2\u011c\u011e\5\30\r\2\u011d\u011b\3\2\2\2\u011e\u0121\3\2\2\2\u011f"+ "\2\2\u011c\u011e\5\30\r\2\u011d\u011b\3\2\2\2\u011e\u0121\3\2\2\2\u011f"+
"\u011d\3\2\2\2\u011f\u0120\3\2\2\2\u0120\33\3\2\2\2\u0121\u011f\3\2\2"+ "\u011d\3\2\2\2\u011f\u0120\3\2\2\2\u0120\33\3\2\2\2\u0121\u011f\3\2\2"+
"\2\u0122\u0126\5\36\20\2\u0123\u0125\5\36\20\2\u0124\u0123\3\2\2\2\u0125"+ "\2\u0122\u0124\5\36\20\2\u0123\u0122\3\2\2\2\u0124\u0127\3\2\2\2\u0125"+
"\u0128\3\2\2\2\u0126\u0124\3\2\2\2\u0126\u0127\3\2\2\2\u0127\35\3\2\2"+ "\u0123\3\2\2\2\u0125\u0126\3\2\2\2\u0126\35\3\2\2\2\u0127\u0125\3\2\2"+
"\2\u0128\u0126\3\2\2\2\u0129\u012c\5 \21\2\u012a\u012c\5\"\22\2\u012b"+ "\2\u0128\u012b\5 \21\2\u0129\u012b\5\"\22\2\u012a\u0128\3\2\2\2\u012a"+
"\u0129\3\2\2\2\u012b\u012a\3\2\2\2\u012c\37\3\2\2\2\u012d\u012e\7>\2\2"+ "\u0129\3\2\2\2\u012b\37\3\2\2\2\u012c\u012d\7>\2\2\u012d\u0131\7\21\2"+
"\u012e\u0132\7\21\2\2\u012f\u0130\7\35\2\2\u0130\u0132\7\21\2\2\u0131"+ "\2\u012e\u012f\7\35\2\2\u012f\u0131\7\21\2\2\u0130\u012c\3\2\2\2\u0130"+
"\u012d\3\2\2\2\u0131\u012f\3\2\2\2\u0132!\3\2\2\2\u0133\u0135\7\60\2\2"+ "\u012e\3\2\2\2\u0131!\3\2\2\2\u0132\u0134\7\60\2\2\u0133\u0135\5$\23\2"+
"\u0134\u0136\5$\23\2\u0135\u0134\3\2\2\2\u0135\u0136\3\2\2\2\u0136#\3"+ "\u0134\u0133\3\2\2\2\u0134\u0135\3\2\2\2\u0135#\3\2\2\2\u0136\u014e\5"+
"\2\2\2\u0137\u014f\5&\24\2\u0138\u0139\7/\2\2\u0139\u014f\5&\24\2\u013a"+ "&\24\2\u0137\u0138\7/\2\2\u0138\u014e\5&\24\2\u0139\u013a\5&\24\2\u013a"+
"\u013b\5&\24\2\u013b\u013c\7\23\2\2\u013c\u013d\7>\2\2\u013d\u014f\3\2"+ "\u013b\7\23\2\2\u013b\u013c\7>\2\2\u013c\u014e\3\2\2\2\u013d\u013e\7\5"+
"\2\2\u013e\u013f\7\5\2\2\u013f\u0140\5&\24\2\u0140\u0141\7\6\2\2\u0141"+ "\2\2\u013e\u013f\5&\24\2\u013f\u0140\7\6\2\2\u0140\u0141\7\23\2\2\u0141"+
"\u0142\7\23\2\2\u0142\u0143\7>\2\2\u0143\u014f\3\2\2\2\u0144\u0145\7\5"+ "\u0142\7>\2\2\u0142\u014e\3\2\2\2\u0143\u0144\7\5\2\2\u0144\u0145\5&\24"+
"\2\2\u0145\u0146\5&\24\2\u0146\u0147\7\23\2\2\u0147\u0148\7>\2\2\u0148"+ "\2\u0145\u0146\7\23\2\2\u0146\u0147\7>\2\2\u0147\u0148\7\6\2\2\u0148\u014e"+
"\u0149\7\6\2\2\u0149\u014f\3\2\2\2\u014a\u014b\7\5\2\2\u014b\u014c\5&"+ "\3\2\2\2\u0149\u014a\7\5\2\2\u014a\u014b\5&\24\2\u014b\u014c\7\6\2\2\u014c"+
"\24\2\u014c\u014d\7\6\2\2\u014d\u014f\3\2\2\2\u014e\u0137\3\2\2\2\u014e"+ "\u014e\3\2\2\2\u014d\u0136\3\2\2\2\u014d\u0137\3\2\2\2\u014d\u0139\3\2"+
"\u0138\3\2\2\2\u014e\u013a\3\2\2\2\u014e\u013e\3\2\2\2\u014e\u0144\3\2"+ "\2\2\u014d\u013d\3\2\2\2\u014d\u0143\3\2\2\2\u014d\u0149\3\2\2\2\u014e"+
"\2\2\u014e\u014a\3\2\2\2\u014f%\3\2\2\2\u0150\u0151\b\24\1\2\u0151\u0152"+ "%\3\2\2\2\u014f\u0150\b\24\1\2\u0150\u0151\t\t\2\2\u0151\u015a\5&\24\n"+
"\t\t\2\2\u0152\u015b\5&\24\n\u0153\u015b\7>\2\2\u0154\u015b\7?\2\2\u0155"+ "\u0152\u015a\7>\2\2\u0153\u015a\7?\2\2\u0154\u0155\7\3\2\2\u0155\u0156"+
"\u0156\7\3\2\2\u0156\u0157\7>\2\2\u0157\u015b\7\4\2\2\u0158\u015b\7\65"+ "\7>\2\2\u0156\u015a\7\4\2\2\u0157\u015a\7\65\2\2\u0158\u015a\7\63\2\2"+
"\2\2\u0159\u015b\7\63\2\2\u015a\u0150\3\2\2\2\u015a\u0153\3\2\2\2\u015a"+ "\u0159\u014f\3\2\2\2\u0159\u0152\3\2\2\2\u0159\u0153\3\2\2\2\u0159\u0154"+
"\u0154\3\2\2\2\u015a\u0155\3\2\2\2\u015a\u0158\3\2\2\2\u015a\u0159\3\2"+ "\3\2\2\2\u0159\u0157\3\2\2\2\u0159\u0158\3\2\2\2\u015a\u0163\3\2\2\2\u015b"+
"\2\2\u015b\u0164\3\2\2\2\u015c\u015d\f\t\2\2\u015d\u015e\t\n\2\2\u015e"+ "\u015c\f\t\2\2\u015c\u015d\t\n\2\2\u015d\u0162\5&\24\n\u015e\u015f\f\b"+
"\u0163\5&\24\n\u015f\u0160\f\b\2\2\u0160\u0161\t\7\2\2\u0161\u0163\5&"+ "\2\2\u015f\u0160\t\7\2\2\u0160\u0162\5&\24\t\u0161\u015b\3\2\2\2\u0161"+
"\24\t\u0162\u015c\3\2\2\2\u0162\u015f\3\2\2\2\u0163\u0166\3\2\2\2\u0164"+ "\u015e\3\2\2\2\u0162\u0165\3\2\2\2\u0163\u0161\3\2\2\2\u0163\u0164\3\2"+
"\u0162\3\2\2\2\u0164\u0165\3\2\2\2\u0165\'\3\2\2\2\u0166\u0164\3\2\2\2"+ "\2\2\u0164\'\3\2\2\2\u0165\u0163\3\2\2\2%\61\65<AFL_rz\u0082\u0085\u008a"+
"%\61\65<AFL_rz\u0082\u0085\u008a\u0090\u0097\u009e\u00ac\u00af\u00b1\u00bb"+ "\u0090\u0097\u009e\u00ac\u00af\u00b1\u00bb\u00c0\u00cc\u00d5\u00e0\u00f1"+
"\u00c0\u00cc\u00d5\u00e0\u00f1\u0115\u0117\u011f\u0126\u012b\u0131\u0135"+ "\u0115\u0117\u011f\u0125\u012a\u0130\u0134\u014d\u0159\u0161\u0163";
"\u014e\u015a\u0162\u0164";
public static final ATN _ATN = public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray()); new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static { static {

View File

@ -227,7 +227,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
private Aliases findAliases() { private Aliases findAliases() {
Aliases candidates = findAliasesCandidates(); Aliases candidates = findAliasesCandidates(false, getProgram());
cleanupCandidates(candidates); cleanupCandidates(candidates);
return candidates; return candidates;
} }
@ -265,9 +265,9 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
* *
* @return Map from Variable to the Constant value * @return Map from Variable to the Constant value
*/ */
private Aliases findAliasesCandidates() { public static Aliases findAliasesCandidates(final boolean allowCrossScope, final Program program) {
final Aliases aliases = new Aliases(); final Aliases aliases = new Aliases();
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() { final ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override @Override
public Void visitAssignment(StatementAssignment assignment) { public Void visitAssignment(StatementAssignment assignment) {
if (assignment.getlValue() instanceof VariableRef) { if (assignment.getlValue() instanceof VariableRef) {
@ -278,7 +278,11 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
if(variable.getScopeNames().equals(alias.getScopeNames())){ if(variable.getScopeNames().equals(alias.getScopeNames())){
aliases.add(variable, alias); aliases.add(variable, alias);
} else { } else {
getLog().append("Not aliassing across scopes: "+variable+" "+alias); if(allowCrossScope) {
aliases.add(variable, alias);
} else {
program.getLog().append("Not aliassing across scopes: " + variable + " " + alias);
}
} }
} }
} }
@ -296,11 +300,13 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
if (phiRValue.getrValue() instanceof VariableRef) { if (phiRValue.getrValue() instanceof VariableRef) {
alias = (VariableRef) phiRValue.getrValue(); alias = (VariableRef) phiRValue.getrValue();
if(!variable.getScopeNames().equals(alias.getScopeNames())){ if(!variable.getScopeNames().equals(alias.getScopeNames())){
getLog().append("Not aliassing across scopes: "+variable+" "+alias); if(!allowCrossScope) {
alias = null; program.getLog().append("Not aliassing across scopes: " + variable + " " + alias);
break; alias = null;
break;
}
} else if(variable.equals(alias)) { } else if(variable.equals(alias)) {
getLog().append("Not aliassing identity: "+variable+" "+alias); program.getLog().append("Not aliassing identity: "+variable+" "+alias);
alias = null; alias = null;
break; break;
} }
@ -325,7 +331,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
return null; return null;
} }
}; };
visitor.visitGraph(getGraph()); visitor.visitGraph(program.getGraph());
return aliases; return aliases;
} }

View File

@ -1,12 +1,12 @@
package dk.camelot64.kickc.passes; package dk.camelot64.kickc.passes;
/**
* Find effective alive intervals for all variables in all statements. Add the intervals to the Program.
*/
import dk.camelot64.kickc.model.*; import dk.camelot64.kickc.model.*;
import java.util.*; import java.util.*;
/**
* Find effective alive intervals for all variables in all statements. Add the intervals to the Program.
*/
public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
public Pass3LiveRangesEffectiveAnalysis(Program program) { public Pass3LiveRangesEffectiveAnalysis(Program program) {
@ -19,17 +19,17 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
//getLog().append("Calculated effective variable live ranges"); //getLog().append("Calculated effective variable live ranges");
} }
private LiveRangeVariablesEffective findAliveEffective(Program program) { private LiveRangeVariablesEffective findAliveEffective(Program program) {
LiveRangeVariables liveRangeVariables = program.getLiveRangeVariables(); LiveRangeVariables liveRangeVariables = program.getLiveRangeVariables();
Map<Integer, Collection<VariableRef>> effectiveLiveVariables = new HashMap<>(); Map<Integer, LiveRangeVariablesEffective.AliveCombinations> effectiveLiveVariablesCombinations = new HashMap<>();
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) { for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for (Statement statement : block.getStatements()) { for (Statement statement : block.getStatements()) {
Collection<VariableRef> aliveEffective = findAliveEffective( liveRangeVariables, statement); Collection<Collection<VariableRef>> statementAliveCombinations = findAliveEffective(liveRangeVariables, statement);
effectiveLiveVariables.put(statement.getIndex(), aliveEffective); LiveRangeVariablesEffective.AliveCombinations aliveCombinations = new LiveRangeVariablesEffective.AliveCombinations(statementAliveCombinations);
effectiveLiveVariablesCombinations.put(statement.getIndex(), aliveCombinations);
} }
} }
return new LiveRangeVariablesEffective(effectiveLiveVariables); return new LiveRangeVariablesEffective(effectiveLiveVariablesCombinations);
} }
/** /**
@ -41,10 +41,10 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
* @param statement The statement to examine * @param statement The statement to examine
* @return All variables alive at the statement * @return All variables alive at the statement
*/ */
private Collection<VariableRef> findAliveEffective(LiveRangeVariables liveRangeVariables, Statement statement) { private Collection<Collection<VariableRef>> findAliveEffective(LiveRangeVariables liveRangeVariables, Statement statement) {
Set<Collection<VariableRef>> combinations = new LinkedHashSet<>();
// Get variables alive from live range analysis // Get variables alive from live range analysis
Collection<VariableRef> effectiveAlive = new LinkedHashSet<>(); Collection<VariableRef> effectiveAlive = liveRangeVariables.getAlive(statement);
effectiveAlive.addAll(liveRangeVariables.getAlive(statement));
// If the statement is inside a method recurse back to all calls // If the statement is inside a method recurse back to all calls
// For each call add the variables alive after the call that are not referenced (used/defined) inside the method // For each call add the variables alive after the call that are not referenced (used/defined) inside the method
ControlFlowBlock block = getProgram().getGraph().getBlockFromStatementIdx(statement.getIndex()); ControlFlowBlock block = getProgram().getGraph().getBlockFromStatementIdx(statement.getIndex());
@ -57,16 +57,28 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
VariableReferenceInfo referenceInfo = new VariableReferenceInfo(getProgram()); VariableReferenceInfo referenceInfo = new VariableReferenceInfo(getProgram());
Collection<VariableRef> referencedInProcedure = referenceInfo.getReferenced(procedure.getRef().getLabelRef()); Collection<VariableRef> referencedInProcedure = referenceInfo.getReferenced(procedure.getRef().getLabelRef());
for (CallGraph.CallBlock.Call caller : callers) { for (CallGraph.CallBlock.Call caller : callers) {
// Each caller creates its own combinations
StatementCall callStatement = StatementCall callStatement =
(StatementCall) getProgram().getGraph().getStatementByIndex(caller.getCallStatementIdx()); (StatementCall) getProgram().getGraph().getStatementByIndex(caller.getCallStatementIdx());
Set<VariableRef> callAliveEffective = new LinkedHashSet<>(findAliveEffective(liveRangeVariables, callStatement)); Collection<Collection<VariableRef>> callerCombinations = findAliveEffective(liveRangeVariables, callStatement);
// Clear out any variables referenced in the method for (Collection<VariableRef> callerCombination : callerCombinations) {
callAliveEffective.removeAll(referencedInProcedure); LinkedHashSet<VariableRef> combination = new LinkedHashSet<>();
effectiveAlive.addAll(callAliveEffective); // Add alive at call
combination.addAll(callerCombination);
// Clear out any variables referenced in the method
combination.removeAll(referencedInProcedure);
// Add alive at statement
combination.addAll(effectiveAlive);
// Add combination
combinations.add(combination);
}
} }
} }
return effectiveAlive; if(combinations.size()==0) {
// Add the combination at the current statement if no other combinations have been created
combinations.add(effectiveAlive);
}
return combinations;
} }
} }

View File

@ -42,10 +42,10 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
* Stores the best combination directly in the {@link LiveRangeEquivalenceClassSet}. * Stores the best combination directly in the {@link LiveRangeEquivalenceClassSet}.
* *
* @param combinationIterator The combination iterator used for supplying different register allocations to test * @param combinationIterator The combination iterator used for supplying different register allocations to test
* @param maxCombinations The maximal number of combinations to test. It the iterator has more combinations he rest is skipped (and a message logged) * @param maxCombinations The maximal number of combinations to test. It the iterator has more combinations he rest is skipped (and a message logged)
* @param unknownFragments Receives any unknown ASM fragments encountered during the combinsation search * @param unknownFragments Receives any unknown ASM fragments encountered during the combinsation search
* @param scope The scope where the variables are being tested. (Only used for logging) * @param scope The scope where the variables are being tested. (Only used for logging)
* @param program The program to test (used for accessing global data structures) * @param program The program to test (used for accessing global data structures)
*/ */
static void chooseBestUpliftCombination( static void chooseBestUpliftCombination(
RegisterCombinationIterator combinationIterator, int maxCombinations, RegisterCombinationIterator combinationIterator, int maxCombinations,
@ -93,15 +93,15 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
* Attempt generate ASM with a specific register combination. * Attempt generate ASM with a specific register combination.
* The generation may result in failure if * The generation may result in failure if
* <ul> * <ul>
* <li>The combination has assigned the same register to variables with overlapping live ranges</li> * <li>The combination has assigned the same register to variables with overlapping live ranges</li>
* <li>The register combination results in clobbering registers containing values that are still alive</li> * <li>The register combination results in clobbering registers containing values that are still alive</li>
* <li>some ASM fragments are missing </li> * <li>some ASM fragments are missing </li>
* <li>the ALU register is used in a non-applicable way</li> * <li>the ALU register is used in a non-applicable way</li>
* </ul> * </ul>
* *
* @param combination The register allocation combination * @param combination The register allocation combination
* @param unknownFragments Will receive any AsmFragments that can not be found during the ASM code generation * @param unknownFragments Will receive any AsmFragments that can not be found during the ASM code generation
* @param scope The scope where the combination is tested. (Only used for logging) * @param scope The scope where the combination is tested. (Only used for logging)
* @return true if the generation was successful * @return true if the generation was successful
*/ */
public static boolean generateCombinationAsm( public static boolean generateCombinationAsm(
@ -167,6 +167,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
* Programs that take less cycles to execute have lower scores. * Programs that take less cycles to execute have lower scores.
* In practice the score is calculated by multiplying cycles of ASM instructions with * In practice the score is calculated by multiplying cycles of ASM instructions with
* an estimate of the invocation count based on the loop depth of the instructions (10^depth). * an estimate of the invocation count based on the loop depth of the instructions (10^depth).
*
* @param program The program containing the ASM to check * @param program The program containing the ASM to check
* @return The score of the ASM * @return The score of the ASM
*/ */
@ -190,17 +191,17 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
return score; return score;
} }
/** /**
* Check the register allocation for whether a is register being allocated to two variables with overlapping live ranges * Check the register allocation for whether a is register being allocated to two variables with overlapping live ranges
*
* @param program The program * @param program The program
* @return true if the register allocation contains an overlapping allocation. false otherwise. * @return true if the register allocation contains an overlapping allocation. false otherwise.
*/ */
public static boolean isAllocationOverlapping(Program program) { public static boolean isAllocationOverlapping(Program program) {
Pass2AliasElimination.Aliases aliases = Pass2AliasElimination.findAliasesCandidates(true, program);
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) { for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for (Statement statement : block.getStatements()) { for (Statement statement : block.getStatements()) {
LinkedHashMap<Registers.Register, LiveRangeEquivalenceClass> usedRegisters = new LinkedHashMap<>(); if (isStatementAllocationOverlapping(program, statement, aliases)) {
if (isStatementAllocationOverlapping(program, statement, usedRegisters)) {
return true; return true;
} }
} }
@ -211,32 +212,46 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
/** /**
* Determine if a statement has an overlapping register allocation * Determine if a statement has an overlapping register allocation
* *
* @param program The program * @param program The program
* @param statement The statement to check * @param statement The statement to check
* @param usedRegisters The used registers. Will be extended with all registers used in the statement. * @param usedRegisters The used registers. Will be extended with all registers used in the statement.
* @return true if there is an overlapping register allocation * @return true if there is an overlapping register allocation
*/ */
private static boolean isStatementAllocationOverlapping( private static boolean isStatementAllocationOverlapping(Program program, Statement statement, Pass2AliasElimination.Aliases aliases) {
Program program,
Statement statement,
LinkedHashMap<Registers.Register, LiveRangeEquivalenceClass> usedRegisters) {
ProgramScope programScope = program.getScope(); ProgramScope programScope = program.getScope();
Collection<VariableRef> alive = program.getLiveRangeVariablesEffective().getAliveEffective(statement); LiveRangeVariablesEffective.AliveCombinations aliveCombinations = program.getLiveRangeVariablesEffective().getAliveCombinations(statement);
for (VariableRef varRef : alive) { for (LiveRangeVariablesEffective.AliveCombination aliveCombination : aliveCombinations.getCombinations()) {
Variable var = programScope.getVariable(varRef); LinkedHashMap<Registers.Register, LiveRangeEquivalenceClass> usedRegisters = new LinkedHashMap<>();
Registers.Register allocation = var.getAllocation(); Collection<VariableRef> alive = aliveCombination.getAlive();
LiveRangeEquivalenceClass allocationClass = usedRegisters.get(allocation); for (VariableRef varRef : alive) {
if (allocationClass != null && !allocationClass.contains(varRef)) { Variable var = programScope.getVariable(varRef);
if (program.getLog().isVerboseUplift()) { Registers.Register allocation = var.getAllocation();
StringBuilder msg = new StringBuilder(); LiveRangeEquivalenceClass allocationClass = usedRegisters.get(allocation);
msg.append("Overlap register " + allocation + " in " + statement.toString(program)); if (allocationClass != null && !allocationClass.contains(varRef)) {
program.getLog().append(msg.toString()); // Examine if the var is an alias of a var in the allocation class
boolean overlap = true;
Pass2AliasElimination.AliasSet aliasSet = aliases.findAliasSet(varRef);
if(aliasSet!=null) {
for (VariableRef aliasVar : aliasSet.getVars()) {
if(allocationClass.contains(aliasVar)) {
overlap = false;
}
}
}
if(overlap) {
if (program.getLog().isVerboseUplift()) {
StringBuilder msg = new StringBuilder();
msg.append("Overlap register " + allocation + " in " + statement.toString(program));
program.getLog().append(msg.toString());
}
return true;
}
} else {
LiveRangeEquivalenceClass varClass =
program.getLiveRangeEquivalenceClassSet().getEquivalenceClass(varRef);
usedRegisters.put(allocation, varClass);
} }
return true;
} }
LiveRangeEquivalenceClass varClass =
program.getLiveRangeEquivalenceClassSet().getEquivalenceClass(varRef);
usedRegisters.put(allocation, varClass);
} }
return false; return false;
} }

View File

@ -74,8 +74,15 @@ public class Pass4RegisterUpliftStatic extends Pass2Base {
setRegister(combination, "line::$7", Registers.getRegisterALU()); setRegister(combination, "line::$7", Registers.getRegisterALU());
setRegister(combination, "initplottables::$6", Registers.getRegisterA()); setRegister(combination, "initplottables::$6", Registers.getRegisterA());
setRegister(combination, "initplottables::$7", Registers.getRegisterALU()); setRegister(combination, "initplottables::$7", Registers.getRegisterALU());
*/
setRegister(combination, "initplottables::$6", Registers.getRegisterA()); setRegister(combination, "initplottables::$6", Registers.getRegisterA());
*/
setRegister(combination, "plot::x#0", Registers.getRegisterX());
setRegister(combination, "plot::x#1", Registers.getRegisterX());
setRegister(combination, "plot::x#2", Registers.getRegisterX());
setRegister(combination, "plot::x#3", Registers.getRegisterX());
setRegister(combination, "main::i#1", Registers.getRegisterX());
setRegister(combination, "main::i#2", Registers.getRegisterX());
boolean success = Pass4RegisterUpliftCombinations.generateCombinationAsm( boolean success = Pass4RegisterUpliftCombinations.generateCombinationAsm(
combination, combination,