From: Thad Smith on
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
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
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
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
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