[Bug rtl-optimization/63209] New: [ARM] Wrong conditional move generated
xinliangli at gmail dot com
gcc-bugzilla@gcc.gnu.org
Mon Sep 8 18:44:00 GMT 2014
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;
}
More information about the Gcc-bugs
mailing list