https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121483

            Bug ID: 121483
           Summary: m68k: Suboptimal handling of 64bit values
           Product: gcc
           Version: 15.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ad...@tho-otto.de
  Target Milestone: ---

Seems like handling of long long 64bit arithmetic has regressed in newer
versions of the compiler for m68k.

In gcc 4.6.4, the simple function 

unsigned long long test(unsigned long long x)
{
        return (x >> 1) | 0x8000000000000000ULL;
}

when compiled with -O2 -fomit-frame-pointer, produced

        move.l 4(%sp),%d0
        move.l 8(%sp),%d1
        lsr.l #1,%d0
        roxr.l #1,%d1
        bset #31,%d0
        rts

In gcc 7 and later, the produced code is

        move.l %d3,-(%sp)
        move.l %d2,-(%sp)
        move.l 12(%sp),%d2
        move.l 16(%sp),%d3
        lsr.l #1,%d2
        roxr.l #1,%d3
        move.l %d2,%d0
        bset #31,%d0
        move.l %d3,%d1
        move.l (%sp)+,%d2
        move.l (%sp)+,%d3
        rts

Bisecting gave me this commit
https://github.com/gcc-mirror/gcc/commit/27508f5fa3c79ca39d32079348017c6132d25722

as cause for the change.

In gcc 15.1.0, code has become even worse:

        move.l %d3,-(%sp)
        move.l %d2,-(%sp)
        move.l 12(%sp),%d0
        move.l 16(%sp),%d1
        move.l %d0,%d2
        move.l %d1,%d3
        lsr.l #1,%d2
        roxr.l #1,%d3
        move.l %d2,%a0
        move.l %d3,%a1
        move.l %d2,%d0
        bset #31,%d0
        move.l %a1,%d1
        move.l (%sp)+,%d2
        move.l (%sp)+,%d3
        rts

(note the additional, completely unnecessary stores to a0/a1)

Reply via email to