[AArch64] Compare Negative instruction in shift and extend mode

Submitted by Hurugalawadi, Naveen on April 10, 2013, 10:35 a.m.

Details

Message ID F3068DEED1A463459E0887A091B1549312369D71@BY2PRD0710MB364.namprd07.prod.outlook.com
State New
Headers show

Commit Message

Hurugalawadi, Naveen April 10, 2013, 10:35 a.m.
Hi,

Please find attached the patch that implements compare negative
instruction with shift and extend mode for aarch64 target.
Testcase have been added for compare and compare negative instruction.

Please review the same and let me know if there should be any 
modifications in the patch.
 
Build and tested on aarch64-thunder-elf (using Cavium's internal
simulator). No new regressions.

Thanks,
Naveen

gcc/

2013-04-10   Naveen H.S  <Naveen.Hurugalawadi@caviumnetworks.com>

	* config/aarch64/aarch64.c (aarch64_select_cc_mode): Use NEG
	code in CC_SWP mode.
	* config/aarch64/aarch64.md (*cmn_swp_<shift>_reg<mode>): New
	pattern.
	(*cmn_swp_<optab><ALLX:mode>_reg<GPI:mode>): New pattern.

gcc/testsuite/

2013-04-10   Naveen H.S  <Naveen.Hurugalawadi@caviumnetworks.com>

	* gcc.target/aarch64/cmn-1.c: New.
	* gcc.target/aarch64/cmp.c: New.

Comments

Marcus Shawcroft April 10, 2013, 5:28 p.m.
On 10/04/13 11:35, Hurugalawadi, Naveen wrote:

> +(define_insn "*cmn_swp_<optab><ALLX:mode>_reg<GPI:mode>"
> +  [(set (reg:CC_SWP CC_REGNUM)
> +	(compare:CC_SWP (ANY_EXTEND:GPI
> +			 (match_operand:ALLX 0 "register_operand" "r"))
> +			(neg:GPI (match_operand:GPI 1 "register_operand" "r"))))]


Umm, I'm not convinced, are you sure this placement of EXTEND and NEG in 
the RTL representation of CMN are correct?

> --- gcc/testsuite/gcc.target/aarch64/cmn-1.c	1970-01-01 05:30:00.000000000 +0530
> +++ gcc/testsuite/gcc.target/aarch64/cmn-1.c	2013-04-10 12:27:17.845318216 +0530
> @@ -0,0 +1,134 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 --save-temps" } */

At the point that these CMN optimizations kick in, GCC is clever enough 
to inline and fold main() to nothing, in effect CMN instruction 
generated never executes and the test cases all pass...

Try this instead:

 > +/* { dg-options "-O2 -fno-line --save-temps" } */

this will result in the test case failing.

Cheers
/Marcus

Patch hide | download patch | download mbox

--- gcc/config/aarch64/aarch64.c	2013-04-09 11:58:48.650789435 +0530
+++ gcc/config/aarch64/aarch64.c	2013-04-10 13:20:12.625311883 +0530
@@ -3094,7 +3094,8 @@  aarch64_select_cc_mode (RTX_CODE code, r
      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 (y) == REG || GET_CODE (y) == SUBREG
+	  || GET_CODE (y) == NEG)
       && (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
 	  || GET_CODE (x) == LSHIFTRT
 	  || GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND))
--- gcc/config/aarch64/aarch64.md	2013-04-09 11:58:48.646789435 +0530
+++ gcc/config/aarch64/aarch64.md	2013-04-10 12:31:40.393317692 +0530
@@ -2190,7 +2190,28 @@ 
    (set_attr "mode" "<GPI:MODE>")]
 )
 
