I always use x << 8 | y & 255...

I eager to see what you will do with register permutations

I think it could be the key to multiply the number of patterns

E.g. these are variation of existing patterns where bc,hl and de are permuted

pattern: 0: pop de 1: ld h,d 2: ld l,e replacement: 0: pop hl constraints: regNotUsed(2,de) pattern: 0: pop de 1: ld b,d 2: ld c,e replacement: 0: pop bc constraints: regNotUsed(2,de)

Ah, yeah "x << 8 | y & 255" would also be safe!

And indeed @ARTRAG, you are right! I think the current pattern set is growing fast because of the need to have all those permutations. The consequence is that probably we are missing some permutations, and also the optimizer is slowed down due to the growing number of patterns.

Maybe a quick thing that could be done to start would be to generalize the patterns a bit, maybe like this:

pattern: 0: pop ?regpair1 1: ld ?reg2a,?reg1a 2: ld ?reg2b,?reg1b replacement: 0: pop ?regpair2 constraints: regNotUsed(2,?regpair1) in(?regpair1,[bc,de,hl]) in(?regpair2,[bc,de,hl]) equal(?reg1a++?reg1b, ?regpair1) equal(?reg2a++?reg2b, ?regpair2)

Or something like that. I'll think about it a bit more

Another one I found in my code the other day:

0: ld de,xx (with xx < 256) 1: ld de,yy (with yy < 256) replacement: 0: ld de,xx 1: ld e,yy constraints: d not used

Thanks Metalion, this one is interesting! This one would be cool to capture also if there is code in between 0 and 1 that do not modify "de"! Also, if there is no code in between, we could directly remove the first instruction altogether. Making a note of this case for testing

Maybe it can be written as a generalization of the existing "remove unused ld reg,?"...

pattern: Remove unused ld reg,? 0: ld ?reg,?any replacement: constraints: regNotUsed(0,?reg)

...but it will require a separate pattern for b, c, d, e, h and l:

pattern: Replace ld de,? with ld e,? 0: ld de,?const1 replacement: 0: ld e,(?const1 % 256) constraints: regNotUsed(0,d)

Interesting, yes!

I'll make a note of this for when I get back to it tonight! Also, another idea, following up on this type of patterns is if we have:

ld de,XX

ld de,YY

Then, if (XX & #ff00) == (YY & #ff00), then we know we only need to modify "e", since that's when "d" is not going to change! And we can have the reverse, if (XX & #00ff) == (YY & #00ff), then we know "e" will not change, and we can just modify "d".

I just added a version of the pattern you suggested, and it works pretty well! I had to update a few test cases, as more optimizations than I Was expecting happened haha. I generalized a bit the way patterns can be defined, and the version in the repo is like this:

pattern: Replace ld ?regpair,?const1 with ld ?regpairl,(?const1 % 256) 0: ld ?regpair,?const1 replacement: 0: ld ?regpairl,(?const1 % 256) constraints: regpair(?regpair,?regpairh,?regpairl) regNotUsed(0,?regpairh)

And there is an alternative version for when it is ?regpairl that is not used.

I now just need to implement one more improvement and I can add Metalion's original pattern in the way I'd like to add it! (but enough for today ).

I keep track of how many optimizations mdl is finding in different projects for reference. Version 0.5 (the current release), for example only optimized 21 bytes out of XSpelunker. But the current master branch already optimizes 33 bytes. So, progress!

*santiontanon*wrote:

This one would be cool to capture also if there is code in between 0 and 1 that do not modify "de"

That is exactly the case I was tring to explain.

In my code, there was a dozen lines between those 2 "ld de".

ah, ok, makes sense now! Yes, I got that pattern of yours noted down in my to-do list! Patterns still do not support "filler instructions in between". But that's coming to the optimizer soon (hopefully this weekend). So, probably your pattern will be the first to exploit it

I hope that with that improvement the optimizer starts to find significantly more optimizations to suggest (fingers crossed! haha)