1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-02-17 10:30:43 +00:00

Fixed infinite loop during optimization when aliase candidates end up with one single element.

This commit is contained in:
jespergravgaard 2018-10-17 23:00:54 +02:00
parent 0b4cb53d07
commit 5050452e23
7 changed files with 1264 additions and 9 deletions

View File

@ -1,12 +1,13 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.*;
import java.util.*;
@ -28,13 +29,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
removeAliasAssignments(aliases);
replaceVariables(aliases.getReplacements(getScope()));
for(AliasSet aliasSet : aliases.getAliasSets()) {
StringBuilder str = new StringBuilder();
str.append(aliasSet.getKeepVar(getScope()).toString(getProgram()));
str.append(" = ");
for(VariableRef var : aliasSet.getEliminateVars(getScope())) {
str.append(var.toString(getProgram()) + " ");
}
getLog().append("Alias " + str);
getLog().append("Alias " + aliasSet.toString(getProgram()));
}
deleteSymbols(aliases.getSymbolsToRemove(getScope()));
return (aliases.size() > 0);
@ -77,6 +72,14 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
}
}
}
ListIterator<AliasSet> aliasSetListIterator = candidates.getAliasSets().listIterator();
while(aliasSetListIterator.hasNext()) {
AliasSet aliasSet = aliasSetListIterator.next();
if(aliasSet.getVars().size() <= 1) {
program.getLog().append("Alias candidate removed " + aliasSet.toString(program));
aliasSetListIterator.remove();
}
}
}
/**
@ -324,6 +327,16 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
}
}
public String toString(Program program) {
StringBuilder str = new StringBuilder();
str.append(getKeepVar(program.getScope()).toString(program));
str.append(" = ");
for(VariableRef var : getEliminateVars(program.getScope())) {
str.append(var.toString(program)).append(" ");
}
return str.toString();
}
public List<VariableRef> getVars() {
return vars;
}

View File

@ -44,6 +44,11 @@ public class TestPrograms {
AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false);
}
@Test
public void testInfLoopError() throws IOException, URISyntaxException {
compileAndCompare("infloop-error");
}
@Test
public void testMinFastMul16() throws IOException, URISyntaxException {
compileAndCompare("min-fmul-16");

View File

@ -0,0 +1,19 @@
// Results in infinite compile loop as the compiler keeps trying to remove the same (empty) alias
byte* SCREEN = $400;
void main() {
byte min = $ff;
byte max = $0;
byte pos = 0;
while(true) {
pos++;
if(pos<min) {
min = pos;
}
if(pos>max) {
max = pos;
}
SCREEN[0] = min;
SCREEN[1] = max;
SCREEN[2] = pos;
}
}

View File

@ -0,0 +1,27 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
jsr main
main: {
ldy #0
ldx #$ff
tya
b2:
clc
adc #1
stx $ff
cmp $ff
bcs b4
tax
b4:
sta $ff
cpy $ff
bcs b5
tay
b5:
stx SCREEN
sty SCREEN+1
sta SCREEN+2
jmp b2
}

View File

@ -0,0 +1,37 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@1
@1: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main [ ] ( )
to:@end
@end: scope:[] from @1
[3] phi() [ ] ( )
main: scope:[main] from @1
[4] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main main::@5
[5] (byte) main::max#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@5/(byte) main::max#3 ) [ main::pos#2 main::min#2 main::max#2 ] ( main:2 [ main::pos#2 main::min#2 main::max#2 ] )
[5] (byte) main::min#2 ← phi( main/(byte/word/signed word/dword/signed dword) 255 main::@5/(byte) main::min#3 ) [ main::pos#2 main::min#2 main::max#2 ] ( main:2 [ main::pos#2 main::min#2 main::max#2 ] )
[5] (byte) main::pos#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@5/(byte) main::pos#1 ) [ main::pos#2 main::min#2 main::max#2 ] ( main:2 [ main::pos#2 main::min#2 main::max#2 ] )
to:main::@2
main::@2: scope:[main] from main::@1
[6] (byte) main::pos#1 ← ++ (byte) main::pos#2 [ main::min#2 main::max#2 main::pos#1 ] ( main:2 [ main::min#2 main::max#2 main::pos#1 ] )
[7] if((byte) main::pos#1>=(byte) main::min#2) goto main::@4 [ main::min#2 main::max#2 main::pos#1 ] ( main:2 [ main::min#2 main::max#2 main::pos#1 ] )
to:main::@8
main::@8: scope:[main] from main::@2
[8] (byte~) main::min#9 ← (byte) main::pos#1 [ main::max#2 main::pos#1 main::min#9 ] ( main:2 [ main::max#2 main::pos#1 main::min#9 ] )
to:main::@4
main::@4: scope:[main] from main::@2 main::@8
[9] (byte) main::min#3 ← phi( main::@2/(byte) main::min#2 main::@8/(byte~) main::min#9 ) [ main::max#2 main::pos#1 main::min#3 ] ( main:2 [ main::max#2 main::pos#1 main::min#3 ] )
[10] if((byte) main::pos#1<=(byte) main::max#2) goto main::@5 [ main::max#2 main::pos#1 main::min#3 ] ( main:2 [ main::max#2 main::pos#1 main::min#3 ] )
to:main::@9
main::@9: scope:[main] from main::@4
[11] (byte~) main::max#9 ← (byte) main::pos#1 [ main::pos#1 main::min#3 main::max#9 ] ( main:2 [ main::pos#1 main::min#3 main::max#9 ] )
to:main::@5
main::@5: scope:[main] from main::@4 main::@9
[12] (byte) main::max#3 ← phi( main::@4/(byte) main::max#2 main::@9/(byte~) main::max#9 ) [ main::pos#1 main::min#3 main::max#3 ] ( main:2 [ main::pos#1 main::min#3 main::max#3 ] )
[13] *((const byte*) SCREEN#0) ← (byte) main::min#3 [ main::pos#1 main::min#3 main::max#3 ] ( main:2 [ main::pos#1 main::min#3 main::max#3 ] )
[14] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) main::max#3 [ main::pos#1 main::min#3 main::max#3 ] ( main:2 [ main::pos#1 main::min#3 main::max#3 ] )
[15] *((const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) main::pos#1 [ main::pos#1 main::min#3 main::max#3 ] ( main:2 [ main::pos#1 main::min#3 main::max#3 ] )
to:main::@1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
(label) @1
(label) @begin
(label) @end
(byte*) SCREEN
(const byte*) SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) 1024
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@4
(label) main::@5
(label) main::@8
(label) main::@9
(byte) main::max
(byte) main::max#2 reg byte y 5.5
(byte) main::max#3 reg byte y 11.0
(byte~) main::max#9 reg byte y 22.0
(byte) main::min
(byte) main::min#2 reg byte x 11.0
(byte) main::min#3 reg byte x 6.285714285714286
(byte~) main::min#9 reg byte x 22.0
(byte) main::pos
(byte) main::pos#1 reg byte a 7.699999999999999
(byte) main::pos#2 reg byte a 22.0
reg byte a [ main::pos#2 main::pos#1 ]
reg byte x [ main::min#2 main::min#3 main::min#9 ]
reg byte y [ main::max#2 main::max#3 main::max#9 ]