diff mbox

[ARM,3/3] Recognise bitwise operations leading to SImode rev16

Message ID 532969CA.8020903@arm.com
State New
Headers show

Commit Message

Kyrylo Tkachov March 19, 2014, 9:56 a.m. UTC
Hi all,

This is the arm equivalent of patch [2/3] in the series that adds combine 
patterns for the bitwise operations leading to a rev16 instruction.
It reuses the functions that were put in aarch-common.c to properly cost these 
operations.

I tried matching a DImode rev16 (with the intent of splitting it into two rev16 
ops) like aarch64 but combine wouldn't try to match that bitwise pattern in 
DImode like aarch64 does. Instead it tries various exotic combinations with subregs.

Tested arm-none-eabi, bootstrap on arm-none-linux-gnueabihf.

Ok for stage1?

[gcc/]
2014-03-19  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     * config/arm/arm.md (arm_rev16si2): New pattern.
     (arm_rev16si2_alt): Likewise.
     * config/arm/arm.c (arm_new_rtx_costs): Handle rev16 case.


[gcc/testsuite/]
2014-03-19  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     * gcc.target/arm/rev16.c: New test.

Comments

Ramana Radhakrishnan March 28, 2014, 2:19 p.m. UTC | #1
On Wed, Mar 19, 2014 at 9:56 AM, Kyrill Tkachov <kyrylo.tkachov@arm.com> wrote:
> Hi all,
>
> This is the arm equivalent of patch [2/3] in the series that adds combine
> patterns for the bitwise operations leading to a rev16 instruction.
> It reuses the functions that were put in aarch-common.c to properly cost
> these operations.
>
> I tried matching a DImode rev16 (with the intent of splitting it into two
> rev16 ops) like aarch64 but combine wouldn't try to match that bitwise
> pattern in DImode like aarch64 does. Instead it tries various exotic
> combinations with subregs.
>
> Tested arm-none-eabi, bootstrap on arm-none-linux-gnueabihf.
>
> Ok for stage1?

This is OK for stage1 .

Ramana

>
> [gcc/]
> 2014-03-19  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>
>     * config/arm/arm.md (arm_rev16si2): New pattern.
>     (arm_rev16si2_alt): Likewise.
>     * config/arm/arm.c (arm_new_rtx_costs): Handle rev16 case.
>
>
> [gcc/testsuite/]
> 2014-03-19  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>
>     * gcc.target/arm/rev16.c: New test.
diff mbox

Patch

commit 04e60723bd1fa2f8e2adcfeed676390643ffec0c
Author: Kyrylo Tkachov <kyrylo.tkachov@arm.com>
Date:   Tue Feb 25 15:26:52 2014 +0000

    [ARM] Implement SImode rev16

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 8d1d721..ed603f0 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -9716,8 +9716,17 @@  arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
       /* Vector mode?  */
       *cost = LIBCALL_COST (2);
       return false;
+    case IOR:
+      if (mode == SImode && arm_arch6 && aarch_rev16_p (x))
+        {
+          *cost = COSTS_N_INSNS (1);
+          if (speed_p)
+            *cost += extra_cost->alu.rev;
 
-    case AND: case XOR: case IOR:
+          return true;
+        }
+    /* Fall through.  */
+    case AND: case XOR:
       if (mode == SImode)
 	{
 	  enum rtx_code subcode = GET_CODE (XEXP (x, 0));
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 4df24a2..47bc747 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12668,6 +12668,44 @@ 
    (set_attr "type" "rev")]
 )
 
+;; There are no canonicalisation rules for the position of the lshiftrt, ashift
+;; operations within an IOR/AND RTX, therefore we have two patterns matching
+;; each valid permutation.
+
+(define_insn "arm_rev16si2"
+  [(set (match_operand:SI 0 "register_operand" "=l,l,r")
+        (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
+                                   (const_int 8))
+                        (match_operand:SI 3 "const_int_operand" "n,n,n"))
+                (and:SI (lshiftrt:SI (match_dup 1)
+                                     (const_int 8))
+                        (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
+  "arm_arch6
+   && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
+   && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
+  "rev16\\t%0, %1"
+  [(set_attr "arch" "t1,t2,32")
+   (set_attr "length" "2,2,4")
+   (set_attr "type" "rev")]
+)
+
+(define_insn "arm_rev16si2_alt"
+  [(set (match_operand:SI 0 "register_operand" "=l,l,r")
+        (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
+                                     (const_int 8))
+                        (match_operand:SI 2 "const_int_operand" "n,n,n"))
+                (and:SI (ashift:SI (match_dup 1)
+                                   (const_int 8))
+                        (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
+  "arm_arch6
+   && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
+   && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
+  "rev16\\t%0, %1"
+  [(set_attr "arch" "t1,t2,32")
+   (set_attr "length" "2,2,4")
+   (set_attr "type" "rev")]
+)
+
 (define_expand "bswaphi2"
   [(set (match_operand:HI 0 "s_register_operand" "=r")
 	(bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
diff --git a/gcc/testsuite/gcc.target/arm/rev16.c b/gcc/testsuite/gcc.target/arm/rev16.c
new file mode 100644
index 0000000..1c869b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/rev16.c
@@ -0,0 +1,35 @@ 
+/* { dg-options "-O2" } */
+/* { dg-do run } */
+
+extern void abort (void);
+
+typedef unsigned int __u32;
+
+__u32
+__rev16_32_alt (__u32 x)
+{
+  return (((__u32)(x) & (__u32)0xff00ff00UL) >> 8)
+         | (((__u32)(x) & (__u32)0x00ff00ffUL) << 8);
+}
+
+__u32
+__rev16_32 (__u32 x)
+{
+  return (((__u32)(x) & (__u32)0x00ff00ffUL) << 8)
+         | (((__u32)(x) & (__u32)0xff00ff00UL) >> 8);
+}
+
+int
+main (void)
+{
+  volatile __u32 in32 = 0x12345678;
+  volatile __u32 expected32 = 0x34127856;
+
+  if (__rev16_32 (in32) != expected32)
+    abort ();
+
+  if (__rev16_32_alt (in32) != expected32)
+    abort ();
+
+  return 0;
+}