7
\$\begingroup\$

We're using the Lite version of the MicroChip PIC compiler so maybe that's the reason, but this simple one-bit shift is generating a loop where none is necessary. Since the shift count is 1 (a constant), I would expect the compiler to create no loop—an elementary optimization.

Is there a compiler optimization switch that would alleviate the loop? Here is the code for the shift:

    long foo;   // a 32-bit value

// Shift foo one bit. 
// A one-iteration loop is created!

    foo >>= 1;

And here is the compiler-generated code. As you can see, the shift is wrapped with a one-iteration loop.

  07F6    3001     MOVLW 0x1
  07F7    00F2     MOVWF 0x72
  07F8    37F6     ASRF 0x76, F
  07F9    0CF5     RRF 0x75, F
  07FA    0CF4     RRF 0x74, F
  07FB    0CF3     RRF 0x73, F
  07FC    0BF2     DECFSZ 0x72, F

EDIT

Compiler Version: HI-TECH C Compiler for PIC10/12/16 MCUs (Lite Mode) V9.81

\$\endgroup\$
8
  • 3
    \$\begingroup\$ Can you post exactly which compiler? Micochip now offers XC series of compilers in addition to C series compilers and since Microchip took over Hi-Tech, some people call Hi-Tech compilers microchip compilers too. \$\endgroup\$
    – AndrejaKo
    Jul 3, 2012 at 4:53
  • 4
    \$\begingroup\$ If you're going to agonize of individual instructions, don't use a compiler. \$\endgroup\$ Jul 3, 2012 at 11:21
  • 2
    \$\begingroup\$ @OlinLathrop - Nonsense. I would write a whole chapter about how wrong that statement is. This is not a case of agonising over individual instructions, this is a clue that the compiler is generating very poor performance code. \$\endgroup\$ Jul 3, 2012 at 14:52
  • 4
    \$\begingroup\$ @Rocket: You are missing the point, which is that the compiler will do what it does. You are caring about individual instructions since you looked at them and decided they were inefficient. Either you're using a high level language or you're not. If you are, don't complain about what goes on under the hood. If you want better, pay for the optimizer, get a better compiler (if that even exists), or write in assembler. \$\endgroup\$ Jul 3, 2012 at 15:18
  • 2
    \$\begingroup\$ @OlinLathrop - I wish I had space to go into great depth about why you are wrong here. \$\endgroup\$ Jul 3, 2012 at 16:05

3 Answers 3

2
\$\begingroup\$

Maybe this is caused by the lack of the optimization of the lite version.
You could try,

foo /= 2;

and see if it helps.

\$\endgroup\$
2
  • \$\begingroup\$ foo /= 2 generates 28 move instructions plus a CALL to a lengthy 32-bit division routine. \$\endgroup\$ Jul 3, 2012 at 15:46
  • \$\begingroup\$ Have you tried to compile the code with XC8? \$\endgroup\$ Jul 3, 2012 at 15:51
1
\$\begingroup\$

I tried various optimisation options, but nothing made the compiler produce sane code. I have had similar experiences with the C18 compiler too. Some of the code it generates it amazingly daft, and I ended up using several types of macros and tricks. In the end, I was able to get it to generate code nearly as good as hand optimised assembler while remaining fairly readable.

This not very nice macro generates the correct assembler for right shifting a long.

long foo;

#define R_SHIFT_LONG(x)     asm("asrf    _" #x "+3, f"); \
                            asm("rrf     _" #x "+2, f"); \
                            asm("rrf     _" #x "+1, f"); \
                            asm("rrf     _" #x "+0, f");

void main(void)
{
    foo=1234;

    R_SHIFT_LONG(foo);
}
\$\endgroup\$
4
  • \$\begingroup\$ I don't know what machine you think this macro is for, but there is no 8 bit PIC that has both a ASRF and RRCF instruction. \$\endgroup\$ Jul 3, 2012 at 23:59
  • \$\begingroup\$ How odd. The compiler didn't generate an error or warning, just silently converted the rrcf into rrf. \$\endgroup\$ Jul 4, 2012 at 0:06
  • \$\begingroup\$ Ah, so you are apparently assuming one of the enhanced 14 bit cores. When you guys are instruction peeping, you really need to say what PIC the code is for. \$\endgroup\$ Jul 4, 2012 at 0:08
  • \$\begingroup\$ @OlinLathrop - Well, I'm assuming the same instruction set that the OP is using. \$\endgroup\$ Jul 4, 2012 at 0:20
-1
\$\begingroup\$

Now that I've had a chance to look at your code, it's really not that unreasonable. Depending on the particular model PIC, it could have been done in 4 or 5 instructions, but only in the special case of shifting by one bit. It seems quite reasonable that the first thing the compiler does is write code for the general case where the shift is for N bits. I'd be surprised if it didn't recognize a shift by one bit as a special case with optimizations turned on, but how is this not exactly the kind of thing you expect it to do without optimization?

Again however, if you care about this level of detail you should be writing in assembler. By using a compiler you have deligated away detailed instruction generation. Besides, it's grossly unfair to evaluate any compiler with optimizations turned off.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ The compiler apparently does this even with optimisations enabled and set to 9. \$\endgroup\$ Jul 4, 2012 at 0:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.