ARM GCC eliminando código requerido durante la optimización.
Tengo el siguiente código que realiza una conversión muy básica de una imagen de 16bpp a una imagen de 1bpp, el código funciona como se espera hasta que habilito las optimizaciones del compilador, momento en el que solo obtengo una imagen negra.
define RSCALE 5014709
define GSCALE 9848225
define BSCALE 1912602
uint16_t _convertBufferTo1bit(uint8_t* buffer, uint16_t size)
{
uint8_t* dst_ptr = buffer;
uint8_t* end_ptr = buffer + size;
uint16_t pos = 0;
uint8_t r, g, b, i;
uint32_t lum;
while(buffer < end_ptr)
{
for(i = 8; i > 0; i--)
{
r = (*buffer & 0xF8);
g = ((*buffer & 0x07) << 5);
buffer += 1;
g |= (*buffer & 0x03);
b = ((*buffer & 0x1F) << 3);
buffer += 1;
lum = ((RSCALE * r) + (GSCALE * g) + (BSCALE * b));
if(lum > 0x7FFFFFFF)
{
//White
dst_ptr[pos] |= (1 << (i-1));
}
else
{
//black
dst_ptr[pos] &= ~(1 << (i-1));
}
}
pos++;
}
return pos;
}
Cuando se mira el ensamblado decompilado, se puede ver que se ha eliminado la declaración if(lum > 0x7FFFFFFF)
y todos los cálculos asociados por el compilador. ¿Alguien puede ayudarme a entender por qué?
-O0 -std=c++17 -Wall -Wextra
https://godbolt.org/z/GhPezzh33
-O1 -std=c++17 -Wall -Wextra
https://godbolt.org/z/bn1M4319h
davy.ai
Parece que el compilador está optimizando el cálculo y la declaración
if
, ya que el valor resultante delum
siempre será menor o igual a0x7FFFFFFF
, debido a que todos los factores de escala son positivos y los valores de entrada (r
,g
yb
) son cada uno menor que0xFF
. Por lo tanto, la declaraciónif
siempre se evalúa como falsa y la optimización elimina el código innecesario.Para solucionar este problema, se podría cambiar
lum
a unint32_t
en lugar de unuint32_t
, para que la comparación con0x7FFFFFFF
dé el resultado esperado. Otra opción podría ser cambiar los factores de escala o los valores de entrada para asegurarse de quelum
pueda superar0x7FFFFFFF
en algunos casos, dependiendo de los requisitos específicos de su aplicación.