¿Cómo evitar que gcc optimice algunas declaraciones en C?

107

Para ensuciar una página (activando el bit sucio en la entrada de la tabla de páginas), toco los primeros bytes de la página así:

pageptr[0] = pageptr[0];

Pero en la práctica, gcc ignorará la declaración por eliminación de tienda muerta. Para evitar que gcc lo optimice, reescribo la declaración de la siguiente manera:

volatile int tmp;
tmp = pageptr[0];
pageptr[0] = tmp;

Parece que el truco funciona, pero algo feo. Me gustaría saber si hay alguna directiva o sintaxis que tenga el mismo efecto. Y no quiero usar una -O0bandera, ya que también traerá una gran penalización de rendimiento.

ZelluX
fuente
8
@Mark -O0 detendrá la optimización, pero también ralentizará el rendimiento del programa. Solo quiero evitar la optimización de este fragmento de código: P
ZelluX
Me gustaría agregar que en el pasado, incluso el uso -O0no impedía la "optimización" del código muerto, por ejemplo, cuando GCC detecta que algún código no tiene efecto, simplemente lo elimina. AFAIK, esta es una etapa incluso antes -O0... Pero esa es solo mi experiencia
smoothware

Respuestas:

91

Desactivar la optimización soluciona el problema, pero no es necesario. Una alternativa más segura es hacer que sea ilegal que el compilador optimice la tienda usando el volatilecalificador de tipo.

// Assuming pageptr is unsigned char * already...
unsigned char *pageptr = ...;
((unsigned char volatile *)pageptr)[0] = pageptr[0];

El volatilecalificador de tipo indica al compilador que sea estricto con las cargas y los almacenes de memoria. Uno de los objetivos volatilees informar al compilador que el acceso a la memoria tiene efectos secundarios y, por lo tanto, debe conservarse. En este caso, la tienda tiene el efecto secundario de provocar un error de página y desea que el compilador conserve el error de página.

De esta manera, el código circundante aún se puede optimizar y su código es portátil para otros compiladores que no entienden la sintaxis #pragmao GCC __attribute__.

Dietrich Epp
fuente
2
Yo diría que esto es preferible a desactivar las optimizaciones. Aún puede beneficiarse de otras optimizaciones utilizando este método.
Ben S
3
La solución de Dietrich Epp no ​​funciona con el compilador ARM4.1 . Incluso la solución de ZelluX no funciona. El método alternativo para hacer que esto funcione para ARM4.1 está en la solución de ZelluX, hacer que ' temp ' sea una variable volátil global .
Oculus Dexter
1
Eso es bastante malo para dicho compilador.
Alexey Frunze
1
@Shocker: GCC aún puede optimizar la variable sin optimizar el acceso a la memoria real. Esos son temas diferentes.
Dietrich Epp
2
@jww: este uso encaja con lo que se describe en esa publicación del blog. volatilesignifica que el acceso a la memoria debe ocurrir como está escrito, que es exactamente lo que queremos. En otras palabras, lo hemos pensado detenidamente y significa lo que creemos que significa.
Dietrich Epp
184

Puedes usar

#pragma GCC push_options
#pragma GCC optimize ("O0")

your code

#pragma GCC pop_options

para deshabilitar optimizaciones desde GCC 4.4.

Consulte la documentación de GCC si necesita más detalles.

Arado
fuente
3
Sin embargo, vale la pena señalar que esto solo funciona en funciones completas, no en declaraciones específicas: gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/… "Cada función que se define después de este punto es como si atributo (( optimizar ("STRING"))) se especificó para esa función. ".
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
134

En lugar de utilizar los nuevos pragmas, también puede utilizarlos __attribute__((optimize("O0")))para sus necesidades. Esto tiene la ventaja de que solo se aplica a una única función y no a todas las funciones definidas en el mismo archivo.

Ejemplo de uso:

void __attribute__((optimize("O0"))) foo(unsigned char data) {
    // unmodifiable compiler code
}
FRob
fuente
3
¿Qué sucede si no estoy usando una -Olevelopción pero usé las opciones individuales que se encienden por separado? (En mi caso, no puedo determinar cuál es la opción de optimización individual que está rompiendo el código) .
user2284570