From: Thad Smith on 7 Jun 2010 22:34 David Brown wrote: > D Yuniskis wrote: >> Hi Meindert, >> >> Meindert Sprang wrote: >>> Unbelievable..... >>> >>> I'm playing around with the Microchip C18 compiler after a >>> hair-splitting >>> experience with CCS. Apparently the optimizer of C18 is not that >>> good. For >>> instance: LATF = addr >> 16; where addr is an uint32, is compiled >>> into a >>> loop where 4 registers really get shifted 16 times in a loop. Any decent >>> compiler should recognise that a shift by 16, stored to an 8 bit port >>> could >>> easily be done by simply accessing the 3rd byte.... sheesh.... >> >> Is LATF *defined* as a uint8_t? (i.e., does the compiler *know* it >> can discard all but the lowest 8 bits?) >> > > That's irrelevant (or should be!) - expressions are evaluated in their > own right, and /then/ cast to the type of the LHS. The compiler should, > as it does, initially treat it as a 32-bit shift, but it's a poor > compiler that can't optimise a 32-bit shift by 16 to something better > than this. Optimising it to a single byte transfer comes logically at a > later stage. And the later stage optimally comes before generating final code. It is logical that a good optimizer transform the statement to single byte move. -- Thad
From: George Neuner on 7 Jun 2010 22:34 On Mon, 7 Jun 2010 20:18:35 +0000 (UTC), Grant Edwards <invalid(a)invalid.invalid> wrote: >On 2010-06-07, George Neuner <gneuner2(a)comcast.net> wrote: > >> I've been programming since 1977 and I have never seen any compiler >> turn a long word shift (and/or mask) into a corresponding short word >> or byte access. Every compiler I have ever worked with would perform >> the shift. > >Really? > >I've seen quite a few compilers do that. For example, gcc for ARM >does: Interesting. But now that I think about it, I almost use shift with a constant count - it's almost always a computed shift - and even when the shift is constant, the value is often in a variable anyway due to surrounding processing. - What version of GCC is it? - What does it do if the shift count is a variable? - What does it do for ((ul & 0xFFFFFF) >> 8) or ((ul >> 8) & 0xFFFF)? If it recognizes the last as wanting just the middle word then that would be impressive. George
From: Grant Edwards on 7 Jun 2010 22:47 On 2010-06-08, George Neuner <gneuner2(a)comcast.net> wrote: > On Mon, 7 Jun 2010 20:18:35 +0000 (UTC), Grant Edwards ><invalid(a)invalid.invalid> wrote: > >>On 2010-06-07, George Neuner <gneuner2(a)comcast.net> wrote: >> >>> I've been programming since 1977 and I have never seen any compiler >>> turn a long word shift (and/or mask) into a corresponding short word >>> or byte access. Every compiler I have ever worked with would perform >>> the shift. >> >>Really? >> >>I've seen quite a few compilers do that. For example, gcc for ARM >>does: > > Interesting. But now that I think about it, I almost use shift with a > constant count - it's almost always a computed shift - and even when > the shift is constant, the value is often in a variable anyway due to > surrounding processing. > > - What version of GCC is it? 4.4.3 > - What does it do if the shift count is a variable? It uses a shift instruction. There's not really anyting else it could do with a variable shift count. > - What does it do for ((ul & 0xFFFFFF) >> 8) ldr r0, [r3, #0] mov r0, r0, asl #8 mov r0, r0, lsr #16 > or ((ul >> 8) & 0xFFFF)? ldr r0, [r3, #0] mov r0, r0, asl #8 mov r0, r0, lsr #16 > If it recognizes the last as wanting just the middle word then that > would be impressive. Recognizing the last two as wanting just the middle word is moot because that 16-bit word is misaligned and can't be accessed using a 16-bit load instruction. -- Grant
From: George Neuner on 8 Jun 2010 00:38 On Mon, 7 Jun 2010 20:18:35 +0000 (UTC), Grant Edwards <invalid(a)invalid.invalid> wrote: >On 2010-06-07, George Neuner <gneuner2(a)comcast.net> wrote: > >> I've been programming since 1977 and I have never seen any compiler >> turn a long word shift (and/or mask) into a corresponding short word >> or byte access. Every compiler I have ever worked with would perform >> the shift. > >Really? > >I've seen quite a few compilers do that. For example, gcc for ARM >does: > >------------------------------testit.c------------------------------ >unsigned long ul; > >unsigned char foo(void) >{ > return ul>>8; >} > >unsigned short bar(void) >{ > return ul>>16; >} >------------------------------testit.c------------------------------ > >$ /home/nextgen/toolchain/bin/arm-linux-gcc -c -Os -S -fomit-frame-pointer testit.c > >------------------------------testit.s------------------------------ > .arch armv5te >[...] > .file "testit.c" > .text > .align 2 > .global foo > .type foo, %function >foo: > ldr r3, .L3 > ldrb r0, [r3, #1] @ zero_extendqisi2 > bx lr >.L4: > .align 2 >.L3: > .word ul > .size foo, .-foo > .align 2 > .global bar > .type bar, %function >bar: > ldr r3, .L7 > ldrh r0, [r3, #2] > bx lr >.L8: > .align 2 >.L7: > .word ul > .size bar, .-bar > .comm ul,4,4 >[...] >------------------------------testit.s------------------------------ GCC 4.4.0 on x86 with the same flags gives: ------------------------------testit.s------------------------------ .file "testit.c" .text ..globl _foo .def _foo; .scl 2; .type 32; .endef _foo: movl _ul, %eax shrl $8, %eax ret ..globl _bar .def _bar; .scl 2; .type 32; .endef _bar: movzwl _ul+2, %eax ret .comm _ul, 16 # 4 ------------------------------testit.s------------------------------ It optimized the half shift but not the quarter shift. George
From: John Temples on 8 Jun 2010 00:48
On 2010-06-07, Meindert Sprang <ms(a)NOJUNKcustomORSPAMware.nl> wrote: > Apparently the optimizer of C18 is not that good. For > instance: LATF = addr >> 16; where addr is an uint32, is compiled into a > loop where 4 registers really get shifted 16 times in a loop. Here's what Hi-Tech's PIC18 compiler does: 853 ;t.c: 59: LATF = addr >> 16; 854 00FFFA C0FE FF8E movff _addr+2,3982 ;volatile -- John W. Temples, III |