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