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