From 46b590a11bdd28eb5f00c5752617b710e04fbffc Mon Sep 17 00:00:00 2001 From: rearnsha Date: Fri, 10 Jan 2014 15:12:03 +0000 Subject: [PATCH] PR target/9744 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): 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 | 9 ++++++++ gcc/config/aarch64/aarch64-modes.def | 1 + gcc/config/aarch64/aarch64.c | 22 ++++++++++++++++--- gcc/config/aarch64/aarch64.md | 4 ++-- gcc/testsuite/ChangeLog | 6 +++++ gcc/testsuite/gcc.target/aarch64/cmn-neg.c | 4 ++-- gcc/testsuite/gcc.target/aarch64/cmn-neg2.c | 34 +++++++++++++++++++++++++++++ 7 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/cmn-neg2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3bf4832..4811aa3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2014-01-10 Richard Earnshaw + + 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): Restrict to equality operations. + 2014-01-10 Andreas Krebbel * config/s390/s390.c (s390_expand_tbegin): Remove jump over CC diff --git a/gcc/config/aarch64/aarch64-modes.def b/gcc/config/aarch64/aarch64-modes.def index 3a56d62..1d2cc76 100644 --- a/gcc/config/aarch64/aarch64-modes.def +++ b/gcc/config/aarch64/aarch64-modes.def @@ -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. */ diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index fe0aab3..3b1f6b5 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -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; diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 4e838ee..3b5e92e 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -1250,8 +1250,8 @@ ) (define_insn "*compare_neg" - [(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")))] "" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a573813..3872369 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2014-01-10 Richard Earnshaw + + 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 PR tree-optimization/59374 diff --git a/gcc/testsuite/gcc.target/aarch64/cmn-neg.c b/gcc/testsuite/gcc.target/aarch64/cmn-neg.c index 05c8bbf..ab264e7 100644 --- a/gcc/testsuite/gcc.target/aarch64/cmn-neg.c +++ b/gcc/testsuite/gcc.target/aarch64/cmn-neg.c @@ -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 index 0000000..ca45a53 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cmn-neg2.c @@ -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 } } */ -- 2.7.4