Question on signed overflow
Georg Lay
avr@gjlay.de
Fri Jun 18 12:56:00 GMT 2010
Andrew Haley schrieb:
> On 06/18/2010 10:11 AM, Georg Lay wrote:
>> Andrew Haley schrieb:
>>> On 06/18/2010 08:56 AM, Georg Lay wrote:
>>>> Hi, I have a question on gcc's signed overflow optimisation in the
>>>> following C function:
>>>>
>>>> int abssat2 (int x)
>>>> {
>>>> unsigned int y = x;
>>>>
>>>> if (x < 0)
>>>> y = -y;
>>>>
>>>> if (y >= 0x80000000)
>>>> y--;
>>>>
>>>> return y;
>>>> }
>>>>
>>>> gcc optimises the second comparison and throws it away, and that's the
>>>> part I do not understand because all computations are performed on
>>>> unsigned int which has no undefined behaviour on overflow.
>>>>
>>>> For the unary - the standard says in 6.5.3.3.3:
>>>> The result of the unary - operator is the negative of its (promoted)
>>>> operand. The integer promotions are performed on the operand, and
>>>> the result has the promoted type.
>>>>
>>>> And the promotion rules in 6.3.1.1.2:
>>>> If an int can represent all values of the original type, the value
>>>> is converted to an int; otherwise, it is converted to an unsigned int.
>>>> These are called the integer promotions. All other types are unchanged
>>>> by the integer promotions.
>>>>
>>>> As an int cannot represent all values that can be represented by an
>>>> unsigned int, there is no signed int in the line y = -y.
>>>>
>>>> Could anyone explain this? I see this on gcc 4.4.3.
>>> Works for me on gcc 4.4.3:
>>>
>>> movl %edi, %eax
>>> sarl $31, %eax
>>> xorl %eax, %edi
>>> subl %eax, %edi
>>> movl %edi, %eax
>>> shrl $31, %eax
>>> subl %eax, %edi
>>> movl %edi, %eax
>> Ok. Is your code as it should be on any machine or is it just a "missed
>> optimisation"?
>
> Your problem sounds to me like incorrect code, not missed optimization.
>
>> I observe it on a non-standard embedded target that has an abs
>> instruction, i.e. there is an abssi2 insn that leads to abs:SI rtx.
>> Maybe there is some standard target that also has native support of abs
>> to see what happens there?
>
> Perhaps. I think the problem may be that abs is being generated incorrectly.
The abs is generated in RTL pass "ce1" by ifcvt.c:noce_try_abs() and
gets optimised away by combine.c:combine_simplify_rtx() which calls
simplify_rtx.c:simplify_relational_operation (code=LT, mode=SImode,
cmp_mode=SImode, op0=(abs:SI (reg:SI)), op1=(const_int 0)).
I tried to reproduce on ARM but there is no abs generated (maybe because
its abssi2 insn does some clobbers) and thus the problem doesnt's show
up there.
> What does -fdump-tree-optimized look like?
It looks almost as yours:
;; Function abssat2 (abssat2)
Analyzing Edge Insertions.
abssat2 (int x)
{
unsigned int y;
<bb 2>:
y = (unsigned int) x;
if (x < 0)
goto <bb 3>;
else
goto <bb 4>;
<bb 3>:
y = -y;
<bb 4>:
if ((int) y < 0)
goto <bb 5>;
else
goto <bb 6>;
<bb 5>:
y = y + 0x0ffffffff;
<bb 6>:
return (int) y;
}
>> Or is my confusion based on some misunderstandings of the language
>> standard?
>
> Your code is correct as far as I can see.
>
> I don't get any warnings with -Wstrict-overflow.
>
> Andrew.
>
> ;; Function abssat2 (abssat2)
>
> Analyzing Edge Insertions.
> abssat2 (int x)
> {
> int prephitmp.15;
> unsigned int y;
>
> <bb 2>:
> y = (unsigned int) x;
> if (x < 0)
> goto <bb 3>;
> else
> goto <bb 4>;
>
> <bb 3>:
> y = -y;
>
> <bb 4>:
> prephitmp.15 = (int) y;
> if (prephitmp.15 < 0)
> goto <bb 5>;
> else
> goto <bb 6>;
>
> <bb 5>:
> prephitmp.15 = (int) (y + 4294967295);
>
> <bb 6>:
> return prephitmp.15;
>
> }
More information about the Gcc-help
mailing list