This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/14812] New: ARM optimizer changes rsb/cmp to cmn, but condition codes different
- From: "marcus at tuells dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 1 Apr 2004 19:46:25 -0000
- Subject: [Bug c++/14812] New: ARM optimizer changes rsb/cmp to cmn, but condition codes different
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
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