1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-29 09:29:31 +00:00

Added test for loop loop invariant calculation hoisting optimization. #535

This commit is contained in:
jespergravgaard 2020-10-05 23:35:41 +02:00
parent 66d7c4ed51
commit 0a2e4189fe
6 changed files with 338 additions and 0 deletions

View File

@ -44,6 +44,11 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testStrengthReduction1() throws IOException, URISyntaxException {
compileAndCompare("strength-reduction-1.c");
}
@Test
public void testProblemBoolCompare2() throws IOException, URISyntaxException {
compileAndCompare("problem-bool-compare-2.c");

View File

@ -0,0 +1,10 @@
// Test loop invariant computation detection
// http://www.cs.toronto.edu/~pekhimenko/courses/cscd70-w18/docs/Lecture%205%20[LICM%20and%20Strength%20Reduction]%2002.08.2018.pdf
char * SCREEN = 0x0400;
void main() {
char x = *SCREEN;
for(char c=0;c<40;c++) {
// x+5 is a loop invariant computation
SCREEN[c] = x+5;
}
}

View File

@ -0,0 +1,28 @@
// Test loop invariant computation detection
// http://www.cs.toronto.edu/~pekhimenko/courses/cscd70-w18/docs/Lecture%205%20[LICM%20and%20Strength%20Reduction]%2002.08.2018.pdf
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
main: {
// x = *SCREEN
ldx SCREEN
ldy #0
__b1:
// for(char c=0;c<40;c++)
cpy #$28
bcc __b2
// }
rts
__b2:
// x+5
txa
clc
adc #5
// SCREEN[c] = x+5
// x+5 is a loop invariant computation
sta SCREEN,y
// for(char c=0;c<40;c++)
iny
jmp __b1
}

View File

@ -0,0 +1,17 @@
void main()
main: scope:[main] from
[0] main::x#0 = *SCREEN
to:main::@1
main::@1: scope:[main] from main main::@2
[1] main::c#2 = phi( main/0, main::@2/main::c#1 )
[2] if(main::c#2<$28) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[3] return
to:@return
main::@2: scope:[main] from main::@1
[4] main::$1 = main::x#0 + 5
[5] SCREEN[main::c#2] = main::$1
[6] main::c#1 = ++ main::c#2
to:main::@1

View File

@ -0,0 +1,266 @@
Inlined call call __init
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start::@1
main::x#0 = *SCREEN
main::c#0 = 0
to:main::@1
main::@1: scope:[main] from main main::@2
main::x#2 = phi( main/main::x#0, main::@2/main::x#1 )
main::c#2 = phi( main/main::c#0, main::@2/main::c#1 )
main::$0 = main::c#2 < $28
if(main::$0) goto main::@2
to:main::@return
main::@2: scope:[main] from main::@1
main::c#3 = phi( main::@1/main::c#2 )
main::x#1 = phi( main::@1/main::x#2 )
main::$1 = main::x#1 + 5
SCREEN[main::c#3] = main::$1
main::c#1 = ++ main::c#3
to:main::@1
main::@return: scope:[main] from main::@1
return
to:@return
void __start()
__start: scope:[__start] from
to:__start::__init1
__start::__init1: scope:[__start] from __start
to:__start::@1
__start::@1: scope:[__start] from __start::__init1
call main
to:__start::@2
__start::@2: scope:[__start] from __start::@1
to:__start::@return
__start::@return: scope:[__start] from __start::@2
return
to:@return
SYMBOL TABLE SSA
const byte* SCREEN = (byte*)$400
void __start()
void main()
bool~ main::$0
number~ main::$1
byte main::c
byte main::c#0
byte main::c#1
byte main::c#2
byte main::c#3
byte main::x
byte main::x#0
byte main::x#1
byte main::x#2
Adding number conversion cast (unumber) $28 in main::$0 = main::c#2 < $28
Adding number conversion cast (unumber) 5 in main::$1 = main::x#1 + 5
Adding number conversion cast (unumber) main::$1 in main::$1 = main::x#1 + (unumber)5
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast $28
Simplifying constant integer cast 5
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type $28
Finalized unsigned number type 5
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in main::$1 = main::x#1 + 5
Alias main::x#1 = main::x#2
Alias main::c#2 = main::c#3
Successful SSA optimization Pass2AliasElimination
Identical Phi Values main::x#1 main::x#0
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition main::$0 [4] if(main::c#2<$28) goto main::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant main::c#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::__init1
Removing unused procedure block __start::@1
Removing unused procedure block __start::@2
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Inlining constant with var siblings main::c#0
Constant inlined main::c#0 = 0
Successful SSA optimization Pass2ConstantInlining
CALL GRAPH
Created 1 initial phi equivalence classes
Coalesced [7] main::c#4 = main::c#1
Coalesced down to 1 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] main::x#0 = *SCREEN
to:main::@1
main::@1: scope:[main] from main main::@2
[1] main::c#2 = phi( main/0, main::@2/main::c#1 )
[2] if(main::c#2<$28) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[3] return
to:@return
main::@2: scope:[main] from main::@1
[4] main::$1 = main::x#0 + 5
[5] SCREEN[main::c#2] = main::$1
[6] main::c#1 = ++ main::c#2
to:main::@1
VARIABLE REGISTER WEIGHTS
void main()
byte~ main::$1 22.0
byte main::c
byte main::c#1 22.0
byte main::c#2 11.0
byte main::x
byte main::x#0 2.1666666666666665
Initial phi equivalence classes
[ main::c#2 main::c#1 ]
Added variable main::x#0 to live range equivalence class [ main::x#0 ]
Added variable main::$1 to live range equivalence class [ main::$1 ]
Complete equivalence classes
[ main::c#2 main::c#1 ]
[ main::x#0 ]
[ main::$1 ]
Allocated zp[1]:2 [ main::c#2 main::c#1 ]
Allocated zp[1]:3 [ main::x#0 ]
Allocated zp[1]:4 [ main::$1 ]
REGISTER UPLIFT POTENTIAL REGISTERS
Potential registers zp[1]:2 [ main::c#2 main::c#1 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:3 [ main::x#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:4 [ main::$1 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 33: zp[1]:2 [ main::c#2 main::c#1 ] 22: zp[1]:4 [ main::$1 ] 2.17: zp[1]:3 [ main::x#0 ]
Uplift Scope []
Uplifting [main] best 295 combination reg byte y [ main::c#2 main::c#1 ] reg byte a [ main::$1 ] reg byte x [ main::x#0 ]
Uplifting [] best 295 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test loop invariant computation detection
// http://www.cs.toronto.edu/~pekhimenko/courses/cscd70-w18/docs/Lecture%205%20[LICM%20and%20Strength%20Reduction]%2002.08.2018.pdf
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// main
main: {
// [0] main::x#0 = *SCREEN -- vbuxx=_deref_pbuc1
ldx SCREEN
// [1] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main:
// [1] phi main::c#2 = 0 [phi:main->main::@1#0] -- vbuyy=vbuc1
ldy #0
jmp __b1
// main::@1
__b1:
// [2] if(main::c#2<$28) goto main::@2 -- vbuyy_lt_vbuc1_then_la1
cpy #$28
bcc __b2
jmp __breturn
// main::@return
__breturn:
// [3] return
rts
// main::@2
__b2:
// [4] main::$1 = main::x#0 + 5 -- vbuaa=vbuxx_plus_vbuc1
txa
clc
adc #5
// [5] SCREEN[main::c#2] = main::$1 -- pbuc1_derefidx_vbuyy=vbuaa
// x+5 is a loop invariant computation
sta SCREEN,y
// [6] main::c#1 = ++ main::c#2 -- vbuyy=_inc_vbuyy
iny
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
__b1_from___b2:
// [1] phi main::c#2 = main::c#1 [phi:main::@2->main::@1#0] -- register_copy
jmp __b1
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b1_from_main:
Removing instruction __breturn:
Removing instruction __b1_from___b2:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
const byte* SCREEN = (byte*) 1024
void main()
byte~ main::$1 reg byte a 22.0
byte main::c
byte main::c#1 reg byte y 22.0
byte main::c#2 reg byte y 11.0
byte main::x
byte main::x#0 reg byte x 2.1666666666666665
reg byte y [ main::c#2 main::c#1 ]
reg byte x [ main::x#0 ]
reg byte a [ main::$1 ]
FINAL ASSEMBLER
Score: 235
// File Comments
// Test loop invariant computation detection
// http://www.cs.toronto.edu/~pekhimenko/courses/cscd70-w18/docs/Lecture%205%20[LICM%20and%20Strength%20Reduction]%2002.08.2018.pdf
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// main
main: {
// x = *SCREEN
// [0] main::x#0 = *SCREEN -- vbuxx=_deref_pbuc1
ldx SCREEN
// [1] phi from main to main::@1 [phi:main->main::@1]
// [1] phi main::c#2 = 0 [phi:main->main::@1#0] -- vbuyy=vbuc1
ldy #0
// main::@1
__b1:
// for(char c=0;c<40;c++)
// [2] if(main::c#2<$28) goto main::@2 -- vbuyy_lt_vbuc1_then_la1
cpy #$28
bcc __b2
// main::@return
// }
// [3] return
rts
// main::@2
__b2:
// x+5
// [4] main::$1 = main::x#0 + 5 -- vbuaa=vbuxx_plus_vbuc1
txa
clc
adc #5
// SCREEN[c] = x+5
// [5] SCREEN[main::c#2] = main::$1 -- pbuc1_derefidx_vbuyy=vbuaa
// x+5 is a loop invariant computation
sta SCREEN,y
// for(char c=0;c<40;c++)
// [6] main::c#1 = ++ main::c#2 -- vbuyy=_inc_vbuyy
iny
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
// [1] phi main::c#2 = main::c#1 [phi:main::@2->main::@1#0] -- register_copy
jmp __b1
}
// File Data

View File

@ -0,0 +1,12 @@
const byte* SCREEN = (byte*) 1024
void main()
byte~ main::$1 reg byte a 22.0
byte main::c
byte main::c#1 reg byte y 22.0
byte main::c#2 reg byte y 11.0
byte main::x
byte main::x#0 reg byte x 2.1666666666666665
reg byte y [ main::c#2 main::c#1 ]
reg byte x [ main::x#0 ]
reg byte a [ main::$1 ]