Using gcc-4.3-20061223 targeting i386-linux and options "-O9
-fomit-frame-pointer -fexpensive-optimizations -S", my test program to detect
unsigned integer overflow:

extern void abort(void);
unsigned foo(unsigned a, unsigned b) {
    unsigned sum = a + b;
    if (sum < a) abort(); /* check for overflow (wrapping) */
    if (sum < b) abort(); /* redundant */
    return sum;
}

compiles to:

foo:
        subl    $12, %esp
        movl    16(%esp), %eax
        movl    20(%esp), %edx
        addl    %eax, %edx
        cmpl    %edx, %eax
        ja      .L7
        cmpl    %edx, 20(%esp)
        ja      .L7
        movl    %edx, %eax
        addl    $12, %esp
        ret
.L7:
        call    abort

After the addition, which sets the ALU flags, the compiler issues two compare
instructions and conditional branches.  This sequence could be replaced by a
conditional branch following the addl, testing one of the flags (overflow?
carry? I forget which) set by it.

I realize for other processors (e.g., with -march=pentiumpro), the addl may be
replaced by something like leal, which may not set the flags the same way.  But
if the flags are set when building for a certain architecture, use them.... 
And is leal+cmp with data dependence still going to be better than addl?

(Also, I think a different set of register selections could eliminate the last
"movl" instruction, by putting the result of the addition into the return-value
register.)


-- 
           Summary: optimize unsigned-add overflow test on x86 to use cpu
                    flags from addl
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: P3
         Component: target
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: raeburn at raeburn dot org
 GCC build triplet: powerpc-apple-darwin
  GCC host triplet: powerpc-apple-darwin
GCC target triplet: i386-unknown-linux


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30315

Reply via email to