/* * gcc-3.4 -O2 miscompiles this program on armv5b-unknown-linux: * a negative value for y is passed to I_lshift(), but I_lshift() * behaves as though y is non-negative (chooses the wrong branch * of the second if-statement). * * The original code comes from the bignum support code in the * runtime system for the Erlang functional language, where the * bug caused bignum right shifts to become left shifts. * * The bug occurs with gcc-3.4.4 and gcc-3.4-20051122. * Reducing optimisation level to -O1 masks the bug. * * The bug does not occur with gcc-3.3.6, which makes this a * regression. It also does not occur with gcc-4.0.2. */ #include <stdio.h>
/* Shift a bignum left or right. */ unsigned int I_lshift(unsigned short *x, unsigned int xl, int y, unsigned short *r) { if (xl == 1) return 1; { int ay = (y < 0) ? -y : y; int bw = ay / 16; unsigned int rl; if (y > 0) { /* shift left */ rl = xl + bw + 1; return rl; } else { /* shift right */ rl = xl - bw; r += (rl-1); xl -= bw; r -= xl; rl--; return rl; } } } unsigned short x[3] = { 0x0000, 0x0000, 0x0010 }; unsigned int xl = 3; int y = -8; unsigned short r[4]; /* should be { 0x0000, 0x1000 } after I_lshift() */ int main(void) { unsigned int res = I_lshift(x, xl, y, r); if (res != 2) { fprintf(stderr, "I_lshift() returned %u, gcc is buggy\n", res); return 1; } return 0; } -- Summary: gcc-3.4 wrong code for conditionals on arm Product: gcc Version: 3.4.5 Status: UNCONFIRMED Severity: major Priority: P3 Component: regression AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: mikpe at csd dot uu dot se GCC build triplet: armv5b-unknown-linux GCC host triplet: armv5b-unknown-linux GCC target triplet: armv5b-unknown-linux http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25133