Moved handling of banked param/return to pass 1.

This commit is contained in:
jespergravgaard 2023-04-24 00:36:36 +02:00
parent 8193688eec
commit d4040e30a0
7 changed files with 79 additions and 54 deletions

View File

@ -224,6 +224,7 @@ public class Compiler {
new Pass1Procedures(program).execute();
new PassNTypeInference(program).execute();
new PassNFixIntermediateMemoryArea(program).execute();
new Pass1FixProcedureParamSegment(program).execute();
new PassNTypeIdSimplification(program).execute();
new Pass1StructTypeSizeFix(program).execute();
new Pass1PrintfIntrinsicRewrite(program).execute();

View File

@ -0,0 +1,46 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.Registers;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.Variable;
import java.util.Collection;
import java.util.List;
/**
* Ensure banked procedure parameters/return values in main memory are placed in the default data segment.
* This is needed to support banking, since it is otherwise impossible to access them across bank boundaries during calls.
*/
public class Pass1FixProcedureParamSegment extends Pass2SsaOptimization {
public Pass1FixProcedureParamSegment(Program program) {
super(program);
}
@Override
public boolean step() {
final Collection<Variable> allVariables = getScope().getAllVariables(true);
for(Variable variable : allVariables) {
if(variable.isKindLoadStore() || variable.isKindPhiMaster() || variable.isKindIntermediate()) {
if(variable.getRegister() instanceof Registers.RegisterMainMem registerMainMem && registerMainMem.isAddressHardcoded())
continue;
if(variable.getDataSegment().equals(Scope.SEGMENT_DATA_DEFAULT))
continue;
final Scope scope = variable.getScope();
if(scope instanceof Procedure procedure) {
if(!procedure.getBank().isCommon()) {
List<Variable> parameters = procedure.getParameters();
if(parameters.contains(variable) || variable.getLocalName().equals("return")) {
variable.setDataSegment(Scope.SEGMENT_DATA_DEFAULT);
getLog().append("Fixing banked procedure parameter/return value to default segment " + variable.getFullName());
}
}
}
}
}
return false;
}
}

View File

@ -583,30 +583,6 @@ public class Pass4CodeGeneration {
if (registerMainMem.getAddress() == null) {
// Generate into the data segment
// Set segment
// We check first the bank of the variable. Only local variables can be stored in the bank.
// Parameters must be stored in main memory.
if(!variable.getDataSegment().equals(Scope.SEGMENT_DATA_DEFAULT)) {
if(scope instanceof Procedure) {
Procedure procedure = (Procedure) scope;
List<Variable> parameters = procedure.getParameters();
if (variable.isKindPhiVersion()) {
Variable master = variable.getPhiMaster();
if (master != null) {
if (parameters.contains(master) || master.getLocalName().equals("return")) {
variable.setDataSegment(Scope.SEGMENT_DATA_DEFAULT);
}
}
}
}
}
// Intermediate variables are placed at the banked data segment, but parameters and return values are kept untouched.
if (variable.isKindIntermediate()) {
if (scope instanceof Procedure) {
Procedure procedure = (Procedure) scope;
variable.setDataSegment(procedure.getSegmentData());
}
}
setCurrentSegment(variable.getDataSegment(), asm);
// Add any comments
generateComments(asm, variable.getComments());

View File

@ -1583,7 +1583,7 @@ public class TestProgramsFast extends TestPrograms {
@Test
public void testBankedPhiMemvars() throws IOException {
compileAndCompare("call-banked-phi-memvars.c", log());
compileAndCompare("call-banked-phi-memvars.c");
}

View File

@ -93,8 +93,8 @@ main: {
iny
jmp __b1
.segment Data
.label __1 = plus.return
.label __3 = plus.return
.label __1 = plus.b
.label __3 = plus.b
}
.segment RAM_Bank1
// __mem() int plus(__mem() int a, __mem() int b)
@ -125,18 +125,18 @@ plus: {
adc a+1
sta r+1
// r += b
lda r
clc
adc b
lda return
adc r
sta return
lda r+1
adc b+1
lda return+1
adc r+1
sta return+1
// }
rts
.segment Data
b: .word 0
return: .word 0
.label return = b
.segment RAM_Bank1
r: .word 0
.segment Data

View File

@ -3,6 +3,9 @@ Updating intermediate variable memory area to MAIN_MEMORY main::$0
Updating intermediate variable memory area to MAIN_MEMORY main::$1
Updating intermediate variable memory area to MAIN_MEMORY main::$2
Updating intermediate variable memory area to MAIN_MEMORY main::$3
Fixing banked procedure parameter/return value to default segment plus::a
Fixing banked procedure parameter/return value to default segment plus::b
Fixing banked procedure parameter/return value to default segment plus::return
CONTROL FLOW GRAPH SSA
@ -359,11 +362,12 @@ Uplifting [plus] best 2226 combination mem[2] [ plus::r#1 ] mem[2] [ plus::r#2 ]
Uplifting [main] best 1866 combination reg byte y [ main::i#2 main::i#1 ] reg byte x [ main::$4 ] reg byte x [ main::$5 ] mem[2] [ main::$1 ] mem[2] [ main::$3 ] reg byte x [ main::$2 ]
Limited combination testing to 100 combinations of 144 possible.
Uplifting [] best 1866 combination
Coalescing zero page register [ mem[2] [ plus::b#2 plus::b#0 plus::b#1 ] ] with [ mem[2] [ plus::return#2 ] ] - score: 1
Coalescing zero page register [ mem[2] [ plus::return#0 ] ] with [ mem[2] [ main::$1 ] ] - score: 1
Coalescing zero page register [ mem[2] [ plus::return#0 main::$1 ] ] with [ mem[2] [ plus::return#2 ] ] - score: 1
Coalescing zero page register [ mem[2] [ plus::return#1 ] ] with [ mem[2] [ main::$3 ] ] - score: 1
Coalescing zero page register [ mem[2] [ plus::r#1 ] ] with [ mem[2] [ plus::r#2 ] ] - score: 1
Coalescing zero page register [ mem[2] [ plus::return#0 main::$1 plus::return#2 ] ] with [ mem[2] [ plus::return#1 main::$3 ] ] - score: 1
Coalescing zero page register [ mem[2] [ plus::b#2 plus::b#0 plus::b#1 plus::return#2 ] ] with [ mem[2] [ plus::return#0 main::$1 ] ] - score: 1
Coalescing zero page register [ mem[2] [ plus::b#2 plus::b#0 plus::b#1 plus::return#2 plus::return#0 main::$1 ] ] with [ mem[2] [ plus::return#1 main::$3 ] ] - score: 1
Coalescing zero page register [ mem[2] [ plus::r#1 plus::r#2 ] ] with [ mem[2] [ plus::r#3 ] ] - score: 1
ASSEMBLER BEFORE OPTIMIZATION
@ -498,8 +502,8 @@ main: {
// [1] phi main::i#2 = main::i#1 [phi:main::@4->main::@1#0] -- register_copy
jmp __b1
.segment Data
.label __1 = plus.return
.label __3 = plus.return
.label __1 = plus.b
.label __3 = plus.b
}
.segment RAM_Bank1
// plus
@ -530,13 +534,13 @@ plus: {
lda r+1
adc a+1
sta r+1
// [22] plus::return#2 = plus::r#3 + plus::b#2 -- vwsm1=vwsm2_plus_vwsm3
lda r
// [22] plus::return#2 = plus::r#3 + plus::b#2 -- vwsm1=vwsm2_plus_vwsm1
clc
adc b
lda return
adc r
sta return
lda r+1
adc b+1
lda return+1
adc r+1
sta return+1
jmp __breturn
// plus::@return
@ -545,7 +549,7 @@ plus: {
rts
.segment Data
b: .word 0
return: .word 0
.label return = b
.segment RAM_Bank1
r: .word 0
.segment Data
@ -599,8 +603,7 @@ int plus::return#2 // return mem[2] 30.75
reg byte y [ main::i#2 main::i#1 ]
mem[2] [ plus::a#2 ]
mem[2] [ plus::b#2 plus::b#0 plus::b#1 ]
mem[2] [ plus::return#0 main::$1 plus::return#2 plus::return#1 main::$3 ]
mem[2] [ plus::b#2 plus::b#0 plus::b#1 plus::return#2 plus::return#0 main::$1 plus::return#1 main::$3 ]
reg byte x [ main::$4 ]
reg byte x [ main::$2 ]
reg byte x [ main::$5 ]
@ -740,8 +743,8 @@ main: {
// [1] phi main::i#2 = main::i#1 [phi:main::@4->main::@1#0] -- register_copy
jmp __b1
.segment Data
.label __1 = plus.return
.label __3 = plus.return
.label __1 = plus.b
.label __3 = plus.b
}
.segment RAM_Bank1
// plus
@ -776,13 +779,13 @@ plus: {
adc a+1
sta r+1
// r += b
// [22] plus::return#2 = plus::r#3 + plus::b#2 -- vwsm1=vwsm2_plus_vwsm3
lda r
// [22] plus::return#2 = plus::r#3 + plus::b#2 -- vwsm1=vwsm2_plus_vwsm1
clc
adc b
lda return
adc r
sta return
lda r+1
adc b+1
lda return+1
adc r+1
sta return+1
// plus::@return
// }
@ -790,7 +793,7 @@ plus: {
rts
.segment Data
b: .word 0
return: .word 0
.label return = b
.segment RAM_Bank1
r: .word 0
.segment Data

View File

@ -26,8 +26,7 @@ int plus::return#2 // return mem[2] 30.75
reg byte y [ main::i#2 main::i#1 ]
mem[2] [ plus::a#2 ]
mem[2] [ plus::b#2 plus::b#0 plus::b#1 ]
mem[2] [ plus::return#0 main::$1 plus::return#2 plus::return#1 main::$3 ]
mem[2] [ plus::b#2 plus::b#0 plus::b#1 plus::return#2 plus::return#0 main::$1 plus::return#1 main::$3 ]
reg byte x [ main::$4 ]
reg byte x [ main::$2 ]
reg byte x [ main::$5 ]