http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53138
Bug #: 53138 Summary: [4.7/4.8 Regression] spaceship operator miscompiled Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: target AssignedTo: bonz...@gnu.org ReportedBy: bonz...@gnu.org Target: x86_64-pc-linux-gnu This program is miscompiled at -O2: typedef struct sreal { unsigned sig; /* Significant. */ int exp; /* Exponent. */ } sreal; sreal_compare (sreal *a, sreal *b) { if (a->exp > b->exp) return 1; if (a->exp < b->exp) return -1; if (a->sig > b->sig) return 1; return -(a->sig < b->sig); } sreal a[] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }; int main() { int i, j; for (i = 0; i <= 3; i++) { for (j = 0; j < 3; j++) { if (i < j && sreal_compare(&a[i], &a[j]) != -1) abort(); if (i == j && sreal_compare(&a[i], &a[j]) != 0) abort(); if (i > j && sreal_compare(&a[i], &a[j]) != 1) abort(); } } } The problem is that the comparison on sig is compiled to this: movl (%rsi), %ecx cmpl %ecx, (%rdi) sbbl %edx, %edx cmovbe %edx, %eax ret but sbbl only preserves the carry flag, not the zero flag.