This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/14812] New: ARM optimizer changes rsb/cmp to cmn, but condition codes different


It seems that certain levels of optimization on ARM transform a sequence of
"rsb rX, RX, #0; cmp rY,RX" into "cmn RY,RX".  This is good, but it seems that
the C flag in particular after cmn is the opposite of after the cmp, so a
conditional branch later on gets the reverse sense.  The ARM ARM says that
cmp sets C to !BORROW(Rn-operand), but cmn sets C to CARRY(Rn+operand).

The following code illustrates the problem:

#include <string>
#include <vector>

struct ss {
        std::string name;
        int filler[6];
};

std::vector<struct ss> X;

int x(std::string s) {
        for (int i = 0; i < X.size(); i++) {
                if (X[i].name == s) return i;
        }
        return -1;
}

--

If I compile this with "arm-linux-g++ -O1 -S x.c", I get code that contains
the following sequence:
        rsb     r3, r3, #0
        cmp     r4, r3
        bcc     .L48

If I compile it with "arm-linux-g++ -Os -S x.c", I get:
        cmn     r6, r2
        ldr     r1, [r1, #0]
        bcc     .L48

The comparison has been replaced, but the branch is still on carry clear.

Marcus Hall

--

Full output from -O1 and -Os follows:

        .file   "x.c"
        .global X
        .bss
        .global X
        .align  2
        .type   X, %object
        .size   X, 12
X:
        .space  12
        .text
        .align  2
        .global _Z1xSs
        .type   _Z1xSs, %function
_Z1xSs:
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 0, uses_anonymous_args = 0
        stmfd   sp!, {r4, r5, r6, r7, lr}
        sub     sp, sp, #8
        mov     r7, r0
        mov     r4, #0
        ldr     r5, .L49
        ldr     r6, [r5, #0]
        b       .L2
.L48:
.L21:
        rsb     r3, r4, r4, asl #3
        ldr     r1, [r5, #0]
.L26:
        ldr     r3, [r1, r3, asl #2]!
        ldr     r3, [r3, #-12]
        str     r3, [sp, #4]
        ldr     r3, [r7, #0]
        ldr     r3, [r3, #-12]
        str     r3, [sp, #0]
        ldr     r0, [sp, #4]
        mov     r2, r3
        mov     r3, sp
        add     lr, sp, #8
        cmp     r2, r0
        subcs   r3, lr, #4
        ldr     r2, [r3, #0]
        ldr     r0, [r1, #0]
        ldr     r1, [r7, #0]
        bl      memcmp
        cmp     r0, #0
        ldmeqia sp, {r0, r3}
        subeq   r0, r3, r0
        cmp     r0, #0
        moveq   r0, r4
        beq     .L1
        add     r4, r4, #1
.L2:
.L6:
.L11:
        ldr     r2, [r5, #4]
        rsb     r2, r6, r2
        mov     r2, r2, asr #2
        add     r3, r2, r2, asl #3
        add     r3, r3, r3, asl #6
        add     r3, r2, r3, asl #3
        add     r3, r3, r3, asl #15
        add     r3, r2, r3, asl #3
        rsb     r3, r3, #0
        cmp     r4, r3
        bcc     .L48
        mvn     r0, #0
.L1:
        add     sp, sp, #8
        ldmfd   sp!, {r4, r5, r6, r7, pc}
        .ident  "GCC: (GNU) 3.3.3"


-------

        .file   "x.c"
        .global X
        .bss
        .global X
        .align  2
        .type   X, %object
        .size   X, 12
X:
        .space  12
        .text
        .align  2
        .global _Z1xSs
        .type   _Z1xSs, %function
_Z1xSs:
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 0, uses_anonymous_args = 0
        stmfd   sp!, {r4, r5, r6, r7, r8, lr}
        mov     r6, #0
        sub     sp, sp, #8
        mov     r8, r0
        mov     r7, r6
        b       .L2
.L48:
.L21:
.L26:
        ldr     r3, [r1, r7]
        ldr     r2, [r8, #0]
        ldr     r5, [r3, #-12]
        ldr     r4, [r2, #-12]
        mov     r1, r2
        cmp     r4, r5
        stmia   sp, {r4, r5}    @ phole stm
        add     r2, sp, #8
        mov     r0, r3
        mov     r3, sp
        subcs   r3, r2, #4
        ldr     r2, [r3, #0]
        bl      memcmp
        cmp     r0, #0
        rsbeq   r0, r4, r5
        cmp     r0, #0
        add     r7, r7, #28
        moveq   r0, r6
        beq     .L1
        add     r6, r6, #1
.L2:
.L6:
.L11:
        ldr     r1, .L49
        ldmia   r1, {r2, r3}
        sub     r2, r3, r2
        mov     r2, r2, asr #2
        add     r3, r2, r2, asl #3
        add     r3, r3, r3, asl #6
        add     r3, r2, r3, asl #3
        add     r3, r3, r3, asl #15
        add     r2, r2, r3, asl #3
        cmn     r6, r2
        ldr     r1, [r1, #0]
        bcc     .L48
        mvn     r0, #0
.L1:
        add     sp, sp, #8
        ldmfd   sp!, {r4, r5, r6, r7, r8, pc}
        .ident  "GCC: (GNU) 3.3.3"

(truncated to the end of x() .)

-- 
           Summary: ARM optimizer changes rsb/cmp to cmn, but condition
                    codes different
           Product: gcc
           Version: 3.3.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: marcus at tuells dot org
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: i586-linux
  GCC host triplet: i586-linux
GCC target triplet: arm-linux


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]