PR target/9744
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 10 Jan 2014 15:12:03 +0000 (15:12 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 10 Jan 2014 15:12:03 +0000 (15:12 +0000)
gcc:
* aarch64-modes.def (CC_Zmode): New flags mode.
* aarch64.c (aarch64_select_cc_mode): Only allow NEG when the condition
represents an equality.
(aarch64_get_condition_code0): Handle CC_Zmode.
* aarch64.md (compare_neg<mode>): Restrict to equality operations.

gcc/testsuite:
* gcc.target/aarch64/cmn-neg.c: Use equality comparisons.
* gcc.target/aarch64/cmn-neg2.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@206529 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/aarch64/aarch64-modes.def
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/cmn-neg.c
gcc/testsuite/gcc.target/aarch64/cmn-neg2.c [new file with mode: 0644]

index 3bf4832..4811aa3 100644 (file)
@@ -1,3 +1,12 @@
+2014-01-10  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR target/9744
+       * aarch64-modes.def (CC_Zmode): New flags mode.
+       * aarch64.c (aarch64_select_cc_mode): Only allow NEG when the condition
+       represents an equality.
+       (aarch64_get_condition_code0): Handle CC_Zmode.
+       * aarch64.md (compare_neg<mode>): Restrict to equality operations.
+
 2014-01-10  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
 
        * config/s390/s390.c (s390_expand_tbegin): Remove jump over CC
index 3a56d62..1d2cc76 100644 (file)
@@ -24,6 +24,7 @@ CC_MODE (CC_SWP);
 CC_MODE (CC_ZESWP); /* zero-extend LHS (but swap to make it RHS).  */
 CC_MODE (CC_SESWP); /* sign-extend LHS (but swap to make it RHS).  */
 CC_MODE (CC_NZ);    /* Only N and Z bits of condition flags are valid.  */
+CC_MODE (CC_Z);     /* Only Z bit of condition flags is valid.  */
 
 /* Vector modes.  */
 VECTOR_MODES (INT, 8);        /*       V8QI V4HI V2SI.  */
index fe0aab3..3b1f6b5 100644 (file)
@@ -3326,17 +3326,24 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
          || GET_CODE (x) == NEG))
     return CC_NZmode;
 
-  /* A compare with a shifted or negated operand.  Because of canonicalization,
+  /* A compare with a shifted operand.  Because of canonicalization,
      the comparison will have to be swapped when we emit the assembly
      code.  */
   if ((GET_MODE (x) == SImode || GET_MODE (x) == DImode)
       && (GET_CODE (y) == REG || GET_CODE (y) == SUBREG)
       && (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
          || GET_CODE (x) == LSHIFTRT
-         || GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND
-         || GET_CODE (x) == NEG))
+         || GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND))
     return CC_SWPmode;
 
+  /* Similarly for a negated operand, but we can only do this for
+     equalities.  */
+  if ((GET_MODE (x) == SImode || GET_MODE (x) == DImode)
+      && (GET_CODE (y) == REG || GET_CODE (y) == SUBREG)
+      && (code == EQ || code == NE)
+      && GET_CODE (x) == NEG)
+    return CC_Zmode;
+
   /* A compare of a mode narrower than SI mode against zero can be done
      by extending the value in the comparison.  */
   if ((GET_MODE (x) == QImode || GET_MODE (x) == HImode)
@@ -3427,6 +3434,15 @@ aarch64_get_condition_code (rtx x)
        }
       break;
 
+    case CC_Zmode:
+      switch (comp_code)
+       {
+       case NE: return AARCH64_NE;
+       case EQ: return AARCH64_EQ;
+       default: gcc_unreachable ();
+       }
+      break;
+
     default:
       gcc_unreachable ();
       break;
index 4e838ee..3b5e92e 100644 (file)
 )
 
 (define_insn "*compare_neg<mode>"
-  [(set (reg:CC_SWP CC_REGNUM)
-       (compare:CC_SWP
+  [(set (reg:CC_Z CC_REGNUM)
+       (compare:CC_Z
         (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
         (match_operand:GPI 1 "register_operand" "r")))]
   ""
index a573813..3872369 100644 (file)
@@ -1,3 +1,9 @@
+2014-01-10  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR target/59744
+       * gcc.target/aarch64/cmn-neg.c: Use equality comparisons.
+       * gcc.target/aarch64/cmn-neg2.c: New test.
+
 2014-01-10  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/59374
index 05c8bbf..ab264e7 100644 (file)
@@ -6,7 +6,7 @@ extern void abort (void);
 void __attribute__ ((noinline))
 foo_s32 (int a, int b)
 {
-  if (a < -b)
+  if (a == -b)
     abort ();
 }
 /* { dg-final { scan-assembler "cmn\tw\[0-9\]" } } */
@@ -14,7 +14,7 @@ foo_s32 (int a, int b)
 void __attribute__ ((noinline))
 foo_s64 (long long a, long long b)
 {
-  if (a < -b)
+  if (a == -b)
     abort ();
 }
 /* { dg-final { scan-assembler "cmn\tx\[0-9\]" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/cmn-neg2.c b/gcc/testsuite/gcc.target/aarch64/cmn-neg2.c
new file mode 100644 (file)
index 0000000..ca45a53
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+extern void abort (void);
+
+/* It's unsafe to use CMN in these comparisons.  */
+
+void __attribute__ ((noinline))
+foo_s32 (int a, int b)
+{
+  if (a < -b)
+    abort ();
+}
+
+void __attribute__ ((noinline))
+foo_s64 (unsigned long long a, unsigned long long b)
+{
+  if (a > -b)
+    abort ();
+}
+
+
+int
+main (void)
+{
+  int a = 30;
+  int b = 42;
+  foo_s32 (a, b);
+  foo_s64 (a, b);
+  return 0;
+}
+/* { dg-final { scan-assembler-not "cmn\t" } } */
+
+/* { dg-final { cleanup-saved-temps } } */