This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug rtl-optimization/63209] New: [ARM] Wrong conditional move generated
- From: "xinliangli at gmail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Mon, 08 Sep 2014 18:44:28 +0000
- Subject: [Bug rtl-optimization/63209] New: [ARM] Wrong conditional move generated
- Auto-submitted: auto-generated
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;
}