Bug 44608 - unspecified signed overflow applied to unsigned int
Summary: unspecified signed overflow applied to unsigned int
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.4.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2010-06-21 11:23 UTC by Georg-Johann Lay
Modified: 2010-07-21 22:51 UTC (History)
1 user (show)

See Also:
Host:
Target: private
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-06-21 11:38:28


Attachments
Dump for .c.123t.optimized (183 bytes, text/plain)
2010-06-21 11:26 UTC, Georg-Johann Lay
Details
Dump for .c.128r.expand (1.13 KB, text/plain)
2010-06-21 11:28 UTC, Georg-Johann Lay
Details
Dump for .c.141r.ce1 (2.17 KB, text/plain)
2010-06-21 11:28 UTC, Georg-Johann Lay
Details
Dump for .c.159r.combine (1.11 KB, text/plain)
2010-06-21 11:30 UTC, Georg-Johann Lay
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Georg-Johann Lay 2010-06-21 11:23:46 UTC
As discussed in 
http://gcc.gnu.org/ml/gcc-help/2010-06/msg00191.html
I am filing a PR for the following piece of C:

int abssat2 (int x)
{
    unsigned int y = x;

    if (x < 0)
        y = -y;

    if (y >= 0x80000000)
        y--;

    return y;
}

Code looks fine until pass CE1 which introduces ABS rtx for the first comparison (ifcvt.c:noce_try_abs). 

Pass insn combine then calls 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))
and the latter removes the second comparison against 0x80000000.

As this problem occurs on a non-standard target, let me know if I con you provide with any additional information.
Comment 1 Georg-Johann Lay 2010-06-21 11:26:55 UTC
Created attachment 20955 [details]
Dump for .c.123t.optimized

Dump for .c.123t.optimized
Comment 2 Georg-Johann Lay 2010-06-21 11:28:05 UTC
Created attachment 20956 [details]
Dump for .c.128r.expand

Dump for .c.128r.expand
Comment 3 Georg-Johann Lay 2010-06-21 11:28:53 UTC
Created attachment 20957 [details]
Dump for .c.141r.ce1

Dump for .c.141r.ce1
Comment 4 Georg-Johann Lay 2010-06-21 11:30:06 UTC
Created attachment 20958 [details]
Dump for .c.159r.combine

Dump for .c.159r.combine
Comment 5 Richard Biener 2010-06-21 11:38:28 UTC
It is folding from the frontend that changes

    if (y >= 0x80000000)

to

    if ((int) y < 0)

(see code == LT instead of code == GEU)

But the main issue is that y = -y to abs is bogus (but we can't easily tell
that as on RTL operands do not have a signedness).
Comment 6 Richard Biener 2010-06-21 11:50:54 UTC
int __attribute__((noinline))
abssat2 (int x)
{
  unsigned int y = x;
  if (x < 0)
    y = -y;
  if (y >= 0x80000000)
    y--;
  return y;
}
extern void abort (void);
int main()
{
  if (abssat2 (0x80000000) != 0x7fffffff)
    abort ();
  return 0;
}

does not fail on x86_64 or i?86.
Comment 7 Georg-Johann Lay 2010-06-21 12:27:11 UTC
(In reply to comment #5)
> It is folding from the frontend that changes
> 
>     if (y >= 0x80000000)
> 
> to
> 
>     if ((int) y < 0)
> 
> (see code == LT instead of code == GEU)
> 
> But the main issue is that y = -y to abs is bogus (but we can't easily tell
> that as on RTL operands do not have a signedness).

Both transformation are ok from the target's point of view. The bad thing is that undefinedness is propagated to RTL which is supposed to be an algebraic formulation of the target's instruction set. But in this case RTL is treated like a low level representation of C (or any other language gcc supports).

To reproduce the problem it seems essential that there is an abssi2 insn in the md. 

Comment 8 Andrew Pinski 2010-07-21 22:51:05 UTC
For some reason rs6000 has an abssi pattern but it is not produced by ce1.