+(define_insn "*cmn_swp_<shift>_reg<mode>"
+  [(set (reg:CC_SWP CC_REGNUM)
+	(compare:CC_SWP (ASHIFT:GPI
+			 (match_operand:GPI 0 "register_operand" "r")
+			 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
+			(neg:GPI (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ"))))]
+  ""
+  "cmn\\t%<w>2, %<w>0, <shift> %1"
+  [(set_attr "v8type" "alus_shift")
+   (set_attr "mode" "<MODE>")]
+)
 
+(define_insn "*cmn_swp_<optab><ALLX:mode>_reg<GPI:mode>"
+  [(set (reg:CC_SWP CC_REGNUM)
+	(compare:CC_SWP (ANY_EXTEND:GPI
+			 (match_operand:ALLX 0 "register_operand" "r"))
+			(neg:GPI (match_operand:GPI 1 "register_operand" "r"))))]
+  ""
+  "cmn\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
+  [(set_attr "v8type" "alus_ext")
+   (set_attr "mode" "<GPI:MODE>")]
+)
 ;; -------------------------------------------------------------------
 ;; Store-flag and conditional select insns
 ;; -------------------------------------------------------------------
--- gcc/testsuite/gcc.target/aarch64/cmn-1.c	1970-01-01 05:30:00.000000000 +0530
+++ gcc/testsuite/gcc.target/aarch64/cmn-1.c	2013-04-10 12:27:17.845318216 +0530
@@ -0,0 +1,134 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+extern void abort (void);
+
+int
+cmn_si_test1 (int a, int b, int c)
+{
+  /* { dg-final { scan-assembler "cmn\tw\[0-9\]+, w\[0-9\]+" } } */
+  if (a + b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+int
+cmn_si_test2 (int a, int b, int c)
+{
+  /* { dg-final { scan-assembler "cmn\tw\[0-9\]+, w\[0-9\]+, asr 3" } } */
+  if ((a >> 3) + b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+int
+cmn_si_test3 (char a, int b, int c)
+{
+  /* { dg-final { scan-assembler "cmn\tw\[0-9\]+, w\[0-9\]+, uxtb" } } */
+  if (a > -b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+typedef long long s64;
+
+s64
+cmn_di_test1 (s64 a, s64 b, s64 c)
+{
+  /* { dg-final { scan-assembler "cmn\tx\[0-9\]+, x\[0-9\]+" } } */
+  if (a + b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+s64
+cmn_di_test2 (s64 a, s64 b, s64 c)
+{
+  /* { dg-final { scan-assembler "cmn\tx\[0-9\]+, x\[0-9\]+, asr 3" } } */
+  if ((a >> 3) + b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+s64
+cmn_di_test3 (int a, s64 b, s64 c)
+{
+  /* { dg-final { scan-assembler "cmn\tx\[0-9\]+, x\[0-9\]+, sxtw" } } */
+  if (a > -b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+int main ()
+{
+  int x;
+  s64 y;
+
+  x = cmn_si_test1 (2, 12, 5);
+  if (x != 7)
+    abort ();
+
+  x = cmn_si_test1 (1, 2, 32);
+  if (x != 33)
+    abort ();
+
+  x = cmn_si_test2 (7, 5, 15);
+  if (x != 22)
+    abort ();
+
+  x = cmn_si_test2 (12, 1, 3);
+  if (x != 15)
+    abort ();
+
+  x = cmn_si_test3 (13, 14, 5);
+  if (x != 18)
+    abort ();
+
+  x = cmn_si_test3 (15, 21, 2);
+  if (x != 17)
+    abort ();
+
+  y = cmn_di_test1 (0x20202020ll,
+		    0x65161611ll,
+		    0x42434243ll);
+  if (y != 0x62636263ll)
+    abort ();
+
+  y = cmn_di_test1 (0x1010101010101ll,
+		    0x123456789abcdll,
+		    0x5555555555555ll);
+  if (y != 0x6565656565656ll)
+    abort ();
+
+  y = cmn_di_test2 (0x31313131ll,
+		    0x35466561ll,
+		    0x42434243ll);
+  if (y != 0x73747374ll)
+    abort ();
+
+  y = cmn_di_test2 (0x101010101ll,
+		    0x123456789ll,
+		    0x555555555ll);
+  if (y != 0x656565656ll)
+    abort ();
+
+  y = cmn_di_test3 (0x62523781ll,
+		    0x64234978ll,
+		    0x12345123ll);
+  if (y != 0x748688a4ll)
+    abort ();
+
+  y = cmn_di_test3 (0x76352626ll,
+		    0x10101010ll,
+		    0x21212121ll);
+  if (y != 0x97564747ll)
+    abort ();
+
+  return 0;
+}
--- gcc/testsuite/gcc.target/aarch64/cmp.c	1970-01-01 05:30:00.000000000 +0530
+++ gcc/testsuite/gcc.target/aarch64/cmp.c	2013-04-10 12:28:12.897318106 +0530
@@ -0,0 +1,134 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+extern void abort (void);
+
+int
+cmp_si_test1 (int a, int b, int c)
+{
+  /* { dg-final { scan-assembler "cmp\tw\[0-9\]+, w\[0-9\]+" } } */
+  if (a > b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+int
+cmp_si_test2 (int a, int b, int c)
+{
+  /* { dg-final { scan-assembler "cmp\tw\[0-9\]+, w\[0-9\]+, asr 3" } } */
+  if ((a >> 3) > b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+int
+cmp_si_test3 (int a, long b, int c)
+{
+  /* { dg-final { scan-assembler "cmp\tx\[0-9\]+, x\[0-9\]+, sxtw" } } */
+  if (a > b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+typedef long long s64;
+
+s64
+cmp_di_test1 (s64 a, s64 b, s64 c)
+{
+  /* { dg-final { scan-assembler "cmp\tx\[0-9\]+, x\[0-9\]+" } } */
+  if (a > b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+s64
+cmp_di_test2 (s64 a, s64 b, s64 c)
+{
+  /* { dg-final { scan-assembler "cmp\tx\[0-9\]+, x\[0-9\]+, asr 3" } } */
+  if ((a >> 3) > b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+int
+cmp_di_test3 (int a, s64 b, s64 c)
+{
+  /* { dg-final { scan-assembler "cmp\tx\[0-9\]+, x\[0-9\]+, sxtw" } } */
+  if (a > b)
+    return a + c;
+  else
+    return a + b + c;
+}
+
+int main ()
+{
+  int x;
+  s64 y;
+
+  x = cmp_si_test1 (2, 12, 5);
+  if (x != 19)
+    abort ();
+
+  x = cmp_si_test1 (1, 2, 32);
+  if (x != 35)
+    abort ();
+
+  x = cmp_si_test2 (7, 5, 15);
+  if (x != 27)
+    abort ();
+
+  x = cmp_si_test2 (12, 1, 3);
+  if (x != 16)
+    abort ();
+
+  x = cmp_si_test3 (13, 14, 5);
+  if (x != 32)
+    abort ();
+
+  x = cmp_si_test3 (15, 21, 2);
+  if (x != 38)
+    abort ();
+
+  y = cmp_di_test1 (0x20202020ll,
+		    0x65161611ll,
+		    0x42434243ll);
+  if (y != 0xc7797874ll)
+    abort ();
+
+  y = cmp_di_test1 (0x1010101010101ll,
+		    0x123456789abcdll,
+		    0x5555555555555ll);
+  if (y != 0x7799bbde00223ll)
+    abort ();
+
+  y = cmp_di_test2 (0x31313131ll,
+		    0x35466561ll,
+		    0x42434243ll);
+  if (y != 0xa8bad8d5ll)
+    abort ();
+
+  y = cmp_di_test2 (0x101010101ll,
+		    0x123456789ll,
+		    0x555555555ll);
+  if (y != 0x7799bbddfll)
+    abort ();
+
+  y = cmp_di_test3 (0x62523781ll,
+		    0x64234978ll,
+		    0x12345123ll);
+  if (y != 0xffffffffd8a9d21cll)
+    abort ();
+
+  y = cmp_di_test3 (0x76352626ll,
+		    0x10101010ll,
+		    0x21212121ll);
+  if (y != 0xffffffff97564747ll)
+    abort ();
+
+  return 0;
+}