¿Por qué el compilador no usa directamente LSR?

10

Hola, he estado trabajando en un proyecto usando un Arduino Uno (por lo tanto, ATmega328p) donde el tiempo es bastante importante y quería ver en qué instrucciones estaba compilando el código el compilador. Y allí tengo un uint8_t que me desplazo un bit hacia la derecha en cada iteración usando data >>= 1 y parece que el compilador tradujo esto en 5 instrucciones ( data está en r24 ):

mov     r18, r24
ldi     r19, 0x00
asr     r19
ror     r18
mov     r24, r18

Pero si miro la documentación del conjunto de instrucciones, veo una instrucción que hace exactamente esto: lsr r24

¿Ignoro algo o por qué el compilador no usa esto también? Los registros r18 y r19 no se utilizan en ningún otro lugar.

Estoy usando un Ardunio pero si estoy en lo correcto, solo usa el compilador normal avr-gcc . Este es el código (recortado) que genera la secuencia:

ISR(PCINT0_vect) {
    uint8_t data = 0;
    for (uint8_t i = 8; i > 0; --i) {
//        asm volatile ("lsr %0": "+w" (data));
        data >>= 1;
        if (PINB & (1 << PB0))
            data |= 0x80;
    }
    host_data = data;
}

Por lo que puedo ver, el IDE de Ardunino está utilizando el compilador AVR gcc proporcionado por el sistema que es la versión 6.2.0-1.fc24. Ambos se instalan a través del gestor de paquetes, por lo que deberían estar actualizados.

    
pregunta xZise

1 respuesta

18

De acuerdo con la especificación del lenguaje C, cualquier valor cuyo tamaño sea menor que el de int (depende del compilador en particular; en su caso int tiene un ancho de 16 bits) involucrado en cualquier operación (en su caso >> ) se ha enviado a un int antes de la operación.
Este comportamiento del compilador se llama promoción de enteros .

Y eso es exactamente lo que hizo el compilador:

  • r19 = 0 es el MSByte del valor promovido de enteros de data .
  • (r19, r18) representa el valor total promovido por enteros de data que luego se desplaza hacia la derecha en un bit en asr r19 y ror 18 .
  • El resultado se vuelve a devolver implícitamente a la variable uint8_t variable data :
    mov r24, r18 , es decir, el MSByte en r19 se desecha.

Editar:
Por supuesto, el complaciente podría optimizar el código.
Tratando de reproducir el problema encontré que al menos con avr-gcc versión 4.9.2 el problema no se produce. Crea código muy eficiente, es decir, C-line   data >>= 1; se compila en una sola instrucción lsr r24 . Así que quizás estás usando una versión de compilador muy antigua.

    
respondido por el Curd

Lea otras preguntas en las etiquetas