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:
parent
0b4cb53d07
commit
5050452e23
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
19
src/test/kc/infloop-error.kc
Normal file
19
src/test/kc/infloop-error.kc
Normal 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;
|
||||
}
|
||||
}
|
27
src/test/ref/infloop-error.asm
Normal file
27
src/test/ref/infloop-error.asm
Normal 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
|
||||
}
|
37
src/test/ref/infloop-error.cfg
Normal file
37
src/test/ref/infloop-error.cfg
Normal 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
|
1127
src/test/ref/infloop-error.log
Normal file
1127
src/test/ref/infloop-error.log
Normal file
File diff suppressed because it is too large
Load Diff
27
src/test/ref/infloop-error.sym
Normal file
27
src/test/ref/infloop-error.sym
Normal 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 ]
|
Loading…
x
Reference in New Issue
Block a user