1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-08-02 09:29:35 +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);
new Pass4RegisterUpliftCombinations(program).performUplift(10_000);
//program.getLog().setVerboseUplift(true);
//new Pass4RegisterUpliftStatic(program).performUplift();
//program.getLog().setVerboseUplift(false);
program.getLog().setVerboseUplift(true);
new Pass4RegisterUpliftStatic(program).performUplift();
program.getLog().setVerboseUplift(false);
// Attempt uplifting registers one at a time to catch remaining potential not realized by combination search
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 {
/** Effectively alive variables by statement index. */
Map<Integer, Collection<VariableRef>> effectiveLiveVariables;
Map<Integer, AliveCombinations> effectiveLiveCombinations;
public LiveRangeVariablesEffective(Map<Integer, Collection<VariableRef>> effectiveLiveVariables) {
this.effectiveLiveVariables = effectiveLiveVariables;
public LiveRangeVariablesEffective(Map<Integer, AliveCombinations> effectiveLiveCombinations) {
this.effectiveLiveCombinations = effectiveLiveCombinations;
}
/**
* Get all variables alive at a statement.
* If the statement is inside a method this also includes all variables alive at the exit of the calls.
* <p>
* This method requires a number of other analysis to be present and updated in the (global) program - especailly the Call Graph.
* 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 any call.
* </p>
* @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) {
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;
import java.util.Collection;
import java.util.List;
/** Statement base class implementing shared properties and logic */
@ -48,7 +49,22 @@ public abstract class StatementBase implements Statement {
return "";
}
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();
str.append(" [ ");
for (VariableRef variableRef : alive) {

View File

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

View File

@ -2315,19 +2315,17 @@ public class KickCParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(288);
asmLine();
setState(292);
setState(291);
_errHandler.sync(this);
_la = _input.LA(1);
while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__26) | (1L << MNEMONIC) | (1L << NAME))) != 0)) {
{
{
setState(289);
setState(288);
asmLine();
}
}
setState(294);
setState(293);
_errHandler.sync(this);
_la = _input.LA(1);
}
@ -2374,21 +2372,21 @@ public class KickCParser extends Parser {
AsmLineContext _localctx = new AsmLineContext(_ctx, getState());
enterRule(_localctx, 28, RULE_asmLine);
try {
setState(297);
setState(296);
_errHandler.sync(this);
switch (_input.LA(1)) {
case T__26:
case NAME:
enterOuterAlt(_localctx, 1);
{
setState(295);
setState(294);
asmLabel();
}
break;
case MNEMONIC:
enterOuterAlt(_localctx, 2);
{
setState(296);
setState(295);
asmInstruction();
}
break;
@ -2432,24 +2430,24 @@ public class KickCParser extends Parser {
AsmLabelContext _localctx = new AsmLabelContext(_ctx, getState());
enterRule(_localctx, 30, RULE_asmLabel);
try {
setState(303);
setState(302);
_errHandler.sync(this);
switch (_input.LA(1)) {
case NAME:
enterOuterAlt(_localctx, 1);
{
setState(299);
setState(298);
match(NAME);
setState(300);
setState(299);
match(T__14);
}
break;
case T__26:
enterOuterAlt(_localctx, 2);
{
setState(301);
setState(300);
match(T__26);
setState(302);
setState(301);
match(T__14);
}
break;
@ -2498,14 +2496,14 @@ public class KickCParser extends Parser {
try {
enterOuterAlt(_localctx, 1);
{
setState(305);
setState(304);
match(MNEMONIC);
setState(307);
setState(306);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,30,_ctx) ) {
case 1:
{
setState(306);
setState(305);
asmParamMode();
}
break;
@ -2656,14 +2654,14 @@ public class KickCParser extends Parser {
AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState());
enterRule(_localctx, 34, RULE_asmParamMode);
try {
setState(332);
setState(331);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,31,_ctx) ) {
case 1:
_localctx = new AsmModeAbsContext(_localctx);
enterOuterAlt(_localctx, 1);
{
setState(309);
setState(308);
asmExpr(0);
}
break;
@ -2671,9 +2669,9 @@ public class KickCParser extends Parser {
_localctx = new AsmModeImmContext(_localctx);
enterOuterAlt(_localctx, 2);
{
setState(310);
setState(309);
match(T__44);
setState(311);
setState(310);
asmExpr(0);
}
break;
@ -2681,11 +2679,11 @@ public class KickCParser extends Parser {
_localctx = new AsmModeAbsXYContext(_localctx);
enterOuterAlt(_localctx, 3);
{
setState(312);
setState(311);
asmExpr(0);
setState(313);
setState(312);
match(T__16);
setState(314);
setState(313);
match(NAME);
}
break;
@ -2693,15 +2691,15 @@ public class KickCParser extends Parser {
_localctx = new AsmModeIndIdxXYContext(_localctx);
enterOuterAlt(_localctx, 4);
{
setState(316);
setState(315);
match(T__2);
setState(317);
setState(316);
asmExpr(0);
setState(318);
setState(317);
match(T__3);
setState(319);
setState(318);
match(T__16);
setState(320);
setState(319);
match(NAME);
}
break;
@ -2709,15 +2707,15 @@ public class KickCParser extends Parser {
_localctx = new AsmModeIdxIndXYContext(_localctx);
enterOuterAlt(_localctx, 5);
{
setState(322);
setState(321);
match(T__2);
setState(323);
setState(322);
asmExpr(0);
setState(324);
setState(323);
match(T__16);
setState(325);
setState(324);
match(NAME);
setState(326);
setState(325);
match(T__3);
}
break;
@ -2725,11 +2723,11 @@ public class KickCParser extends Parser {
_localctx = new AsmModeIndContext(_localctx);
enterOuterAlt(_localctx, 6);
{
setState(328);
setState(327);
match(T__2);
setState(329);
setState(328);
asmExpr(0);
setState(330);
setState(329);
match(T__3);
}
break;
@ -2900,7 +2898,7 @@ public class KickCParser extends Parser {
int _alt;
enterOuterAlt(_localctx, 1);
{
setState(344);
setState(343);
_errHandler.sync(this);
switch (_input.LA(1)) {
case T__20:
@ -2912,7 +2910,7 @@ public class KickCParser extends Parser {
_ctx = _localctx;
_prevctx = _localctx;
setState(335);
setState(334);
_la = _input.LA(1);
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__20) | (1L << T__21) | (1L << T__24) | (1L << T__25))) != 0)) ) {
_errHandler.recoverInline(this);
@ -2922,7 +2920,7 @@ public class KickCParser extends Parser {
_errHandler.reportMatch(this);
consume();
}
setState(336);
setState(335);
asmExpr(8);
}
break;
@ -2931,7 +2929,7 @@ public class KickCParser extends Parser {
_localctx = new AsmExprLabelContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(337);
setState(336);
match(NAME);
}
break;
@ -2940,7 +2938,7 @@ public class KickCParser extends Parser {
_localctx = new AsmExprLabelRelContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(338);
setState(337);
match(ASMREL);
}
break;
@ -2949,11 +2947,11 @@ public class KickCParser extends Parser {
_localctx = new AsmExprReplaceContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(339);
setState(338);
match(T__0);
setState(340);
setState(339);
match(NAME);
setState(341);
setState(340);
match(T__1);
}
break;
@ -2962,7 +2960,7 @@ public class KickCParser extends Parser {
_localctx = new AsmExprIntContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(342);
setState(341);
match(NUMBER);
}
break;
@ -2971,7 +2969,7 @@ public class KickCParser extends Parser {
_localctx = new AsmExprCharContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(343);
setState(342);
match(CHAR);
}
break;
@ -2979,7 +2977,7 @@ public class KickCParser extends Parser {
throw new NoViableAltException(this);
}
_ctx.stop = _input.LT(-1);
setState(354);
setState(353);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,34,_ctx);
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();
_prevctx = _localctx;
{
setState(352);
setState(351);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,33,_ctx) ) {
case 1:
{
_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
setState(346);
setState(345);
if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
setState(347);
setState(346);
_la = _input.LA(1);
if ( !(_la==T__17 || _la==T__31) ) {
_errHandler.recoverInline(this);
@ -3006,7 +3004,7 @@ public class KickCParser extends Parser {
_errHandler.reportMatch(this);
consume();
}
setState(348);
setState(347);
asmExpr(8);
}
break;
@ -3014,9 +3012,9 @@ public class KickCParser extends Parser {
{
_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
setState(349);
setState(348);
if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
setState(350);
setState(349);
_la = _input.LA(1);
if ( !(_la==T__24 || _la==T__25) ) {
_errHandler.recoverInline(this);
@ -3026,14 +3024,14 @@ public class KickCParser extends Parser {
_errHandler.reportMatch(this);
consume();
}
setState(351);
setState(350);
asmExpr(7);
}
break;
}
}
}
setState(356);
setState(355);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,34,_ctx);
}
@ -3117,7 +3115,7 @@ public class KickCParser extends Parser {
}
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"+
"\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"+
@ -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"+
"\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"+
"\16\u0121\13\16\3\17\3\17\7\17\u0125\n\17\f\17\16\17\u0128\13\17\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"+
"\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"+
"\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"+
"\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\7\24\u0163\n\24\f\24\16\24\u0166\13\24"+
"\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"+
"\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"+
"\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"+
"\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"+
"\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"+
"\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"+
"\2\2 \u0131\3\2\2\2\"\u0133\3\2\2\2$\u014e\3\2\2\2&\u015a\3\2\2\2()\5"+
"\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\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"+
"\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"+
"\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"+
"=>\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"+
"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"+
"\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"+
"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"+
"\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"+
"\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"+
"\16\u0121\13\16\3\17\7\17\u0124\n\17\f\17\16\17\u0127\13\17\3\20\3\20"+
"\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"+
"\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\5\23\u014e\n\23\3\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\7\24\u0162\n\24\f\24\16\24\u0165\13\24\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\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\4\2\27\30"+
"$*\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\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"+
"\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"+
"\u00f1\3\2\2\2\32\u011a\3\2\2\2\34\u0125\3\2\2\2\36\u012a\3\2\2\2 \u0130"+
"\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"+
"\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"+
"\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"+
"\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"+
"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"+
"\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"+
"\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"+
"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\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"+
"\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"+
"[\\\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"+
"\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"+
@ -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"+
"\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"+
"\2\u0122\u0126\5\36\20\2\u0123\u0125\5\36\20\2\u0124\u0123\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"+
"\2\u0128\u0126\3\2\2\2\u0129\u012c\5 \21\2\u012a\u012c\5\"\22\2\u012b"+
"\u0129\3\2\2\2\u012b\u012a\3\2\2\2\u012c\37\3\2\2\2\u012d\u012e\7>\2\2"+
"\u012e\u0132\7\21\2\2\u012f\u0130\7\35\2\2\u0130\u0132\7\21\2\2\u0131"+
"\u012d\3\2\2\2\u0131\u012f\3\2\2\2\u0132!\3\2\2\2\u0133\u0135\7\60\2\2"+
"\u0134\u0136\5$\23\2\u0135\u0134\3\2\2\2\u0135\u0136\3\2\2\2\u0136#\3"+
"\2\2\2\u0137\u014f\5&\24\2\u0138\u0139\7/\2\2\u0139\u014f\5&\24\2\u013a"+
"\u013b\5&\24\2\u013b\u013c\7\23\2\2\u013c\u013d\7>\2\2\u013d\u014f\3\2"+
"\2\2\u013e\u013f\7\5\2\2\u013f\u0140\5&\24\2\u0140\u0141\7\6\2\2\u0141"+
"\u0142\7\23\2\2\u0142\u0143\7>\2\2\u0143\u014f\3\2\2\2\u0144\u0145\7\5"+
"\2\2\u0145\u0146\5&\24\2\u0146\u0147\7\23\2\2\u0147\u0148\7>\2\2\u0148"+
"\u0149\7\6\2\2\u0149\u014f\3\2\2\2\u014a\u014b\7\5\2\2\u014b\u014c\5&"+
"\24\2\u014c\u014d\7\6\2\2\u014d\u014f\3\2\2\2\u014e\u0137\3\2\2\2\u014e"+
"\u0138\3\2\2\2\u014e\u013a\3\2\2\2\u014e\u013e\3\2\2\2\u014e\u0144\3\2"+
"\2\2\u014e\u014a\3\2\2\2\u014f%\3\2\2\2\u0150\u0151\b\24\1\2\u0151\u0152"+
"\t\t\2\2\u0152\u015b\5&\24\n\u0153\u015b\7>\2\2\u0154\u015b\7?\2\2\u0155"+
"\u0156\7\3\2\2\u0156\u0157\7>\2\2\u0157\u015b\7\4\2\2\u0158\u015b\7\65"+
"\2\2\u0159\u015b\7\63\2\2\u015a\u0150\3\2\2\2\u015a\u0153\3\2\2\2\u015a"+
"\u0154\3\2\2\2\u015a\u0155\3\2\2\2\u015a\u0158\3\2\2\2\u015a\u0159\3\2"+
"\2\2\u015b\u0164\3\2\2\2\u015c\u015d\f\t\2\2\u015d\u015e\t\n\2\2\u015e"+
"\u0163\5&\24\n\u015f\u0160\f\b\2\2\u0160\u0161\t\7\2\2\u0161\u0163\5&"+
"\24\t\u0162\u015c\3\2\2\2\u0162\u015f\3\2\2\2\u0163\u0166\3\2\2\2\u0164"+
"\u0162\3\2\2\2\u0164\u0165\3\2\2\2\u0165\'\3\2\2\2\u0166\u0164\3\2\2\2"+
"%\61\65<AFL_rz\u0082\u0085\u008a\u0090\u0097\u009e\u00ac\u00af\u00b1\u00bb"+
"\u00c0\u00cc\u00d5\u00e0\u00f1\u0115\u0117\u011f\u0126\u012b\u0131\u0135"+
"\u014e\u015a\u0162\u0164";
"\2\u0122\u0124\5\36\20\2\u0123\u0122\3\2\2\2\u0124\u0127\3\2\2\2\u0125"+
"\u0123\3\2\2\2\u0125\u0126\3\2\2\2\u0126\35\3\2\2\2\u0127\u0125\3\2\2"+
"\2\u0128\u012b\5 \21\2\u0129\u012b\5\"\22\2\u012a\u0128\3\2\2\2\u012a"+
"\u0129\3\2\2\2\u012b\37\3\2\2\2\u012c\u012d\7>\2\2\u012d\u0131\7\21\2"+
"\2\u012e\u012f\7\35\2\2\u012f\u0131\7\21\2\2\u0130\u012c\3\2\2\2\u0130"+
"\u012e\3\2\2\2\u0131!\3\2\2\2\u0132\u0134\7\60\2\2\u0133\u0135\5$\23\2"+
"\u0134\u0133\3\2\2\2\u0134\u0135\3\2\2\2\u0135#\3\2\2\2\u0136\u014e\5"+
"&\24\2\u0137\u0138\7/\2\2\u0138\u014e\5&\24\2\u0139\u013a\5&\24\2\u013a"+
"\u013b\7\23\2\2\u013b\u013c\7>\2\2\u013c\u014e\3\2\2\2\u013d\u013e\7\5"+
"\2\2\u013e\u013f\5&\24\2\u013f\u0140\7\6\2\2\u0140\u0141\7\23\2\2\u0141"+
"\u0142\7>\2\2\u0142\u014e\3\2\2\2\u0143\u0144\7\5\2\2\u0144\u0145\5&\24"+
"\2\u0145\u0146\7\23\2\2\u0146\u0147\7>\2\2\u0147\u0148\7\6\2\2\u0148\u014e"+
"\3\2\2\2\u0149\u014a\7\5\2\2\u014a\u014b\5&\24\2\u014b\u014c\7\6\2\2\u014c"+
"\u014e\3\2\2\2\u014d\u0136\3\2\2\2\u014d\u0137\3\2\2\2\u014d\u0139\3\2"+
"\2\2\u014d\u013d\3\2\2\2\u014d\u0143\3\2\2\2\u014d\u0149\3\2\2\2\u014e"+
"%\3\2\2\2\u014f\u0150\b\24\1\2\u0150\u0151\t\t\2\2\u0151\u015a\5&\24\n"+
"\u0152\u015a\7>\2\2\u0153\u015a\7?\2\2\u0154\u0155\7\3\2\2\u0155\u0156"+
"\7>\2\2\u0156\u015a\7\4\2\2\u0157\u015a\7\65\2\2\u0158\u015a\7\63\2\2"+
"\u0159\u014f\3\2\2\2\u0159\u0152\3\2\2\2\u0159\u0153\3\2\2\2\u0159\u0154"+
"\3\2\2\2\u0159\u0157\3\2\2\2\u0159\u0158\3\2\2\2\u015a\u0163\3\2\2\2\u015b"+
"\u015c\f\t\2\2\u015c\u015d\t\n\2\2\u015d\u0162\5&\24\n\u015e\u015f\f\b"+
"\2\2\u015f\u0160\t\7\2\2\u0160\u0162\5&\24\t\u0161\u015b\3\2\2\2\u0161"+
"\u015e\3\2\2\2\u0162\u0165\3\2\2\2\u0163\u0161\3\2\2\2\u0163\u0164\3\2"+
"\2\2\u0164\'\3\2\2\2\u0165\u0163\3\2\2\2%\61\65<AFL_rz\u0082\u0085\u008a"+
"\u0090\u0097\u009e\u00ac\u00af\u00b1\u00bb\u00c0\u00cc\u00d5\u00e0\u00f1"+
"\u0115\u0117\u011f\u0125\u012a\u0130\u0134\u014d\u0159\u0161\u0163";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {

View File

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

View File

@ -1,12 +1,12 @@
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 java.util.*;
/**
* Find effective alive intervals for all variables in all statements. Add the intervals to the Program.
*/
public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
public Pass3LiveRangesEffectiveAnalysis(Program program) {
@ -19,17 +19,17 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
//getLog().append("Calculated effective variable live ranges");
}
private LiveRangeVariablesEffective findAliveEffective(Program program) {
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 (Statement statement : block.getStatements()) {
Collection<VariableRef> aliveEffective = findAliveEffective( liveRangeVariables, statement);
effectiveLiveVariables.put(statement.getIndex(), aliveEffective);
Collection<Collection<VariableRef>> statementAliveCombinations = findAliveEffective(liveRangeVariables, statement);
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
* @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
Collection<VariableRef> effectiveAlive = new LinkedHashSet<>();
effectiveAlive.addAll(liveRangeVariables.getAlive(statement));
Collection<VariableRef> effectiveAlive = liveRangeVariables.getAlive(statement);
// 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
ControlFlowBlock block = getProgram().getGraph().getBlockFromStatementIdx(statement.getIndex());
@ -57,16 +57,28 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
VariableReferenceInfo referenceInfo = new VariableReferenceInfo(getProgram());
Collection<VariableRef> referencedInProcedure = referenceInfo.getReferenced(procedure.getRef().getLabelRef());
for (CallGraph.CallBlock.Call caller : callers) {
// Each caller creates its own combinations
StatementCall callStatement =
(StatementCall) getProgram().getGraph().getStatementByIndex(caller.getCallStatementIdx());
Set<VariableRef> callAliveEffective = new LinkedHashSet<>(findAliveEffective(liveRangeVariables, callStatement));
// Clear out any variables referenced in the method
callAliveEffective.removeAll(referencedInProcedure);
effectiveAlive.addAll(callAliveEffective);
Collection<Collection<VariableRef>> callerCombinations = findAliveEffective(liveRangeVariables, callStatement);
for (Collection<VariableRef> callerCombination : callerCombinations) {
LinkedHashSet<VariableRef> combination = new LinkedHashSet<>();
// 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}.
*
* @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 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 program The program to test (used for accessing global data structures)
* @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 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)
*/
static void chooseBestUpliftCombination(
RegisterCombinationIterator combinationIterator, int maxCombinations,
@ -93,15 +93,15 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
* Attempt generate ASM with a specific register combination.
* The generation may result in failure if
* <ul>
* <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>some ASM fragments are missing </li>
* <li>the ALU register is used in a non-applicable way</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>some ASM fragments are missing </li>
* <li>the ALU register is used in a non-applicable way</li>
* </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 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
*/
public static boolean generateCombinationAsm(
@ -167,6 +167,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
* Programs that take less cycles to execute have lower scores.
* 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).
*
* @param program The program containing the ASM to check
* @return The score of the ASM
*/
@ -190,17 +191,17 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
return score;
}
/**
* Check the register allocation for whether a is register being allocated to two variables with overlapping live ranges
*
* @param program The program
* @return true if the register allocation contains an overlapping allocation. false otherwise.
*/
public static boolean isAllocationOverlapping(Program program) {
Pass2AliasElimination.Aliases aliases = Pass2AliasElimination.findAliasesCandidates(true, program);
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for (Statement statement : block.getStatements()) {
LinkedHashMap<Registers.Register, LiveRangeEquivalenceClass> usedRegisters = new LinkedHashMap<>();
if (isStatementAllocationOverlapping(program, statement, usedRegisters)) {
if (isStatementAllocationOverlapping(program, statement, aliases)) {
return true;
}
}
@ -211,32 +212,46 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
/**
* Determine if a statement has an overlapping register allocation
*
* @param program The program
* @param statement The statement to check
* @param program The program
* @param statement The statement to check
* @param usedRegisters The used registers. Will be extended with all registers used in the statement.
* @return true if there is an overlapping register allocation
*/
private static boolean isStatementAllocationOverlapping(
Program program,
Statement statement,
LinkedHashMap<Registers.Register, LiveRangeEquivalenceClass> usedRegisters) {
private static boolean isStatementAllocationOverlapping(Program program, Statement statement, Pass2AliasElimination.Aliases aliases) {
ProgramScope programScope = program.getScope();
Collection<VariableRef> alive = program.getLiveRangeVariablesEffective().getAliveEffective(statement);
for (VariableRef varRef : alive) {
Variable var = programScope.getVariable(varRef);
Registers.Register allocation = var.getAllocation();
LiveRangeEquivalenceClass allocationClass = usedRegisters.get(allocation);
if (allocationClass != null && !allocationClass.contains(varRef)) {
if (program.getLog().isVerboseUplift()) {
StringBuilder msg = new StringBuilder();
msg.append("Overlap register " + allocation + " in " + statement.toString(program));
program.getLog().append(msg.toString());
LiveRangeVariablesEffective.AliveCombinations aliveCombinations = program.getLiveRangeVariablesEffective().getAliveCombinations(statement);
for (LiveRangeVariablesEffective.AliveCombination aliveCombination : aliveCombinations.getCombinations()) {
LinkedHashMap<Registers.Register, LiveRangeEquivalenceClass> usedRegisters = new LinkedHashMap<>();
Collection<VariableRef> alive = aliveCombination.getAlive();
for (VariableRef varRef : alive) {
Variable var = programScope.getVariable(varRef);
Registers.Register allocation = var.getAllocation();
LiveRangeEquivalenceClass allocationClass = usedRegisters.get(allocation);
if (allocationClass != null && !allocationClass.contains(varRef)) {
// 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;
}

View File

@ -74,8 +74,15 @@ public class Pass4RegisterUpliftStatic extends Pass2Base {
setRegister(combination, "line::$7", Registers.getRegisterALU());
setRegister(combination, "initplottables::$6", Registers.getRegisterA());
setRegister(combination, "initplottables::$7", Registers.getRegisterALU());
*/
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(
combination,