Patchwork [AArch64] Compare Negative instruction in shift and extend mode

login
register
mail settings
Submitter Hurugalawadi, Naveen
Date April 10, 2013, 10:35 a.m.
Message ID <F3068DEED1A463459E0887A091B1549312369D71@BY2PRD0710MB364.namprd07.prod.outlook.com>
Download mbox | patch
Permalink /patch/235354/
State New
Headers show

Comments

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.
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

--- 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;
+}