This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug rtl-optimization/63209] New: [ARM] Wrong conditional move 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;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]