9 votos

¿Por qué el compilador GCC omitiendo algún código?

No puedo entender por qué el compilador GCC cortar parte de mi código, mientras que preservar absolutamente la misma en el barrio?

El código de C:

#define setb_SYNCO do{(PORTA|= (1<<0));} while(0);

ISR(INT0_vect){
    unsigned char i;

    i = 10;
    while(i>0)i--;   // first pause - omitted

    setb_SYNCO;
    setb_GATE;
    i=30;
    clrb_SYNCO;
    while(i>0)i--;  // second pause - preserved
    clrb_GATE;
}

La parte correspondiente de la LSS (ensamblador de archivo, creado por el compilador):

ISR(INT0_vect){
  a4:   1f 92           push    r1
  a6:   0f 92           push    r0
  a8:   0f b6           in  r0, 0x3f    ; 63
  aa:   0f 92           push    r0
  ac:   11 24           eor r1, r1
  ae:   8f 93           push    r24
    unsigned char i;

    i = 10;
    while(i>0)i--;

    setb_SYNCO;
  b0:   d8 9a           sbi 0x1b, 0 ; 27
    setb_GATE;
  b2:   d9 9a           sbi 0x1b, 1 ; 27
    i=30;
    clrb_SYNCO;
  b4:   d8 98           cbi 0x1b, 0 ; 27
  b6:   8e e1           ldi r24, 0x1E   ; 30
  b8:   81 50           subi    r24, 0x01   ; 1
    while(i>0)i--;
  ba:   f1 f7           brne    .-4         ; 0xb8 <__vector_1+0x14>
    clrb_GATE;
  bc:   d9 98           cbi 0x1b, 1 ; 27
}
  be:   8f 91           pop r24
  c0:   0f 90           pop r0
  c2:   0f be           out 0x3f, r0    ; 63
  c4:   0f 90           pop r0
  c6:   1f 90           pop r1
  c8:   18 95           reti

Yo podría suponer que el compilador de averiguar que dicho código es ficticio y lo corta pero ¿por qué es preservar la misma en la final del código?

Es allí cualquier compilador de instrucciones para evitar tales optimización?

13voto

user4245 Puntos 324

Usted podría tratar de hacer el bucle realmente hacer algo. Tal y como está el compilador es, con bastante razón, diciendo: "Este bucle es no hacer nada - me voy a deshacerse de él".

Así que usted podría tratar de una construcción que se utilizan con frecuencia:

int i;
for (i = 0; i < 10; i++) {
    asm volatile ("nop");
}

Nota: no todos los objetivos para el compilador gcc utilizar el mismo ensamblado en línea de la sintaxis - puede que tenga que ajustar para su destino.

9voto

Sammo034 Puntos 26

Ya en uno de los comentarios que afirman que "cada una de las CPU de la garrapata es digno" yo sugiero utilizar algo de ensamblador para hacer su retrasos bucle justo como usted desea. Esta solución es superior a la de varios volatile o -O0 porque se hace claro cuál es su intención.

unsigned char i = 10;
__asm__ volatile ( "loop: subi    %0, 0x01\n\t"
                   "      brne    loop"
                   : "+rm" (i)
                   : /* no inputs */
                   : /* no dirty registers to decleare*/);

Que debe hacer el truco. La volátil cosa hay que decir que el compilador "sé que esto no hace nada, solo mantenerlo y confía en mí". Los tres asm "declaraciones" son bastante auto explicativo, puede utilizar cualquiera de los registros en lugar de r24, creo que el compilador le gusta registros más bajos así que puede que desee utilizar un alto. Después de la primera : debe incluir en la lista de salida (lectura y escritura) c variables, y no hay ninguno, después de la segunda : debe incluir en la lista de entrada (ronly) c variables, de nuevo, no hay ninguno, y el tercer parámetro es una lista separada por comas de modificación de los registros, en este caso r24. No estoy seguro de si usted debe incluir también el registro de estado desde la ZERO indicador cambia de curso, yo no la incluyen.

editar editar respuesta como OP solicitado. Algunas notas.

El "+rm" antes (i) significa que usted está dejando el compilador decide poner yo en memory o en un register. Eso es una cosa buena en la mayoría de los casos ya que el compilador puede optimizar si es gratis mejor. En tu caso yo creo que quiere mantener sólo la r restricción a la fuerza he de ser un registro.

6voto

user64204 Puntos 947

Sí se podría asumir que. Si se declara la variable i como la volatilidad de los que dicen que el compilador no a optimizar en la i.

1voto

Mehrdad Puntos 10388

Después de que el primer bucle i es una constante. La inicialización de i de bucle y el no hacer nada pero que producen un valor constante. Nada de lo dispuesto en la norma se especifica que este bucle debe ser compilado como-es. La norma no dice nada sobre el tiempo. El código compilado debe comportarse como si el bucle se hizo presente y se hace. Usted no puede de manera confiable decir que esta optimización se realizó bajo la norma (tiempo no cuenta).

El segundo bucle debe ser eliminado. Yo considero que es un error (o una falta de optimización) que no lo es. Después de que el bucle i es constante cero. El código debe ser reemplazado con la configuración i a cero.

Creo GCC mantiene i alrededor puramente por la razón de que usted realice un (opaco) acceso al puerto podría afectar a i.

Uso

asm volatile ("nop");

para engañar a GCC en la creencia de que el bucle se hace algo.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X