https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63209
Bug ID: 63209 Summary: [ARM] Wrong conditional move generated Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: xinliangli at gmail dot com Created attachment 33460 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33460&action=edit patch file GCC (arm-unknown-linux-gnueabi) generates wrong code (O2) for the following program. The problem is that it uses a source register in the condition move that has already been overwritten in the previous move. The program produces output: top[-1]: ff7a7a7a top[0]: ff7a7a7a left: ff7b7b7b pred: ff7a7a7a pred != left The bad assembly code is: cmn r1, r2 mov r0, r3 movgt r0, r3 The expected output is: top[-1]: ff7a7a7a top[0]: ff7a7a7a left: ff7b7b7b pred: ff7b7b7b The expected assembly: cmn r1, r2 movle r0, r3 The attached patch fixed the problem. The patch passes regression test. // tests.c #include <stdio.h> static int Sub(int a, int b) { return b -a; } static unsigned Select(unsigned a, unsigned b, unsigned c) { const int pa_minus_pb = Sub((a >> 8) & 0xff, (b >> 8) & 0xff) + Sub((a >> 0) & 0xff, (b >> 0) & 0xff); return (pa_minus_pb <= 0) ? a : b; } __attribute__((noinline)) unsigned Predictor(unsigned left, const unsigned* const top) { const unsigned pred = Select(top[1], left, top[0]); return pred; } int main(void) { const unsigned top[2] = {0xff7a7a7a, 0xff7a7a7a}; const unsigned left = 0xff7b7b7b; const unsigned pred = Predictor(left, top /*+ 1*/); fprintf(stderr, "top[-1]: %8x top[0]: %8x left: %8x pred: %8x\n", top[0], top[1], left, pred); if (pred == left) return 0; fprintf(stderr, "pred != left\n"); return 1; }