bebbo / gcc

Bebbo's gcc-6-branch for m68k-amigaos
GNU General Public License v2.0
33 stars 11 forks source link

Possible compiler bug while inlining #227

Closed mankeli closed 4 months ago

mankeli commented 4 months ago

Hi, I compile the following code with /opt/amiga/bin/m68k-amigaos-gcc -mcrt=nix13 -O2 -Wall -c test.c -o test.o and it seems to "forget" the y-loop ( for (uint16_t y = 0; y < 150;) ). If I change waitforvblank() to not-inlined by adding the attribute, the loop seems to be there.

#include <stdio.h>
#include <hardware/custom.h>
#include <assert.h>
#include <clib/exec_protos.h>

extern volatile struct Custom custom;

uint16_t* framebuffer;

volatile uint16_t vblflag = 0;

void counterintuition_vbl()
{

    vblflag = 1;
}

#define NOINLINE __attribute__ ((noinline))
//#define NOINLINE
#define LINE
//#define LINE NOINLINE

void LINE waitforvblank()
{
    vblflag = 0;
    while(!vblflag)
    {
        continue;
    }
}

void counterintuition_run()
{
    while(1)
    {
            static int beg = 0;
            beg ++;
            beg &= 15;

            uint16_t* ptr = framebuffer + 20*beg;
            for (uint16_t y = 0; y < 150;)
            {

                custom.color[0] = 0xf00;

                for (uint16_t x = 0; x < 20; x++)
                    *ptr++ = 0xff00;

                y++;

                waitforvblank();

                for (uint16_t x = 0; x < 20; x++)
                    *ptr++ = 0x00ff;

                y++;

                waitforvblank();
            }
    }
}
mankeli commented 4 months ago

When disassembling with objdump, I get this with automatic inlining. It seems to correspond to latter call to waitforvblank() and then jump for the while(1) loop. (and also some code for the 20*beg)

  7e:   33c1 0000 0000  move.w d1,0 0 _vblflag
  84:   3039 0000 0000  move.w 0 0 _vblflag,d0
  8a:   67f8            beq.s 84 84 _counterintuition_run+0x68
  8c:   5283            addq.l #1,d3
  8e:   700f            moveq #15,d0
  90:   c680            and.l d0,d3
  92:   2003            move.l d3,d0
  94:   e588            lsl.l #2,d0
  96:   d083            add.l d3,d0
  98:   e788            lsl.l #3,d0
  9a:   d085            add.l d5,d0
  9c:   2240            movea.l d0,a1
  9e:   784a            moveq #74,d4
  a0:   60a2            bra.s 44 44 _counterintuition_run+0x28

If I compile with noinline, the jump for y-loop is there. (a4 contains address of waitforvblank)


  72:   4e94            jsr (a4)
  74:   5344            subq.w #1,d4
  76:   67b6            beq.s 2e 2e _counterintuition_run+0x12
  78:   33c2 0000 0180  move.w d2,180 180 _custom+0x180
  7e:   204b            movea.l a3,a0
  80:   7013            moveq #19,d0
  82:   60d2            bra.s 56 56 _counterintuition_run+0x3a

Am I hitting some weird UB, or might this really be a bug?

mheyer32 commented 4 months ago

I made a previous comment about vblflag needing volatile. I now see it already is qualified as such. Sorry.

bebbo commented 4 months ago

sorry, I don't get it: http://franke.ms/cex/z/znsh8q The code looks ok for me. There is a moveq #74,d4 and a dbf d4,.L13 and since y gets incremented twice this yields 75 loops.

mankeli commented 4 months ago

The GCC I have locally doesn't seem to generate the dbf instruction, even though it looks the same otherwise

bebbo commented 4 months ago

The GCC I have locally doesn't seem to generate the dbf instruction, even though it looks the same otherwise

then update first

mankeli commented 4 months ago

GCC update indeed fixes this.