mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-06-03 07:29:37 +00:00
Ensured we do not coalesce across segments.
This commit is contained in:
parent
606ea29132
commit
11c86793d3
|
@ -583,30 +583,30 @@ public class Pass4CodeGeneration {
|
||||||
if (registerMainMem.getAddress() == null) {
|
if (registerMainMem.getAddress() == null) {
|
||||||
// Generate into the data segment
|
// Generate into the data segment
|
||||||
// Set segment
|
// Set segment
|
||||||
// // We check first the bank of the variable. Only local variables can be stored in the bank.
|
// We check first the bank of the variable. Only local variables can be stored in the bank.
|
||||||
// // Parameters must be stored in main memory.
|
// Parameters must be stored in main memory.
|
||||||
// if(!variable.getDataSegment().equals(Scope.SEGMENT_DATA_DEFAULT)) {
|
if(!variable.getDataSegment().equals(Scope.SEGMENT_DATA_DEFAULT)) {
|
||||||
// if(scope instanceof Procedure) {
|
if(scope instanceof Procedure) {
|
||||||
// Procedure procedure = (Procedure) scope;
|
Procedure procedure = (Procedure) scope;
|
||||||
// List<Variable> parameters = procedure.getParameters();
|
List<Variable> parameters = procedure.getParameters();
|
||||||
// if (variable.isKindPhiVersion()) {
|
if (variable.isKindPhiVersion()) {
|
||||||
// Variable master = variable.getPhiMaster();
|
Variable master = variable.getPhiMaster();
|
||||||
// if (master != null) {
|
if (master != null) {
|
||||||
// if (parameters.contains(master) || master.getLocalName().equals("return")) {
|
if (parameters.contains(master) || master.getLocalName().equals("return")) {
|
||||||
// variable.setDataSegment(Scope.SEGMENT_DATA_DEFAULT);
|
variable.setDataSegment(Scope.SEGMENT_DATA_DEFAULT);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// // Intermediate variables are placed at the banked data segment, but parameters and return values are kept untouched.
|
// Intermediate variables are placed at the banked data segment, but parameters and return values are kept untouched.
|
||||||
// if (variable.isKindIntermediate()) {
|
if (variable.isKindIntermediate()) {
|
||||||
// if (scope instanceof Procedure) {
|
if (scope instanceof Procedure) {
|
||||||
// Procedure procedure = (Procedure) scope;
|
Procedure procedure = (Procedure) scope;
|
||||||
// variable.setDataSegment(procedure.getSegmentData());
|
variable.setDataSegment(procedure.getSegmentData());
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
setCurrentSegment(variable.getDataSegment(), asm);
|
setCurrentSegment(variable.getDataSegment(), asm);
|
||||||
// Add any comments
|
// Add any comments
|
||||||
generateComments(asm, variable.getComments());
|
generateComments(asm, variable.getComments());
|
||||||
|
@ -925,7 +925,7 @@ public class Pass4CodeGeneration {
|
||||||
if(Bank.CallingDistance.NEAR.equals(callingDistance)) {
|
if(Bank.CallingDistance.NEAR.equals(callingDistance)) {
|
||||||
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program), program);
|
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program), program);
|
||||||
} else {
|
} else {
|
||||||
throw new CompileError("Call procedure not supported in banked mode " + toProcedure.toString(program));
|
throw new CompileError("Stack Call procedure not supported in banked mode " + toProcedure.toString(program));
|
||||||
}
|
}
|
||||||
RValue procedureRVal = call.getProcedureRVal();
|
RValue procedureRVal = call.getProcedureRVal();
|
||||||
if (!(procedureRVal instanceof ProcedureRef)) {
|
if (!(procedureRVal instanceof ProcedureRef)) {
|
||||||
|
|
|
@ -53,6 +53,7 @@ public abstract class Pass4MemoryCoalesce extends Pass2Base {
|
||||||
return
|
return
|
||||||
canCoalesceNotEqual(ec1, ec2) &&
|
canCoalesceNotEqual(ec1, ec2) &&
|
||||||
canCoalesceCompatible(ec1, ec2, program) &&
|
canCoalesceCompatible(ec1, ec2, program) &&
|
||||||
|
canCoalesceSegments(ec1, ec2, program) &&
|
||||||
canCoalesceVolatile(ec1, ec2, program) &&
|
canCoalesceVolatile(ec1, ec2, program) &&
|
||||||
canCoalesceThreads(ec1, ec2, threadHeads, program) &&
|
canCoalesceThreads(ec1, ec2, threadHeads, program) &&
|
||||||
canCoalesceClobber(ec1, ec2, unknownFragments, program);
|
canCoalesceClobber(ec1, ec2, unknownFragments, program);
|
||||||
|
@ -69,6 +70,21 @@ public abstract class Pass4MemoryCoalesce extends Pass2Base {
|
||||||
return !ec1.equals(ec2);
|
return !ec1.equals(ec2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if two live range equivalence classes are candidates for coalescing by ensuring they are not from different data segments.
|
||||||
|
* @param ec1 One equivalence class
|
||||||
|
* @param ec2 Another equivalence class
|
||||||
|
* @param program The program
|
||||||
|
* @return True if the two equivalence classes can be coalesced into one without problems.
|
||||||
|
*/
|
||||||
|
private static boolean canCoalesceSegments(LiveRangeEquivalenceClass ec1, LiveRangeEquivalenceClass ec2, Program program) {
|
||||||
|
final VariableRef variableRef1 = ec1.getVariables().get(0);
|
||||||
|
final String dataSegment1 = program.getScope().getVar(variableRef1).getDataSegment();
|
||||||
|
final VariableRef variableRef2 = ec2.getVariables().get(0);
|
||||||
|
final String dataSegment2 = program.getScope().getVar(variableRef2).getDataSegment();
|
||||||
|
return dataSegment1.equals(dataSegment2);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if two live range equivalence classes can be coalesced without cross-thread clobber.
|
* Determines if two live range equivalence classes can be coalesced without cross-thread clobber.
|
||||||
* This is possible if they are both only called from the same thread head.
|
* This is possible if they are both only called from the same thread head.
|
||||||
|
|
|
@ -1581,6 +1581,12 @@ public class TestProgramsFast extends TestPrograms {
|
||||||
compileAndCompare("call-banked-phi-case-6-close-1.c");
|
compileAndCompare("call-banked-phi-case-6-close-1.c");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBankedPhiMemvars() throws IOException {
|
||||||
|
compileAndCompare("call-banked-phi-memvars.c", log());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBankedStackCase2Close0() throws IOException {
|
public void testBankedStackCase2Close0() throws IOException {
|
||||||
assertError("call-banked-stack-case-2-close-0.c", "Stack Call procedure not supported in banked mode");
|
assertError("call-banked-stack-case-2-close-0.c", "Stack Call procedure not supported in banked mode");
|
||||||
|
|
30
src/test/kc/call-banked-phi-memvars.c
Normal file
30
src/test/kc/call-banked-phi-memvars.c
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/**
|
||||||
|
* Test banked calls with memory variables.
|
||||||
|
* The parameters & return should end up in the shared/common bank.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma link("call-banked-phi.ld")
|
||||||
|
#pragma var_model(mem)
|
||||||
|
|
||||||
|
int* const SCREEN = (int*)0x0400;
|
||||||
|
|
||||||
|
#pragma code_seg(Code)
|
||||||
|
#pragma nobank
|
||||||
|
void main(void) {
|
||||||
|
for(char i=0;i<5; i++) {
|
||||||
|
SCREEN[i] = plus(100, (int)i);
|
||||||
|
SCREEN[10+i] = plus(200, (int)i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma code_seg(RAM_Bank1)
|
||||||
|
#pragma data_seg(RAM_Bank1)
|
||||||
|
#pragma bank(cx16_ram, 1)
|
||||||
|
int plus(int a, int b) {
|
||||||
|
int r = 2;
|
||||||
|
r += a;
|
||||||
|
r += b;
|
||||||
|
r += a;
|
||||||
|
r += b;
|
||||||
|
return r;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user