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

            Bug ID: 122948
           Summary: sh: comparison is miscompiled
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kristerw at gcc dot gnu.org
            Blocks: 118443
  Target Milestone: ---
            Target: sh-elf

The program below is miscompiled by sh-elf-gcc when built with -O1 or higher:

__attribute__ ((noipa)) unsigned int
foo(unsigned int a, unsigned int b) {
  if (b - a - 1 <= b)
    a = 0;
  return a;
}

int main()
{
  if (foo(0xffffffff, 0x4e92c833))
    __builtin_abort();
  return 0;
}

The generated assembly for foo is:

_foo:
        sett
        mov     r5,r1
        subc    r4,r1
        subc    r1,r1
        mov     r4,r0
        rts     
        and     r1,r0

The issue is that:
        sett
        mov     r5,r1
        subc    r4,r1
does not evaluate the condition b - a - 1 <= b because SUBC sets the T bit if
either b-a overflows or (b-a)-1 overflows, while we want T to be set if the
subtraction b-(a+1) overflows.

For example, the following assembly implements the correct calculation:

_foo:
        clrt
        mov     r4,r0
        add     #1,r4
        mov     r5,r1
        subc    r4,r1
        subc    r1,r1
        rts     
        and     r1,r0


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118443
[Bug 118443] [Meta bug] Bugs triggered by and blocking more smtgcc testing

Reply via email to