Compile the following function with options -Os -mthumb -march=armv5te int ldrb(unsigned char* p) { if (p[8] <= 0x7F) return 2; else return 5; }
Gcc generates following codes: push {lr} mov r3, #8 ldrsb r3, [r0, r3] mov r0, #2 cmp r3, #0 bge .L2 mov r0, #5 .L2: @ sp needed for prologue pop {pc} The source code if (p[8] <= 0x7F) is translated to: mov r3, #8 ldrsb r3, [r0, r3] cmp r3, #0 A better code sequence should be: ldrb r3, [r0, 8] cmp r3, 0x7F This can save one instruction. The tree dump shows in a very early pass (ldrb.c.003t.original) the comparison was transformed to if ((signed char) *(p + 8) >= 0) I guess gcc thinks comparing with 0 is much cheaper than comparing with other numbers. Am I right? Unfortunately in thumb mode, loading a signed byte costs more than loading an unsigned byte and comparing with 0 has same cost as comparing with 0x7F. -- Summary: unnecessary conversion from unsigned byte load to signed byte load Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: carrot at google dot com GCC build triplet: i686-linux GCC host triplet: i686-linux GCC target triplet: arm-eabi http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40603