[patch] ARM: Fix miscompilation in arm.md:*minmax_arithsi. (PR target/51408)

Kazu_Hirata@mentor.com Kazu_Hirata@mentor.com
Sun Dec 4 13:33:00 GMT 2011


Hi,

Attached is a patch to fix miscompilation in
arm.md:*minmax_arithsi.

The following testcase, reduced from efgcvt_r.c:fcvt_r in glibc, gets
miscompiled:

extern void abort (void);

int __attribute__((noinline))
foo (int a, int b)
{
  int max = (b > 0) ? b : 0;
  return max - a;
}

int
main (void)
{
  if (foo (3, -1) != -3)
    abort ();
  return 0;
}

arm-none-eabi-gcc -O1 generates:

foo:
	@ Function supports interworking.
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	@ link register save eliminated.
	cmp	r1, #0
	rsbge	r0, r0, r1
	bx	lr

This would be equivalent to:

  return b >= 0 ? b - a : a;

which is different from:

  return b >= 0 ? b - a : -a;

That is, in assembly code, we should have an "else" clause like so:

	cmp	r1, #0
	rsbge	r0, r0, r1  <- then clause
	rsblt	r0, r0, #0  <- else clause
	bx	lr

The problem comes from the fact that arm.md:*minmax_arithsi does not
add the "else" clause even though MINUS is not commutative.

The patch fixes the problem by always requiring the "else" clause in
the MINUS case.

Tested by running gcc testsuite on various ARM subarchitectures.  OK
to apply?

Kazu Hirata

gcc/
2011-12-04  Kazu Hirata  <kazu@codesourcery.com>

	PR target/51408
	* config/arm/arm.md (*minmax_arithsi): Always require the else
	clause in the MINUS case.

gcc/testsuite/
2011-12-04  Kazu Hirata  <kazu@codesourcery.com>

	PR target/51408
	* gcc.dg/pr51408.c: New.

Index: gcc/config/arm/arm.md
===================================================================
--- gcc/config/arm/arm.md	(revision 181985)
+++ gcc/config/arm/arm.md	(working copy)
@@ -3413,7 +3413,7 @@
     bool need_else;
 
     if (which_alternative != 0 || operands[3] != const0_rtx
-        || (code != PLUS && code != MINUS && code != IOR && code != XOR))
+        || (code != PLUS && code != IOR && code != XOR))
       need_else = true;
     else
       need_else = false;
Index: gcc/testsuite/gcc.dg/pr51408.c
===================================================================
--- gcc/testsuite/gcc.dg/pr51408.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr51408.c	(revision 0)
@@ -0,0 +1,22 @@
+/* This testcase used to fail because of a bug in 
+   arm.md:*minmax_arithsi.  */
+
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+extern void abort (void);
+
+int __attribute__((noinline))
+foo (int a, int b)
+{
+  int max = (b > 0) ? b : 0;
+  return max - a;
+}
+
+int
+main (void)
+{
+  if (foo (3, -1) != -3)
+    abort ();
+  return 0;
+}



More information about the Gcc-patches mailing list