EgonOlsen71 / basicv2

A Commodore (CBM) BASIC V2 interpreter/compiler written in Java
https://egonolsen71.github.io/basicv2/
The Unlicense
85 stars 15 forks source link

Avoid Gosub constructs so it is in future safe to add inlining #9

Closed ciplogic closed 5 years ago

ciplogic commented 5 years ago

This PR allows to remove in future some cases of proper inlining (by inline I mean to remove a gosub and back code if there is only one way to run the code)

 L: gosub N
 L+1: ...
 (...)
 N: ...
 return

if the gosub to N is unique, the code is transformed to:

 L: goto N
 L+1: ...
 (...)
 N: (...)
 goto L+1

If this PR is built, more work will be done to cleanup the PCode class so it can be easier to navigate and replace stuff in it.

ciplogic commented 5 years ago

I will do the changes in the evening.

You are right about the default, I was using it when testing... and I forgot to flip it back :(

EgonOlsen71 commented 5 years ago

Do you actually have a test case that shows the benefits of this optimization? I mean...modern compilers do inlining mainly because jumps are expensive. But on the 6502, they simply cost the number of clock cycles that they cost, there's no pipeline flush or stall or anything involved.

ciplogic commented 5 years ago

You are right, I assume initially will have almost no benefit.

I don't have any test case it would improve, but after that I will want to do one extra step that will remove all together the goto and goto-back.

(this will be a separate PR to not bloat this one).

So the idea is that:

 L: goto N
 L+1: ...
 (...)
 N: (...)//"Function" code
 goto L+1

wil become:

L: (...) //"Function" code
L+1:

(I need to shift also all jumps by the function size and to know all possible goto like statements).

ciplogic commented 5 years ago

Last comment before arriving with a fix of your comments.

And after removing as many GOTOs, I hope to implement as many basic block optimisations, at least "forward propagation of constants" and "common subexpression eliminations".

I did implement an optimising compiler in C# so I assume that in future it would help to create similar functionality inside your optimizing compiler. (You can look for "CodeRefractor" out of my repos)

EgonOlsen71 commented 5 years ago

I've merged your changes. Constant propagation is already part of the compilation process, BTW.

ciplogic commented 5 years ago

I noticed how it is done, and it is not exactly how I assume that it would work: what I mean is: "basic block propagation of constants" which I noticed you don't have it:

a = 1
(...) code with no go to or loops
a=2

between: a=1 and a=2 you can propagate value of a as being 1 and then remove assignment to a=1.

This is the hope and direction I will be able to achieve.

EgonOlsen71 commented 5 years ago

No, I don't have that. I didn't care about basic blocks, because finding them in a language with unstructured control flow seemed hard to do to me. Anyway...

I've found a problem with your optimizer. Just try the GamesCompiler test and it will crash with an array index out of bounds on the moonbuggy source.

ciplogic commented 5 years ago

I will debug it in the evening (I live in EU) as I am in work-time now.

ciplogic commented 5 years ago

Found the issue:

0 GOSUB10050
1 POKE55,255:POKE56,47:V=53248:POKEV+32,0:POKEV+33,0
(...)
10050 POKE53281,0:PRINT”{clear}to go left press z : to go right press c”
10060 PRINT”{space*11}to fire jets press m”:FORT=1TO2000:NEXT:RETURN

^ I look for one return per line, so I could not find the return as it doesn't exist alone.

I will replace the logic to look for the return command properly even in this case