initialising array members

Bug reports (if you don't/won't have a Github account)
Post Reply
arnoldemu
New member
Posts: 8
Joined: Wed Sep 08, 2010 1:07 pm

initialising array members

Post by arnoldemu »

I have an array defined as:

static unsigned short PlayerType[2];

In the code I initialise the PlayerType like this:

PlayerType[0] = HUMAN;
PlayerType[1] = HUMAN;

and also I tried:

PlayerType[0] = PlayerType[1] = HUMAN;

the generated z80 code is poor in both cases.

ld hl,1
ld (_PlayerType),hl

for element 0. this is good. Element 0 is always initialised well.

ld hl,_PlayerType+1+1
ld (hl),#(1 % 256)
inc hl
ld (hl),#(1 / 256)

should this not be?

ld hl,1
ld (_PlayerType+2),hl

and if both player types are the same the ultimate is then

ld hl,1
ld (_PlayerType),hl
ld (_PlayerType+2),hl

??

The program I am writing is very tight on ram, so I need to do everything I can to reduce code size.

Is this a bug?
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

Can you supply a longer snippet of code? Some optimisation rules are kicking in to generate the output that you've got.
arnoldemu
New member
Posts: 8
Joined: Wed Sep 08, 2010 1:07 pm

Post by arnoldemu »

dom wrote:Can you supply a longer snippet of code? Some optimisation rules are kicking in to generate the output that you've got.

Code: Select all

enum
{
        PLAYER_HUMAN = 0,
        PLAYER_CPU
};

enum
{
        VS_PLAYERVSCPU = 0,
        VS_CPUVSPLAYER,
        VS_PLAYERVSPLAYER,
        VS_CPUVSCPU,
        VS_MAX
};
static unsigned short PlayerType[2];
static unsigned short VS = VS_PLAYERVSCPU;


void SetPlayerTypes()
{
        switch (VS)
        {
                case VS_PLAYERVSCPU:
                {
                        PlayerType[1] = PLAYER_CPU;
                        PlayerType[0] = PLAYER_HUMAN;
                }
                break;
                
                case VS_CPUVSPLAYER:
                {
                        PlayerType[1] = PLAYER_HUMAN;
                        PlayerType[0] = PLAYER_CPU;
                }
                break;

                case VS_PLAYERVSPLAYER:
                {
                        PlayerType[1] = PLAYER_HUMAN;
                        PlayerType[0] = PLAYER_HUMAN;
                }
                break;
                
                case VS_CPUVSCPU:
                {
                        PlayerType[0] = PlayerType[1] = PLAYER_CPU;
                }
                break;
        }
}                

void main()
{
}

Code: Select all

zcc +cpc -zorg=512 -create-app  -O3 -Wall -unsigned -o bin\test test.c
This produces both results for code generation.

thankyou for taking the time to look at this.

Is there a possible workaround?
I don't mind taking a z88dk snapshot if not.

I noticed a few other things and documented them on the cpcwiki forum, but in each case I was able to work around it.

http://cpcwiki.eu/forum/index.php/topic,574.0.html
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

Not forgotten - was just away for the weekend.

I've checked in a couple of rules that kick in on -O3 which clear up a couple of the cases.

Since I've just restarted the nightly build if you pick up the build that should pop out tonight you can give it a go.
arnoldemu
New member
Posts: 8
Joined: Wed Sep 08, 2010 1:07 pm

Post by arnoldemu »

dom wrote:Not forgotten - was just away for the weekend.

I've checked in a couple of rules that kick in on -O3 which clear up a couple of the cases.

Since I've just restarted the nightly build if you pick up the build that should pop out tonight you can give it a go.
much better. Thankyou for reading and helping.

Can you improve the case where:

PlayerType[0] = PlayerType[1] = PLAYER_CPU;

??

Code: Select all

        ld        hl,_PlayerType
        push        hl
        inc        hl
        inc        hl
        ld        de,1        ;const
        ex        de,hl
        call        l_pint
        call        l_pint_pop
It seems it is better to re-write it as:

Code: Select all

PlayerType[0] = PLAYER_CPU;
PlayerType[1] = PLAYER_CPU;
With your change optimisations.




The code here is not great.

Btw I would like to share some code optimisations that you may be able to use:

Code: Select all

        ld        a,h
        or        l
        jp        nz,%1
        jr        %2
.%1
        ld        hl,1        ;const
.%2
        ret
=
        ld  a,h
        or  l
        ret z
.%1        ld hl,1
.%2        ret

Code: Select all

        call        l_lneg
        jp        nc,%1
        ld        hl,1        ;const
        jr        %2
.%1
        ld        hl,0        ;const
.%2
        ld        h,0
        ret
=
        call        l_lneg
        ld hl,1
        jr c,%2
.%1
        ld l,0
.%2
        ret

Code: Select all

        ld        hl,%3 % 256        ;const
        ld        a,l
        ld        (%1),a
        ld        h,0
        ld        a,l
        ld        (%2),a
=
        ld hl,%3 % 256
        ld a,l
        ld (%1),a
        ld (%2),a

Code: Select all

        ld        h,0
        ld        a,l
        ld        (%1),a
        ld        h,0
        ld        a,l
        ld        (%2),a
=
        ld  h,0
        ld  a,l
        ld        (%1),a
        ld        (%2),a
Not sure if this is one of mine, or one already in there.

Code: Select all

        ld        hl,%1
        push        hl
        ld        hl,(%2)
        add        hl,hl
        pop        de
        add        hl,de
=
        ld hl,(%2)
        ld de,%1
        add hl,hl
        add hl,de
This would be great if it could be extended to the general case. I've seen the code generated. it didn't use a case code setup this time.

Code: Select all

        ld        a,l
        cp        #(0% 256)
        jp        z,%1
        cp        #(1% 256)
        jp        z,%2
        cp        #(2% 256)
        jp        z,%3
        cp        #(3% 256)
        jp        z,%4
=
        ld a,l
        or a
        jp z,%1
        dec a
        jp z,%2
        dec a
        jp z,%3        
        dec a
        jp z,%4
Is there any optimisation rule which can be used to reduce jp to jr on a final pass?
So that when all of these rules have worked you can then go and reduce the code down furthur to jr where possible?

BTW, all these changes make a difference. I also swapped from using pucrunch for some gfx and used exomizer instead, now I have a few hundred bytes free :)
Post Reply