Bucle extraño producido por el compilador PIC de MicroChip

Estamos usando la versión Lite del compilador MicroChip PIC, así que tal vez esa sea la razón, pero este simple cambio de un bit está generando un bucle donde no es necesario. Dado que el recuento de turnos es 1 (una constante), esperaría que el compilador no creara ningún bucle, una optimización elemental.

¿Existe un interruptor de optimización del compilador que alivie el bucle? Aquí está el código para el turno:

    long foo;   // a 32-bit value

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

    foo >>= 1;

Y aquí está el código generado por el compilador. Como puede ver, el cambio se envuelve con un bucle de una iteración.

  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

EDITAR

Versión del compilador: compilador HI-TECH C para MCU PIC10/12/16 (modo Lite) V9.81

¿Puedes publicar exactamente qué compilador? Micochip ahora ofrece la serie XC de compiladores además de los compiladores de la serie C y, dado que Microchip se hizo cargo de Hi-Tech, algunas personas también llaman compiladores de microchip a los compiladores de Hi-Tech.
Lo he notado hoy en la edición gratuita de MPLAB XC8 también; Me tiré del pelo porque no pude resistirme después de ver todas las cosas que hace XC8. Buenas noticias, no tienes que ir al peluquero por unos meses..
Si va a agonizar con instrucciones individuales, no use un compilador.
@OlinLathrop - Tonterías. Escribiría un capítulo entero sobre lo equivocada que es esa afirmación. Este no es un caso de angustiarse por las instrucciones individuales, es una pista de que el compilador está generando un código de muy bajo rendimiento.
@Rocket: te estás perdiendo el punto, que es que el compilador hará lo que hace. Te preocupas por las instrucciones individuales ya que las miraste y decidiste que eran ineficientes. O estás usando un lenguaje de alto nivel o no lo estás. Si es así, no se queje de lo que sucede debajo del capó. Si quiere algo mejor, pague por el optimizador, obtenga un mejor compilador (si es que existe) o escriba en ensamblador.
@OlinLathrop: desearía tener espacio para profundizar sobre por qué está equivocado aquí.
@Rocketmagnet puedes escribir múltiples comentarios :)
Es bueno escribir en C, por todas las razones obvias. Dejar caer al ensamblaje está bien cuando sea necesario. Estoy de acuerdo con @OlinLathrop en que la salida del compilador no debe obsesionarse; donde no estamos de acuerdo es que producir un bucle para un cambio de 1 bit es razonable en 2012.

Respuestas (3)

Tal vez esto se deba a la falta de optimización de la versión lite.
Tu podrías intentar,

foo /= 2;

y ver si ayuda.

foo /= 2 genera 28 instrucciones de movimiento más una LLAMADA a una larga rutina de división de 32 bits.
¿Has probado a compilar el código con XC8?

Probé varias opciones de optimización, pero nada hizo que el compilador produjera un código sensato. También he tenido experiencias similares con el compilador C18. Parte del código que genera es increíblemente tonto, y terminé usando varios tipos de macros y trucos. Al final, pude hacer que generara un código casi tan bueno como el ensamblador optimizado a mano sin dejar de ser bastante legible.

Esta macro no muy agradable genera el ensamblador correcto para un desplazamiento largo a la derecha.

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);
}
No sé para qué máquina cree que es esta macro, pero no hay un PIC de 8 bits que tenga instrucciones ASRF y RRCF.
Que extraño. El compilador no generó un error o advertencia, simplemente convirtió silenciosamente el rrcf en rrf.
Ah, entonces aparentemente estás asumiendo uno de los núcleos mejorados de 14 bits. Cuando están mirando las instrucciones, realmente necesitan decir para qué PIC es el código.
@OlinLathrop: bueno, asumo el mismo conjunto de instrucciones que usa el OP.

Ahora que he tenido la oportunidad de ver su código, realmente no es tan irrazonable. Dependiendo del modelo de PIC en particular, podría haberse hecho en 4 o 5 instrucciones, pero solo en el caso especial de desplazamiento de un bit . Parece bastante razonable que lo primero que haga el compilador sea escribir código para el caso general en el que el cambio es para N bits. Me sorprendería si no reconociera un cambio de un bit como un caso especial con optimizaciones activadas, pero ¿cómo es que esto no es exactamente el tipo de cosas que espera que haga sin optimización?

De nuevo, sin embargo, si le importa este nivel de detalle, debería escribir en ensamblador. Al usar un compilador, ha eliminado la generación de instrucciones detalladas. Además, es muy injusto evaluar cualquier compilador con las optimizaciones desactivadas.

El compilador aparentemente hace esto incluso con las optimizaciones habilitadas y configuradas en 9.