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; > > }