diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index f71521d3c..d7d239728 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -1175,15 +1175,12 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor comments = ensureUnusedComments(getCommentsSymbol(ctx)); - if(elseStmt == null) { // If without else - skip the entire section if condition not met SymbolVariableRef notExprVar = getCurrentScope().addVariableIntermediate().getRef(); sequence.addStatement(new StatementAssignment((LValue) notExprVar, null, Operators.LOGIC_NOT, rValue, true, StatementSource.ifThen(ctx), comments)); - PrePostModifierHandler.addPostModifiers(this, ctx.commaExpr(), StatementSource.ifThen(ctx)); Label endJumpLabel = getCurrentScope().addLabelIntermediate(); sequence.addStatement(new StatementConditionalJump(notExprVar, endJumpLabel.getRef(), StatementSource.ifThen(ctx), Comment.NO_COMMENTS)); this.visit(ifStmt); @@ -1191,7 +1188,6 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor comments = ensureUnusedComments(getCommentsSymbol(ctx)); StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef(), StatementSource.whileDo(ctx), comments); sequence.addStatement(beginJumpTarget); - PrePostModifierHandler.addPreModifiers(this, ctx.commaExpr(), StatementSource.whileDo(ctx)); - RValue rValue = (RValue) this.visit(ctx.commaExpr()); - PrePostModifierHandler.addPostModifiers(this, ctx.commaExpr(), StatementSource.whileDo(ctx)); + RValue rValue = addCondition(ctx.commaExpr(), StatementSource.whileDo(ctx)); StatementConditionalJump doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel.getRef(), StatementSource.whileDo(ctx), Comment.NO_COMMENTS); sequence.addStatement(doJmpStmt); Statement endJmpStmt = new StatementJump(endJumpLabel.getRef(), StatementSource.whileDo(ctx), Comment.NO_COMMENTS); @@ -1293,6 +1287,31 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor comments = ensureUnusedComments(getCommentsSymbol(ctx)); // TODO: Add comments to next stmt // Evaluate the switch-expression - PrePostModifierHandler.addPreModifiers(this, ctx.commaExpr(), StatementSource.switchExpr(ctx)); - RValue eValue = (RValue) this.visit(ctx.commaExpr()); - PrePostModifierHandler.addPostModifiers(this, ctx.commaExpr(), StatementSource.switchExpr(ctx)); + RValue eValue = addCondition(ctx.commaExpr(), StatementSource.switchExpr(ctx)); // Add case conditional jumps List caseBodies = new ArrayList<>(); for(KickCParser.SwitchCaseContext caseContext : ctx.switchCases().switchCase()) { @@ -1409,10 +1424,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor= (const nomodify byte) PLAYFIELD_LINES Inversing boolean not [842] (bool~) play_collision::$7 ← (byte~) play_collision::$5 == (byte) 0 from [841] (bool~) play_collision::$6 ← (byte~) play_collision::$5 != (byte) 0 Inversing boolean not [850] (bool~) play_collision::$9 ← (byte) play_collision::xp#4 < (const nomodify byte) PLAYFIELD_COLS from [849] (bool~) play_collision::$8 ← (byte) play_collision::xp#4 >= (const nomodify byte) PLAYFIELD_COLS Inversing boolean not [855] (bool~) play_collision::$11 ← *((byte*) play_collision::playfield_line#1 + (byte) play_collision::xp#5) == (byte) 0 from [854] (bool~) play_collision::$10 ← *((byte*) play_collision::playfield_line#1 + (byte) play_collision::xp#5) != (byte) 0 -Inversing boolean not [876] (bool~) play_lock_current::$1 ← *((byte*) current_piece_gfx#22 + (byte) play_lock_current::i#2) == (byte) 0 from [875] (bool~) play_lock_current::$0 ← *((byte*) current_piece_gfx#22 + (byte) play_lock_current::i#2) != (byte) 0 +Inversing boolean not [877] (bool~) play_lock_current::$1 ← *((byte*) current_piece_gfx#22 + (byte) play_lock_current::i#2) == (byte) 0 from [875] (bool~) play_lock_current::$0 ← *((byte*) current_piece_gfx#22 + (byte) play_lock_current::i#2) != (byte) 0 Inversing boolean not [910] (bool~) play_spawn_current::$3 ← (byte~) play_spawn_current::$1 != (const nomodify byte) COLLISION_PLAYFIELD from [909] (bool~) play_spawn_current::$2 ← (byte~) play_spawn_current::$1 == (const nomodify byte) COLLISION_PLAYFIELD Inversing boolean not [950] (bool~) play_remove_lines::$1 ← (byte) play_remove_lines::c#0 != (byte) 0 from [949] (bool~) play_remove_lines::$0 ← (byte) play_remove_lines::c#0 == (byte) 0 Inversing boolean not [962] (bool~) play_remove_lines::$4 ← (byte) play_remove_lines::full#2 != (byte) 1 from [961] (bool~) play_remove_lines::$3 ← (byte) play_remove_lines::full#2 == (byte) 1 diff --git a/src/test/ref/post-increment-problem.asm b/src/test/ref/post-increment-problem.asm index 08dbd6300..041e1b332 100644 --- a/src/test/ref/post-increment-problem.asm +++ b/src/test/ref/post-increment-problem.asm @@ -12,12 +12,12 @@ main: { // Error! The post-increment in the following loop is turned into a pre-increment by the compiler. __b1: // while(*msg++) + ldy #0 + lda (msg),y inc.z msg bne !+ inc.z msg+1 !: - ldy #0 - lda (msg),y cmp #0 bne __b1 // *--msg = 'x'; diff --git a/src/test/ref/post-increment-problem.cfg b/src/test/ref/post-increment-problem.cfg index 53aeed5e1..0f846f3fb 100644 --- a/src/test/ref/post-increment-problem.cfg +++ b/src/test/ref/post-increment-problem.cfg @@ -14,23 +14,24 @@ main: scope:[main] from @1 to:main::@1 main::@1: scope:[main] from main main::@1 [5] (byte*) main::msg#4 ← phi( main/(const byte*) MESSAGE main::@1/(byte*) main::msg#1 ) - [6] (byte*) main::msg#1 ← ++ (byte*) main::msg#4 - [7] if((byte) 0!=*((byte*) main::msg#1)) goto main::@1 + [6] (byte~) main::$0 ← *((byte*) main::msg#4) + [7] (byte*) main::msg#1 ← ++ (byte*) main::msg#4 + [8] if((byte) 0!=(byte~) main::$0) goto main::@1 to:main::@2 main::@2: scope:[main] from main::@1 - [8] (byte*) main::msg#2 ← -- (byte*) main::msg#1 - [9] *((byte*) main::msg#2) ← (byte) 'x' - [10] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 - [11] *((byte*) main::msg#3) ← (byte) 0 + [9] (byte*) main::msg#2 ← -- (byte*) main::msg#1 + [10] *((byte*) main::msg#2) ← (byte) 'x' + [11] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 + [12] *((byte*) main::msg#3) ← (byte) 0 to:main::@3 main::@3: scope:[main] from main::@2 main::@4 - [12] (byte) main::i#2 ← phi( main::@2/(byte) 0 main::@4/(byte) main::i#1 ) - [13] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 + [13] (byte) main::i#2 ← phi( main::@2/(byte) 0 main::@4/(byte) main::i#1 ) + [14] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 to:main::@return main::@return: scope:[main] from main::@3 - [14] return + [15] return to:@return main::@4: scope:[main] from main::@3 - [15] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) - [16] (byte) main::i#1 ← ++ (byte) main::i#2 + [16] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) + [17] (byte) main::i#1 ← ++ (byte) main::i#2 to:main::@3 diff --git a/src/test/ref/post-increment-problem.log b/src/test/ref/post-increment-problem.log index b84d58d09..608db030a 100644 --- a/src/test/ref/post-increment-problem.log +++ b/src/test/ref/post-increment-problem.log @@ -1,4 +1,4 @@ -Warning! Adding boolean cast to non-boolean condition *((byte*) main::msg) +Warning! Adding boolean cast to non-boolean condition (byte~) main::$0 Warning! Adding boolean cast to non-boolean condition *((const byte*) MESSAGE + (byte) main::i) Culled Empty Block (label) main::@2 Culled Empty Block (label) main::@4 @@ -19,9 +19,10 @@ main: scope:[main] from @1 to:main::@1 main::@1: scope:[main] from main main::@1 (byte*) main::msg#4 ← phi( main/(byte*) main::msg#0 main::@1/(byte*) main::msg#1 ) + (byte~) main::$0 ← *((byte*) main::msg#4) (byte*) main::msg#1 ← ++ (byte*) main::msg#4 - (bool~) main::$0 ← (number) 0 != *((byte*) main::msg#1) - if((bool~) main::$0) goto main::@1 + (bool~) main::$1 ← (number) 0 != (byte~) main::$0 + if((bool~) main::$1) goto main::@1 to:main::@3 main::@3: scope:[main] from main::@1 (byte*) main::msg#5 ← phi( main::@1/(byte*) main::msg#1 ) @@ -33,8 +34,8 @@ main::@3: scope:[main] from main::@1 to:main::@7 main::@7: scope:[main] from main::@3 main::@8 (byte) main::i#2 ← phi( main::@3/(byte) main::i#0 main::@8/(byte) main::i#1 ) - (bool~) main::$1 ← (number) 0 != *((const byte*) MESSAGE + (byte) main::i#2) - if((bool~) main::$1) goto main::@8 + (bool~) main::$2 ← (number) 0 != *((const byte*) MESSAGE + (byte) main::i#2) + if((bool~) main::$2) goto main::@8 to:main::@return main::@8: scope:[main] from main::@7 (byte) main::i#3 ← phi( main::@7/(byte) main::i#2 ) @@ -59,8 +60,9 @@ SYMBOL TABLE SSA (const byte*) MESSAGE[(number) $14] = (byte*) "camelot" (const nomodify byte*) SCREEN = (byte*)(number) $400 (void()) main() -(bool~) main::$0 +(byte~) main::$0 (bool~) main::$1 +(bool~) main::$2 (label) main::@1 (label) main::@3 (label) main::@7 @@ -79,9 +81,9 @@ SYMBOL TABLE SSA (byte*) main::msg#4 (byte*) main::msg#5 -Adding number conversion cast (unumber) 0 in (bool~) main::$0 ← (number) 0 != *((byte*) main::msg#1) +Adding number conversion cast (unumber) 0 in (bool~) main::$1 ← (number) 0 != (byte~) main::$0 Adding number conversion cast (unumber) 0 in *((byte*) main::msg#3) ← (number) 0 -Adding number conversion cast (unumber) 0 in (bool~) main::$1 ← (number) 0 != *((const byte*) MESSAGE + (byte) main::i#2) +Adding number conversion cast (unumber) 0 in (bool~) main::$2 ← (number) 0 != *((const byte*) MESSAGE + (byte) main::i#2) Successful SSA optimization PassNAddNumberTypeConversions Inlining cast *((byte*) main::msg#3) ← (unumber)(number) 0 Successful SSA optimization Pass2InlineCast @@ -97,8 +99,8 @@ Successful SSA optimization PassNFinalizeNumberTypeConversions Alias main::msg#1 = main::msg#5 Alias main::i#2 = main::i#3 Successful SSA optimization Pass2AliasElimination -Simple Condition (bool~) main::$0 [4] if((byte) 0!=*((byte*) main::msg#1)) goto main::@1 -Simple Condition (bool~) main::$1 [12] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@8 +Simple Condition (bool~) main::$1 [5] if((byte) 0!=(byte~) main::$0) goto main::@1 +Simple Condition (bool~) main::$2 [13] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@8 Successful SSA optimization Pass2ConditionalJumpSimplification Constant (const byte*) main::msg#0 = MESSAGE Constant (const byte) main::i#0 = 0 @@ -118,8 +120,8 @@ CALL GRAPH Calls in [] to main:2 Created 2 initial phi equivalence classes -Coalesced [18] main::i#4 ← main::i#1 -Coalesced [19] main::msg#6 ← main::msg#1 +Coalesced [19] main::i#4 ← main::i#1 +Coalesced [20] main::msg#6 ← main::msg#1 Coalesced down to 2 phi equivalence classes Culled Empty Block (label) @2 Culled Empty Block (label) main::@13 @@ -148,53 +150,58 @@ main: scope:[main] from @1 to:main::@1 main::@1: scope:[main] from main main::@1 [5] (byte*) main::msg#4 ← phi( main/(const byte*) MESSAGE main::@1/(byte*) main::msg#1 ) - [6] (byte*) main::msg#1 ← ++ (byte*) main::msg#4 - [7] if((byte) 0!=*((byte*) main::msg#1)) goto main::@1 + [6] (byte~) main::$0 ← *((byte*) main::msg#4) + [7] (byte*) main::msg#1 ← ++ (byte*) main::msg#4 + [8] if((byte) 0!=(byte~) main::$0) goto main::@1 to:main::@2 main::@2: scope:[main] from main::@1 - [8] (byte*) main::msg#2 ← -- (byte*) main::msg#1 - [9] *((byte*) main::msg#2) ← (byte) 'x' - [10] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 - [11] *((byte*) main::msg#3) ← (byte) 0 + [9] (byte*) main::msg#2 ← -- (byte*) main::msg#1 + [10] *((byte*) main::msg#2) ← (byte) 'x' + [11] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 + [12] *((byte*) main::msg#3) ← (byte) 0 to:main::@3 main::@3: scope:[main] from main::@2 main::@4 - [12] (byte) main::i#2 ← phi( main::@2/(byte) 0 main::@4/(byte) main::i#1 ) - [13] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 + [13] (byte) main::i#2 ← phi( main::@2/(byte) 0 main::@4/(byte) main::i#1 ) + [14] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 to:main::@return main::@return: scope:[main] from main::@3 - [14] return + [15] return to:@return main::@4: scope:[main] from main::@3 - [15] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) - [16] (byte) main::i#1 ← ++ (byte) main::i#2 + [16] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) + [17] (byte) main::i#1 ← ++ (byte) main::i#2 to:main::@3 VARIABLE REGISTER WEIGHTS (void()) main() +(byte~) main::$0 101.0 (byte) main::i (byte) main::i#1 202.0 (byte) main::i#2 168.33333333333331 (byte*) main::msg -(byte*) main::msg#1 157.0 +(byte*) main::msg#1 106.5 (byte*) main::msg#2 16.5 (byte*) main::msg#3 22.0 -(byte*) main::msg#4 202.0 +(byte*) main::msg#4 151.5 Initial phi equivalence classes [ main::msg#4 main::msg#1 ] [ main::i#2 main::i#1 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] Added variable main::msg#2 to live range equivalence class [ main::msg#2 ] Added variable main::msg#3 to live range equivalence class [ main::msg#3 ] Complete equivalence classes [ main::msg#4 main::msg#1 ] [ main::i#2 main::i#1 ] +[ main::$0 ] [ main::msg#2 ] [ main::msg#3 ] Allocated zp[2]:2 [ main::msg#4 main::msg#1 ] Allocated zp[1]:4 [ main::i#2 main::i#1 ] -Allocated zp[2]:5 [ main::msg#2 ] -Allocated zp[2]:7 [ main::msg#3 ] +Allocated zp[1]:5 [ main::$0 ] +Allocated zp[2]:6 [ main::msg#2 ] +Allocated zp[2]:8 [ main::msg#3 ] INITIAL ASM Target platform is c64basic / MOS6502X @@ -224,9 +231,10 @@ __bend_from___b1: __bend: // main main: { + .label __0 = 5 .label msg = 2 - .label msg_1 = 5 - .label msg_2 = 7 + .label msg_1 = 6 + .label msg_2 = 8 // Print the resulting message - should be "camelotx" - but the error causes it to be "camelox" .label i = 4 // [5] phi from main to main::@1 [phi:main->main::@1] @@ -244,20 +252,23 @@ main: { jmp __b1 // main::@1 __b1: - // [6] (byte*) main::msg#1 ← ++ (byte*) main::msg#4 -- pbuz1=_inc_pbuz1 + // [6] (byte~) main::$0 ← *((byte*) main::msg#4) -- vbuz1=_deref_pbuz2 + ldy #0 + lda (msg),y + sta.z __0 + // [7] (byte*) main::msg#1 ← ++ (byte*) main::msg#4 -- pbuz1=_inc_pbuz1 inc.z msg bne !+ inc.z msg+1 !: - // [7] if((byte) 0!=*((byte*) main::msg#1)) goto main::@1 -- vbuc1_neq__deref_pbuz1_then_la1 - ldy #0 - lda (msg),y - cmp #0 + // [8] if((byte) 0!=(byte~) main::$0) goto main::@1 -- vbuc1_neq_vbuz1_then_la1 + lda #0 + cmp.z __0 bne __b1_from___b1 jmp __b2 // main::@2 __b2: - // [8] (byte*) main::msg#2 ← -- (byte*) main::msg#1 -- pbuz1=_dec_pbuz2 + // [9] (byte*) main::msg#2 ← -- (byte*) main::msg#1 -- pbuz1=_dec_pbuz2 lda.z msg sec sbc #1 @@ -265,12 +276,12 @@ main: { lda.z msg+1 sbc #0 sta.z msg_1+1 - // [9] *((byte*) main::msg#2) ← (byte) 'x' -- _deref_pbuz1=vbuc1 + // [10] *((byte*) main::msg#2) ← (byte) 'x' -- _deref_pbuz1=vbuc1 // Now msg should point right after the zero, since the post increment was executed in the last condition that evaluated to zero. lda #'x' ldy #0 sta (msg_1),y - // [10] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz2 + // [11] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz2 lda.z msg_1 clc adc #1 @@ -278,19 +289,19 @@ main: { lda.z msg_1+1 adc #0 sta.z msg_2+1 - // [11] *((byte*) main::msg#3) ← (byte) 0 -- _deref_pbuz1=vbuc1 + // [12] *((byte*) main::msg#3) ← (byte) 0 -- _deref_pbuz1=vbuc1 lda #0 ldy #0 sta (msg_2),y - // [12] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + // [13] phi from main::@2 to main::@3 [phi:main::@2->main::@3] __b3_from___b2: - // [12] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuz1=vbuc1 + // [13] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuz1=vbuc1 lda #0 sta.z i jmp __b3 // main::@3 __b3: - // [13] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 -- vbuc1_neq_pbuc2_derefidx_vbuz1_then_la1 + // [14] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 -- vbuc1_neq_pbuc2_derefidx_vbuz1_then_la1 lda #0 ldy.z i cmp MESSAGE,y @@ -298,19 +309,19 @@ main: { jmp __breturn // main::@return __breturn: - // [14] return + // [15] return rts // main::@4 __b4: - // [15] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz1 + // [16] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz1 ldy.z i lda MESSAGE,y sta SCREEN,y - // [16] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 + // [17] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc.z i - // [12] phi from main::@4 to main::@3 [phi:main::@4->main::@3] + // [13] phi from main::@4 to main::@3 [phi:main::@4->main::@3] __b3_from___b4: - // [12] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy + // [13] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy jmp __b3 } // File Data @@ -319,34 +330,35 @@ main: { .fill $c, 0 REGISTER UPLIFT POTENTIAL REGISTERS -Statement [7] if((byte) 0!=*((byte*) main::msg#1)) goto main::@1 [ main::msg#1 ] ( main:2 [ main::msg#1 ] { } ) always clobbers reg byte a reg byte y -Statement [8] (byte*) main::msg#2 ← -- (byte*) main::msg#1 [ main::msg#2 ] ( main:2 [ main::msg#2 ] { } ) always clobbers reg byte a -Statement [9] *((byte*) main::msg#2) ← (byte) 'x' [ main::msg#2 ] ( main:2 [ main::msg#2 ] { } ) always clobbers reg byte a reg byte y -Statement [10] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 [ main::msg#3 ] ( main:2 [ main::msg#3 ] { } ) always clobbers reg byte a -Statement [11] *((byte*) main::msg#3) ← (byte) 0 [ ] ( main:2 [ ] { } ) always clobbers reg byte a reg byte y -Statement [13] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 [ main::i#2 ] ( main:2 [ main::i#2 ] { } ) always clobbers reg byte a +Statement [6] (byte~) main::$0 ← *((byte*) main::msg#4) [ main::msg#4 main::$0 ] ( main:2 [ main::msg#4 main::$0 ] { } ) always clobbers reg byte a reg byte y +Statement [9] (byte*) main::msg#2 ← -- (byte*) main::msg#1 [ main::msg#2 ] ( main:2 [ main::msg#2 ] { } ) always clobbers reg byte a +Statement [10] *((byte*) main::msg#2) ← (byte) 'x' [ main::msg#2 ] ( main:2 [ main::msg#2 ] { } ) always clobbers reg byte a reg byte y +Statement [11] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 [ main::msg#3 ] ( main:2 [ main::msg#3 ] { } ) always clobbers reg byte a +Statement [12] *((byte*) main::msg#3) ← (byte) 0 [ ] ( main:2 [ ] { } ) always clobbers reg byte a reg byte y +Statement [14] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 [ main::i#2 ] ( main:2 [ main::i#2 ] { } ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:4 [ main::i#2 main::i#1 ] -Statement [15] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) [ main::i#2 ] ( main:2 [ main::i#2 ] { } ) always clobbers reg byte a -Statement [7] if((byte) 0!=*((byte*) main::msg#1)) goto main::@1 [ main::msg#1 ] ( main:2 [ main::msg#1 ] { } ) always clobbers reg byte a reg byte y -Statement [8] (byte*) main::msg#2 ← -- (byte*) main::msg#1 [ main::msg#2 ] ( main:2 [ main::msg#2 ] { } ) always clobbers reg byte a -Statement [9] *((byte*) main::msg#2) ← (byte) 'x' [ main::msg#2 ] ( main:2 [ main::msg#2 ] { } ) always clobbers reg byte a reg byte y -Statement [10] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 [ main::msg#3 ] ( main:2 [ main::msg#3 ] { } ) always clobbers reg byte a -Statement [11] *((byte*) main::msg#3) ← (byte) 0 [ ] ( main:2 [ ] { } ) always clobbers reg byte a reg byte y -Statement [13] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 [ main::i#2 ] ( main:2 [ main::i#2 ] { } ) always clobbers reg byte a -Statement [15] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) [ main::i#2 ] ( main:2 [ main::i#2 ] { } ) always clobbers reg byte a +Statement [16] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) [ main::i#2 ] ( main:2 [ main::i#2 ] { } ) always clobbers reg byte a +Statement [6] (byte~) main::$0 ← *((byte*) main::msg#4) [ main::msg#4 main::$0 ] ( main:2 [ main::msg#4 main::$0 ] { } ) always clobbers reg byte a reg byte y +Statement [9] (byte*) main::msg#2 ← -- (byte*) main::msg#1 [ main::msg#2 ] ( main:2 [ main::msg#2 ] { } ) always clobbers reg byte a +Statement [10] *((byte*) main::msg#2) ← (byte) 'x' [ main::msg#2 ] ( main:2 [ main::msg#2 ] { } ) always clobbers reg byte a reg byte y +Statement [11] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 [ main::msg#3 ] ( main:2 [ main::msg#3 ] { } ) always clobbers reg byte a +Statement [12] *((byte*) main::msg#3) ← (byte) 0 [ ] ( main:2 [ ] { } ) always clobbers reg byte a reg byte y +Statement [14] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 [ main::i#2 ] ( main:2 [ main::i#2 ] { } ) always clobbers reg byte a +Statement [16] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) [ main::i#2 ] ( main:2 [ main::i#2 ] { } ) always clobbers reg byte a Potential registers zp[2]:2 [ main::msg#4 main::msg#1 ] : zp[2]:2 , Potential registers zp[1]:4 [ main::i#2 main::i#1 ] : zp[1]:4 , reg byte x , reg byte y , -Potential registers zp[2]:5 [ main::msg#2 ] : zp[2]:5 , -Potential registers zp[2]:7 [ main::msg#3 ] : zp[2]:7 , +Potential registers zp[1]:5 [ main::$0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[2]:6 [ main::msg#2 ] : zp[2]:6 , +Potential registers zp[2]:8 [ main::msg#3 ] : zp[2]:8 , REGISTER UPLIFT SCOPES -Uplift Scope [main] 370.33: zp[1]:4 [ main::i#2 main::i#1 ] 359: zp[2]:2 [ main::msg#4 main::msg#1 ] 22: zp[2]:7 [ main::msg#3 ] 16.5: zp[2]:5 [ main::msg#2 ] +Uplift Scope [main] 370.33: zp[1]:4 [ main::i#2 main::i#1 ] 258: zp[2]:2 [ main::msg#4 main::msg#1 ] 101: zp[1]:5 [ main::$0 ] 22: zp[2]:8 [ main::msg#3 ] 16.5: zp[2]:6 [ main::msg#2 ] Uplift Scope [] -Uplifting [main] best 824 combination reg byte x [ main::i#2 main::i#1 ] zp[2]:2 [ main::msg#4 main::msg#1 ] zp[2]:7 [ main::msg#3 ] zp[2]:5 [ main::msg#2 ] +Uplifting [main] best 824 combination reg byte x [ main::i#2 main::i#1 ] zp[2]:2 [ main::msg#4 main::msg#1 ] reg byte a [ main::$0 ] zp[2]:8 [ main::msg#3 ] zp[2]:6 [ main::msg#2 ] Uplifting [] best 824 combination -Coalescing zero page register [ zp[2]:2 [ main::msg#4 main::msg#1 ] ] with [ zp[2]:5 [ main::msg#2 ] ] - score: 1 -Coalescing zero page register [ zp[2]:2 [ main::msg#4 main::msg#1 main::msg#2 ] ] with [ zp[2]:7 [ main::msg#3 ] ] - score: 1 +Coalescing zero page register [ zp[2]:2 [ main::msg#4 main::msg#1 ] ] with [ zp[2]:6 [ main::msg#2 ] ] - score: 1 +Coalescing zero page register [ zp[2]:2 [ main::msg#4 main::msg#1 main::msg#2 ] ] with [ zp[2]:8 [ main::msg#3 ] ] - score: 1 ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -391,65 +403,66 @@ main: { jmp __b1 // main::@1 __b1: - // [6] (byte*) main::msg#1 ← ++ (byte*) main::msg#4 -- pbuz1=_inc_pbuz1 + // [6] (byte~) main::$0 ← *((byte*) main::msg#4) -- vbuaa=_deref_pbuz1 + ldy #0 + lda (msg),y + // [7] (byte*) main::msg#1 ← ++ (byte*) main::msg#4 -- pbuz1=_inc_pbuz1 inc.z msg bne !+ inc.z msg+1 !: - // [7] if((byte) 0!=*((byte*) main::msg#1)) goto main::@1 -- vbuc1_neq__deref_pbuz1_then_la1 - ldy #0 - lda (msg),y + // [8] if((byte) 0!=(byte~) main::$0) goto main::@1 -- vbuc1_neq_vbuaa_then_la1 cmp #0 bne __b1_from___b1 jmp __b2 // main::@2 __b2: - // [8] (byte*) main::msg#2 ← -- (byte*) main::msg#1 -- pbuz1=_dec_pbuz1 + // [9] (byte*) main::msg#2 ← -- (byte*) main::msg#1 -- pbuz1=_dec_pbuz1 lda.z msg bne !+ dec.z msg+1 !: dec.z msg - // [9] *((byte*) main::msg#2) ← (byte) 'x' -- _deref_pbuz1=vbuc1 + // [10] *((byte*) main::msg#2) ← (byte) 'x' -- _deref_pbuz1=vbuc1 // Now msg should point right after the zero, since the post increment was executed in the last condition that evaluated to zero. lda #'x' ldy #0 sta (msg),y - // [10] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz1 + // [11] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz1 inc.z msg bne !+ inc.z msg+1 !: - // [11] *((byte*) main::msg#3) ← (byte) 0 -- _deref_pbuz1=vbuc1 + // [12] *((byte*) main::msg#3) ← (byte) 0 -- _deref_pbuz1=vbuc1 lda #0 ldy #0 sta (msg),y - // [12] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + // [13] phi from main::@2 to main::@3 [phi:main::@2->main::@3] __b3_from___b2: - // [12] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuxx=vbuc1 + // [13] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuxx=vbuc1 ldx #0 jmp __b3 // main::@3 __b3: - // [13] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 -- vbuc1_neq_pbuc2_derefidx_vbuxx_then_la1 + // [14] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 -- vbuc1_neq_pbuc2_derefidx_vbuxx_then_la1 lda MESSAGE,x cmp #0 bne __b4 jmp __breturn // main::@return __breturn: - // [14] return + // [15] return rts // main::@4 __b4: - // [15] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx + // [16] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx lda MESSAGE,x sta SCREEN,x - // [16] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx + // [17] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx inx - // [12] phi from main::@4 to main::@3 [phi:main::@4->main::@3] + // [13] phi from main::@4 to main::@3 [phi:main::@4->main::@3] __b3_from___b4: - // [12] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy + // [13] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy jmp __b3 } // File Data @@ -496,6 +509,7 @@ FINAL SYMBOL TABLE (const byte*) MESSAGE[(number) $14] = (byte*) "camelot" (const nomodify byte*) SCREEN = (byte*) 1024 (void()) main() +(byte~) main::$0 reg byte a 101.0 (label) main::@1 (label) main::@2 (label) main::@3 @@ -505,13 +519,14 @@ FINAL SYMBOL TABLE (byte) main::i#1 reg byte x 202.0 (byte) main::i#2 reg byte x 168.33333333333331 (byte*) main::msg -(byte*) main::msg#1 msg zp[2]:2 157.0 +(byte*) main::msg#1 msg zp[2]:2 106.5 (byte*) main::msg#2 msg zp[2]:2 16.5 (byte*) main::msg#3 msg zp[2]:2 22.0 -(byte*) main::msg#4 msg zp[2]:2 202.0 +(byte*) main::msg#4 msg zp[2]:2 151.5 zp[2]:2 [ main::msg#4 main::msg#1 main::msg#2 main::msg#3 ] reg byte x [ main::i#2 main::i#1 ] +reg byte a [ main::$0 ] FINAL ASSEMBLER @@ -547,66 +562,67 @@ main: { // main::@1 __b1: // while(*msg++) - // [6] (byte*) main::msg#1 ← ++ (byte*) main::msg#4 -- pbuz1=_inc_pbuz1 + // [6] (byte~) main::$0 ← *((byte*) main::msg#4) -- vbuaa=_deref_pbuz1 + ldy #0 + lda (msg),y + // [7] (byte*) main::msg#1 ← ++ (byte*) main::msg#4 -- pbuz1=_inc_pbuz1 inc.z msg bne !+ inc.z msg+1 !: - // [7] if((byte) 0!=*((byte*) main::msg#1)) goto main::@1 -- vbuc1_neq__deref_pbuz1_then_la1 - ldy #0 - lda (msg),y + // [8] if((byte) 0!=(byte~) main::$0) goto main::@1 -- vbuc1_neq_vbuaa_then_la1 cmp #0 bne __b1 // main::@2 // *--msg = 'x'; - // [8] (byte*) main::msg#2 ← -- (byte*) main::msg#1 -- pbuz1=_dec_pbuz1 + // [9] (byte*) main::msg#2 ← -- (byte*) main::msg#1 -- pbuz1=_dec_pbuz1 lda.z msg bne !+ dec.z msg+1 !: dec.z msg // *--msg = 'x' - // [9] *((byte*) main::msg#2) ← (byte) 'x' -- _deref_pbuz1=vbuc1 + // [10] *((byte*) main::msg#2) ← (byte) 'x' -- _deref_pbuz1=vbuc1 // Now msg should point right after the zero, since the post increment was executed in the last condition that evaluated to zero. lda #'x' ldy #0 sta (msg),y // *++msg = 0; - // [10] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz1 + // [11] (byte*) main::msg#3 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz1 inc.z msg bne !+ inc.z msg+1 !: // *++msg = 0 - // [11] *((byte*) main::msg#3) ← (byte) 0 -- _deref_pbuz1=vbuc1 + // [12] *((byte*) main::msg#3) ← (byte) 0 -- _deref_pbuz1=vbuc1 lda #0 tay sta (msg),y - // [12] phi from main::@2 to main::@3 [phi:main::@2->main::@3] - // [12] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuxx=vbuc1 + // [13] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + // [13] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuxx=vbuc1 tax // main::@3 __b3: // while(MESSAGE[i]) - // [13] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 -- vbuc1_neq_pbuc2_derefidx_vbuxx_then_la1 + // [14] if((byte) 0!=*((const byte*) MESSAGE + (byte) main::i#2)) goto main::@4 -- vbuc1_neq_pbuc2_derefidx_vbuxx_then_la1 lda MESSAGE,x cmp #0 bne __b4 // main::@return // } - // [14] return + // [15] return rts // main::@4 __b4: // SCREEN[i] = MESSAGE[i] - // [15] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx + // [16] *((const nomodify byte*) SCREEN + (byte) main::i#2) ← *((const byte*) MESSAGE + (byte) main::i#2) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx lda MESSAGE,x sta SCREEN,x // i++; - // [16] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx + // [17] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx inx - // [12] phi from main::@4 to main::@3 [phi:main::@4->main::@3] - // [12] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy + // [13] phi from main::@4 to main::@3 [phi:main::@4->main::@3] + // [13] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy jmp __b3 } // File Data diff --git a/src/test/ref/post-increment-problem.sym b/src/test/ref/post-increment-problem.sym index c8a14739b..31798caf8 100644 --- a/src/test/ref/post-increment-problem.sym +++ b/src/test/ref/post-increment-problem.sym @@ -4,6 +4,7 @@ (const byte*) MESSAGE[(number) $14] = (byte*) "camelot" (const nomodify byte*) SCREEN = (byte*) 1024 (void()) main() +(byte~) main::$0 reg byte a 101.0 (label) main::@1 (label) main::@2 (label) main::@3 @@ -13,10 +14,11 @@ (byte) main::i#1 reg byte x 202.0 (byte) main::i#2 reg byte x 168.33333333333331 (byte*) main::msg -(byte*) main::msg#1 msg zp[2]:2 157.0 +(byte*) main::msg#1 msg zp[2]:2 106.5 (byte*) main::msg#2 msg zp[2]:2 16.5 (byte*) main::msg#3 msg zp[2]:2 22.0 -(byte*) main::msg#4 msg zp[2]:2 202.0 +(byte*) main::msg#4 msg zp[2]:2 151.5 zp[2]:2 [ main::msg#4 main::msg#1 main::msg#2 main::msg#3 ] reg byte x [ main::i#2 main::i#1 ] +reg byte a [ main::$0 ] diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm index f39e9bace..932dfa650 100644 --- a/src/test/ref/sandbox.asm +++ b/src/test/ref/sandbox.asm @@ -8,12 +8,12 @@ .label TIMELO = $a2 .label VICBANK = $d018 main: { - .label __3 = 6 .label __4 = 6 - .label __5 = $11 - .label __12 = 6 - .label __13 = 6 - .label __14 = $f + .label __5 = 6 + .label __6 = $11 + .label __15 = 6 + .label __16 = 6 + .label __17 = $f .label v = 4 // test performance of 'div16u(10)' // test performance of 'div10' @@ -64,26 +64,26 @@ main: { bcc __b10 // (word)*TIMEHI lda TIMEHI - sta.z __12 + sta.z __15 lda #0 - sta.z __12+1 + sta.z __15+1 // (word)*TIMEHI << 8 - lda.z __13 - sta.z __13+1 + lda.z __16 + sta.z __16+1 lda #0 - sta.z __13 + sta.z __16 // (word)*TIMELO lda TIMELO - sta.z __14 + sta.z __17 lda #0 - sta.z __14+1 + sta.z __17+1 // myprintf(strTemp, "200 DIV10 : %5d,%4d IN %04d FRAMESm", u, v, ((word)*TIMEHI << 8) + (word)*TIMELO) lda.z myprintf.w3 clc - adc.z __14 + adc.z __17 sta.z myprintf.w3 lda.z myprintf.w3+1 - adc.z __14+1 + adc.z __17+1 sta.z myprintf.w3+1 lda #