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


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

  • 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 '12 at 4:53
  • 4
    \$\begingroup\$ If you're going to agonize of individual instructions, don't use a compiler. \$\endgroup\$ – Olin Lathrop Jul 3 '12 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\$ – Rocketmagnet Jul 3 '12 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\$ – Olin Lathrop Jul 3 '12 at 15:18
  • 2
    \$\begingroup\$ @OlinLathrop - I wish I had space to go into great depth about why you are wrong here. \$\endgroup\$ – Rocketmagnet Jul 3 '12 at 16:05

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

foo /= 2;

and see if it helps.

| improve this answer | |
  • \$\begingroup\$ foo /= 2 generates 28 move instructions plus a CALL to a lengthy 32-bit division routine. \$\endgroup\$ – I. J. Kennedy Jul 3 '12 at 15:46
  • \$\begingroup\$ Have you tried to compile the code with XC8? \$\endgroup\$ – Bruno Ferreira Jul 3 '12 at 15:51

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)

| improve this answer | |
  • \$\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\$ – Olin Lathrop Jul 3 '12 at 23:59
  • \$\begingroup\$ How odd. The compiler didn't generate an error or warning, just silently converted the rrcf into rrf. \$\endgroup\$ – Rocketmagnet Jul 4 '12 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\$ – Olin Lathrop Jul 4 '12 at 0:08
  • \$\begingroup\$ @OlinLathrop - Well, I'm assuming the same instruction set that the OP is using. \$\endgroup\$ – Rocketmagnet Jul 4 '12 at 0:20

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.

| improve this answer | |
  • 2
    \$\begingroup\$ The compiler apparently does this even with optimisations enabled and set to 9. \$\endgroup\$ – Rocketmagnet Jul 4 '12 at 0:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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