[Bug target/60369] New: [PATCH] [TIC6X] new compiler intrinsics

wojtek.golf at interia dot pl gcc-bugzilla@gcc.gnu.org
Fri Feb 28 20:00:00 GMT 2014


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60369

            Bug ID: 60369
           Summary: [PATCH] [TIC6X] new compiler intrinsics
           Product: gcc
           Version: 4.8.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wojtek.golf at interia dot pl
              Host: Linux wmigda-desktop 3.11.0-13-generic #20-Ubuntu SMP
                    Wed Oct 23 17:26:33 UTC 2013 i686 i686 i686 GNU/Linux
            Target: tic6x-none-elf
             Build: 4.8.3 20140224 (prerelease)

Texas Instruments TIC6X compiler suite offers a number of compiler intrinsics
(see e.g. SPRU197u document) which are absent in gcc.
This is a patch proposal which is supposed to amend that. The scope is rather
limited as this would be my first contribution to gcc so I would like to treat
this as a pilot to see if I got everything right.

The intrinsics I would like to add with my patch are:
_swap2
_swap4
_dmv
_packlh2
_packhl2
_rotl

1. Legal Prerequisites
I think this proposal is small enough not to require for a separate copyright
disclaimer/assignment.

2. Coding Standards
Applied.

3. Testing Patches
I have prepared few testcases which check whether the instruction descriptions
are correct and whether the expected assembler instruction is generated for
each of the intrinsics.

4. Documentation Changes
TIC6X intrinsics are not listed in gcc documentation, so no update is
necessary.

5. Web Site Changes
As above.

6. Submitting Patches

A description of the problem/bug and how your patch addresses it.
GCC is missing some of the compiler intrinsics available in the Texas
Instruments TIC6X compiler suite. This patch attempts to extend the intrinsics
set offered by gcc.

Testcases
I have created a total of 12 testcases and placed them inside the
gcc/testsuite/gcc.target/tic6x folder.

ChangeLog
2014-02-28  Wojciech Migda  <wojtek.golf@interia.pl>

    * gcc/config/c6x/c6x.c: new intrinsics entries in enum c6x_builtins,
    c6x_init_builtins, bdesc_2arg, and bdesc_1arg. v2si_ftype_si_si definition.
    * gcc/config/c6x/c6x.md: new instruction definitions.
    * gcc/config/c6x/c6x_intrinsics.h: new intrinsics functions.
    * gcc/testsuite/gcc.target/tic6x/{dmv-O2-scan.c,dmv-O2-volatile-scan.c,
    packhl2-O2-scan.c,packhl2-O2-volatile-scan.c,packlh2-O2-scan.c,
    packlh2-O2-volatile-scan.c,rotl-O2-scan.c,rotl-O2-volatile-scan.c,
    swap2-O2-scan.c,swap2-O2-volatile-scan.c,swap4-O2-scan.c,
    swap4-O2-volatile-scan.c}: testcases for new intrinsics.

Bootstrapping and testing
Host: Linux wmigda-desktop 3.11.0-13-generic #20-Ubuntu SMP Wed Oct 23 17:26:33
UTC 2013 i686 i686 i686 GNU/Linux
Target: tic6x-none-elf
Results for the new testcases (run with make check-gcc
RUNTESTFLAGS="CFLAGS_FOR_TARGET='$CFLAGS_FOR_TARGET
--sysroot=${CXTOOLS}${TRIPLET}/sysroot' -v -v tic6x.exp")
PASS: gcc.target/tic6x/dmv-O2-scan.c (test for excess errors)
PASS: gcc.target/tic6x/dmv-O2-scan.c scan-assembler \\(exit\\)
PASS: gcc.target/tic6x/dmv-O2-scan.c scan-assembler-not [\\t ]dmv[\\t ]
PASS: gcc.target/tic6x/dmv-O2-volatile-scan.c (test for excess errors)
PASS: gcc.target/tic6x/dmv-O2-volatile-scan.c scan-assembler dmv
PASS: gcc.target/tic6x/dmv-O2-volatile-scan.c scan-assembler-not \\(_dmv\\)
PASS: gcc.target/tic6x/packhl2-O2-scan.c (test for excess errors)
PASS: gcc.target/tic6x/packhl2-O2-scan.c scan-assembler \\(exit\\)
PASS: gcc.target/tic6x/packhl2-O2-scan.c scan-assembler-not [\\t ]packhl2[\\t ]
PASS: gcc.target/tic6x/packhl2-O2-volatile-scan.c (test for excess errors)
PASS: gcc.target/tic6x/packhl2-O2-volatile-scan.c scan-assembler packhl2
PASS: gcc.target/tic6x/packhl2-O2-volatile-scan.c scan-assembler-not
\\(_packhl2\\)
PASS: gcc.target/tic6x/packlh2-O2-scan.c (test for excess errors)
PASS: gcc.target/tic6x/packlh2-O2-scan.c scan-assembler \\(exit\\)
PASS: gcc.target/tic6x/packlh2-O2-scan.c scan-assembler-not [\\t ]packlh2[\\t ]
PASS: gcc.target/tic6x/packlh2-O2-volatile-scan.c (test for excess errors)
PASS: gcc.target/tic6x/packlh2-O2-volatile-scan.c scan-assembler packlh2
PASS: gcc.target/tic6x/packlh2-O2-volatile-scan.c scan-assembler-not
\\(_packlh2\\)
PASS: gcc.target/tic6x/rotl-O2-scan.c (test for excess errors)
PASS: gcc.target/tic6x/rotl-O2-scan.c scan-assembler \\(exit\\)
PASS: gcc.target/tic6x/rotl-O2-scan.c scan-assembler-not [\\t ]rotl[\\t ]
PASS: gcc.target/tic6x/rotl-O2-volatile-scan.c (test for excess errors)
PASS: gcc.target/tic6x/rotl-O2-volatile-scan.c scan-assembler rotl
PASS: gcc.target/tic6x/rotl-O2-volatile-scan.c scan-assembler-not \\(_rotl\\)
PASS: gcc.target/tic6x/swap2-O2-scan.c (test for excess errors)
PASS: gcc.target/tic6x/swap2-O2-scan.c scan-assembler \\(exit\\)
PASS: gcc.target/tic6x/swap2-O2-scan.c scan-assembler-not packlh2
PASS: gcc.target/tic6x/swap2-O2-scan.c scan-assembler-not _swap2
PASS: gcc.target/tic6x/swap2-O2-volatile-scan.c (test for excess errors)
PASS: gcc.target/tic6x/swap2-O2-volatile-scan.c scan-assembler packlh2
PASS: gcc.target/tic6x/swap2-O2-volatile-scan.c scan-assembler-not \\(_swap2\\)
PASS: gcc.target/tic6x/swap4-O2-scan.c (test for excess errors)
PASS: gcc.target/tic6x/swap4-O2-scan.c scan-assembler \\(exit\\)
PASS: gcc.target/tic6x/swap4-O2-scan.c scan-assembler-not [\\t ]swap4[\\t ]
PASS: gcc.target/tic6x/swap4-O2-volatile-scan.c (test for excess errors)
PASS: gcc.target/tic6x/swap4-O2-volatile-scan.c scan-assembler swap4
PASS: gcc.target/tic6x/swap4-O2-volatile-scan.c scan-assembler-not \\(_swap4\\)

The patch itself

diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index e0db8b12..2258c23 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -6364,6 +6364,12 @@ enum c6x_builtins
   C6X_BUILTIN_AVG2,
   C6X_BUILTIN_AVGU4,

+  C6X_BUILTIN_SWAP4,
+  C6X_BUILTIN_ROTL,
+  C6X_BUILTIN_PACKLH2,
+  C6X_BUILTIN_PACKHL2,
+  C6X_BUILTIN_DMV,
+
   C6X_BUILTIN_MAX
 };

@@ -6412,6 +6418,9 @@ c6x_init_builtins (void)
   tree v2si_ftype_v2hi_v2hi
     = build_function_type_list (V2SI_type_node, V2HI_type_node,
                 V2HI_type_node, NULL_TREE);
+  tree v2si_ftype_si_si
+    = build_function_type_list (V2SI_type_node, intSI_type_node,
+                intSI_type_node, NULL_TREE);

   def_builtin ("__builtin_c6x_sadd", int_ftype_int_int,
            C6X_BUILTIN_SADD);
@@ -6462,8 +6471,17 @@ c6x_init_builtins (void)
   def_builtin ("__builtin_c6x_extru", int_ftype_int_int,
            C6X_BUILTIN_EXTRU);

+
   def_builtin ("__builtin_c6x_abs", int_ftype_int, C6X_BUILTIN_ABS);
   def_builtin ("__builtin_c6x_abs2", v2hi_ftype_v2hi, C6X_BUILTIN_ABS2);
+
+  def_builtin ("__builtin_c6x_swap4", v2hi_ftype_v2hi, C6X_BUILTIN_SWAP4);
+  def_builtin ("__builtin_c6x_rotl", int_ftype_int_int, C6X_BUILTIN_ROTL);
+
+  def_builtin ("__builtin_c6x_packlh2", v2hi_ftype_v2hi_v2hi,
C6X_BUILTIN_PACKLH2);
+  def_builtin ("__builtin_c6x_packhl2", v2hi_ftype_v2hi_v2hi,
C6X_BUILTIN_PACKHL2);
+
+  def_builtin ("__builtin_c6x_dmv", v2si_ftype_si_si, C6X_BUILTIN_DMV);
 }


@@ -6501,13 +6519,21 @@ static const struct builtin_description bdesc_2arg[] =

   { CODE_FOR_clrr, "__builtin_c6x_clrr", C6X_BUILTIN_CLRR },
   { CODE_FOR_extr, "__builtin_c6x_extr", C6X_BUILTIN_EXTR },
-  { CODE_FOR_extru, "__builtin_c6x_extru", C6X_BUILTIN_EXTRU }
+  { CODE_FOR_extru, "__builtin_c6x_extru", C6X_BUILTIN_EXTRU },
+
+  { CODE_FOR_rotlsi3, "__builtin_c6x_rotl", C6X_BUILTIN_ROTL },
+
+  { CODE_FOR_packlh2v2hi, "__builtin_c6x_packlh2", C6X_BUILTIN_PACKLH2 },
+  { CODE_FOR_packhl2v2hi, "__builtin_c6x_packhl2", C6X_BUILTIN_PACKHL2 },
+
+  { CODE_FOR_dmvv2si, "__builtin_c6x_dmv", C6X_BUILTIN_DMV }
 };

 static const struct builtin_description bdesc_1arg[] =
 {
   { CODE_FOR_ssabssi2, "__builtin_c6x_abs", C6X_BUILTIN_ABS },
-  { CODE_FOR_ssabsv2hi2, "__builtin_c6x_abs2", C6X_BUILTIN_ABS2 }
+  { CODE_FOR_ssabsv2hi2, "__builtin_c6x_abs2", C6X_BUILTIN_ABS2 },
+  { CODE_FOR_bswapv2hi2, "__builtin_c6x_swap4", C6X_BUILTIN_SWAP4 }
 };

 /* Errors in the source file can cause expand_expr to return const0_rtx
diff --git a/gcc/config/c6x/c6x.md b/gcc/config/c6x/c6x.md
index e1c6f9a..e655411 100644
--- a/gcc/config/c6x/c6x.md
+++ b/gcc/config/c6x/c6x.md
@@ -3136,5 +3136,41 @@
   [(set_attr "units" "ls")
    (set_attr "cross" "n,n,y,y")])

+(define_insn "packlh2v2hi"
+  [(set (match_operand:V2HI 0 "register_operand" "=a,b,a,b")
+        (vec_concat:V2HI
+          (vec_select:HI (match_operand:V2HI 2 "register_operand" "a,b,?b,?a")
(parallel [(const_int 1)]))
+          (vec_select:HI (match_operand:V2HI 1 "register_operand" "a,b,a,b")  
(parallel [(const_int 0)]))
+        )
+  )]
+  "TARGET_INSNS_64"
+  "%|%.\\tpacklh2\\t%$\\t%1, %2, %0"
+  [(set_attr "units" "ls")
+   (set_attr "cross" "n,n,y,y")])
+
+(define_insn "packhl2v2hi"
+  [(set (match_operand:V2HI 0 "register_operand" "=a,b,a,b")
+        (vec_concat:V2HI
+          (vec_select:HI (match_operand:V2HI 2 "register_operand" "a,b,?b,?a")
(parallel [(const_int 0)]))
+          (vec_select:HI (match_operand:V2HI 1 "register_operand" "a,b,a,b")  
(parallel [(const_int 1)]))
+        )
+  )]
+  "TARGET_INSNS_64"
+  "%|%.\\tpackhl2\\t%$\\t%1, %2, %0"
+  [(set_attr "units" "ls")
+   (set_attr "cross" "n,n,y,y")])
+
+(define_insn "dmvv2si"
+  [(set (match_operand:V2SI 0 "register_operand" "=a,b,a,b")
+        (vec_concat:V2SI
+          (match_operand:SI 2 "register_operand" "a,b,?b,?a")
+          (match_operand:SI 1 "register_operand" "a,b,a,b")
+        )
+  )]
+  "TARGET_INSNS_64PLUS"
+  "%|%.\\tdmv\\t%$\\t%1, %2, %0"
+  [(set_attr "units" "s")
+   (set_attr "cross" "n,n,y,y")])
+
 (include "c6x-mult.md")
 (include "sync.md")
diff --git a/gcc/config/c6x/c6x_intrinsics.h b/gcc/config/c6x/c6x_intrinsics.h
index d768046..bd027e2 100644
--- a/gcc/config/c6x/c6x_intrinsics.h
+++ b/gcc/config/c6x/c6x_intrinsics.h
@@ -186,6 +186,41 @@ _subc (int src1, int src2)
   return __builtin_c6x_subc (src1, src2);
 }

+__extension__ static __inline unsigned __attribute__ ((__always_inline__))
+_swap4 (unsigned src)
+{
+  return (unsigned)__builtin_c6x_swap4 ((__v2hi)src);
+}
+
+__extension__ static __inline unsigned __attribute__ ((__always_inline__))
+_swap2 (unsigned src)
+{
+  return (unsigned)__builtin_c6x_packlh2 ((__v2hi)src, (__v2hi)src);
+}
+
+__extension__ static __inline unsigned __attribute__ ((__always_inline__))
+_rotl (unsigned src1, unsigned src2)
+{
+  return __builtin_c6x_rotl (src1, src2);
+}
+
+__extension__ static __inline unsigned __attribute__ ((__always_inline__))
+_packlh2 (unsigned src1, unsigned src2)
+{
+  return (unsigned)__builtin_c6x_packlh2 ((__v2hi)src1, (__v2hi)src2);
+}
+
+__extension__ static __inline unsigned __attribute__ ((__always_inline__))
+_packhl2 (unsigned src1, unsigned src2)
+{
+  return (unsigned)__builtin_c6x_packhl2 ((__v2hi)src1, (__v2hi)src2);
+}
+
+__extension__ static __inline long long __attribute__ ((__always_inline__))
+_dmv (unsigned src1, unsigned src2)
+{
+  return (long long)__builtin_c6x_dmv (src1, src2);
+}

 #ifdef __cplusplus
 }
diff --git a/gcc/testsuite/gcc.target/tic6x/dmv-O2-scan.c
b/gcc/testsuite/gcc.target/tic6x/dmv-O2-scan.c
new file mode 100644
index 0000000..f9ae4ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/dmv-O2-scan.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x+" } */
+/* { dg-final { scan-assembler "\\(exit\\)" } } */
+/* { dg-final { scan-assembler-not "\[\\t \]dmv\[\\t \]" } } */
+
+/*
+ *  Check if the instruction definition is correct so that it will allow
+ *  to evaluate and optimize away _dmv in the compile time.
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+int main (void)
+{
+  unsigned src1 = 0x12345678;
+  unsigned src2 = 0x87654321;
+  long long ex = 0x1234567887654321LL;
+
+  long long out = _dmv (src1, src2);
+  if (out != ex)
+    {
+      return 1;
+    }
+  else
+    {
+      exit (0);
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/dmv-O2-volatile-scan.c
b/gcc/testsuite/gcc.target/tic6x/dmv-O2-volatile-scan.c
new file mode 100644
index 0000000..dd13bd8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/dmv-O2-volatile-scan.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x+" } */
+/* { dg-final { scan-assembler "dmv" } } */
+/* { dg-final { scan-assembler-not "\\(_dmv\\)" } } */
+
+/*
+ * Check if _dmv is resolved to the correct machine instruction
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+long long fn_dmv (unsigned src1, unsigned src2)
+{
+  return _dmv (src1, src2);
+}
+
+int main (void)
+{
+  volatile unsigned src1 = 0x12345678;
+  volatile unsigned src2 = 0x87654321;
+  long long ex = 0x1234567887654321LL;
+
+  long long out = fn_dmv (src1, src2);
+  if (out != ex)
+    {
+      exit (1);
+    }
+  else
+    {
+      return 0;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/packhl2-O2-scan.c
b/gcc/testsuite/gcc.target/tic6x/packhl2-O2-scan.c
new file mode 100644
index 0000000..6bf17f1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/packhl2-O2-scan.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x" } */
+/* { dg-final { scan-assembler "\\(exit\\)" } } */
+/* { dg-final { scan-assembler-not "\[\\t \]packhl2\[\\t \]" } } */
+
+/*
+ *  Check if the instruction definition is correct so that it will allow
+ *  to evaluate and optimize away _packhl2 in the compile time.
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+int main (void)
+{
+  int in1 = 0x12345678;
+  int in2 = 0x87654321;
+  int ex = 0x12344321;
+
+  int out = _packhl2 (in1, in2);
+  if (out != ex)
+    {
+      return 1;
+    }
+  else
+    {
+      exit (0);
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/packhl2-O2-volatile-scan.c
b/gcc/testsuite/gcc.target/tic6x/packhl2-O2-volatile-scan.c
new file mode 100644
index 0000000..e3ca4da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/packhl2-O2-volatile-scan.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x" } */
+/* { dg-final { scan-assembler "packhl2" } } */
+/* { dg-final { scan-assembler-not "\\(_packhl2\\)" } } */
+
+/*
+ * Check if _packhl2 is resolved to the correct machine instruction
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+unsigned fn_packhl2 (unsigned x, unsigned y)
+{
+  return _packhl2 (x, y);
+}
+
+int main (void)
+{
+  volatile int in1 = 0x12345678;
+  volatile int in2 = 0x87654321;
+  int ex = 0x12344321;
+
+  int out = fn_packhl2 (in1, in2);
+  if (out != ex)
+    {
+      exit (1);
+    }
+  else
+    {
+      return 0;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/packlh2-O2-scan.c
b/gcc/testsuite/gcc.target/tic6x/packlh2-O2-scan.c
new file mode 100644
index 0000000..343d428
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/packlh2-O2-scan.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x" } */
+/* { dg-final { scan-assembler "\\(exit\\)" } } */
+/* { dg-final { scan-assembler-not "\[\\t \]packlh2\[\\t \]" } } */
+
+/*
+ *  Check if the instruction definition is correct so that it will allow
+ *  to evaluate and optimize away _packlh2 in the compile time.
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+int main (void)
+{
+  int in1 = 0x12345678;
+  int in2 = 0x87654321;
+  int ex = 0x56788765;
+
+  int out = _packlh2 (in1, in2);
+  if (out != ex)
+    {
+      return 1;
+    }
+  else
+    {
+      exit (0);
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/packlh2-O2-volatile-scan.c
b/gcc/testsuite/gcc.target/tic6x/packlh2-O2-volatile-scan.c
new file mode 100644
index 0000000..af624cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/packlh2-O2-volatile-scan.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x" } */
+/* { dg-final { scan-assembler "packlh2" } } */
+/* { dg-final { scan-assembler-not "\\(_packlh2\\)" } } */
+
+/*
+ * Check if _packlh2 is resolved to the correct machine instruction
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+unsigned fn_packlh2 (unsigned x, unsigned y)
+{
+  return _packlh2 (x, y);
+}
+
+int main (void)
+{
+  volatile int in1 = 0x12345678;
+  volatile int in2 = 0x87654321;
+  int ex = 0x56788765;
+
+  int out = fn_packlh2 (in1, in2);
+  if (out != ex)
+    {
+      exit (1);
+    }
+  else
+    {
+      return 0;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/rotl-O2-scan.c
b/gcc/testsuite/gcc.target/tic6x/rotl-O2-scan.c
new file mode 100644
index 0000000..58147a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/rotl-O2-scan.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x" } */
+/* { dg-final { scan-assembler "\\(exit\\)" } } */
+/* { dg-final { scan-assembler-not "\[\\t \]rotl\[\\t \]" } } */
+
+/*
+ *  Check if the instruction definition is correct so that it will allow
+ *  to evaluate and optimize away _rotl in the compile time.
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+int main (void)
+{
+  int in = 0x12345678;
+  int nbit = 1;
+  int ex;
+
+  ex = 0x2468ACF0;
+  int out = _rotl (in, nbit);
+  if (out != ex)
+    {
+      return 1;
+    }
+  else
+    {
+      exit (0);
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/rotl-O2-volatile-scan.c
b/gcc/testsuite/gcc.target/tic6x/rotl-O2-volatile-scan.c
new file mode 100644
index 0000000..a27921e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/rotl-O2-volatile-scan.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x" } */
+/* { dg-final { scan-assembler "rotl" } } */
+/* { dg-final { scan-assembler-not "\\(_rotl\\)" } } */
+
+/*
+ * Check if _rotl is resolved to the correct machine instruction
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+int fn_rotl (int x, int nbit)
+{
+  return _rotl (x, nbit);
+}
+
+int main (void)
+{
+  volatile int in = 0x12345678;
+  volatile int nbit = 1;
+  int ex;
+
+  ex = 0x2468ACF0;
+  int out = fn_rotl (in, nbit);
+  if (out != ex)
+    {
+      exit (1);
+    }
+  else
+    {
+      return 0;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/swap2-O2-scan.c
b/gcc/testsuite/gcc.target/tic6x/swap2-O2-scan.c
new file mode 100644
index 0000000..aceb266
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/swap2-O2-scan.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x" } */
+/* { dg-final { scan-assembler "\\(exit\\)" } } */
+/* { dg-final { scan-assembler-not "packlh2" } } */
+/* { dg-final { scan-assembler-not "_swap2" } } */
+
+/*
+ *  Check if the instruction definition is correct so that it will allow
+ *  to evaluate and optimize away _swap2 in the compile time.
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+int main (void)
+{
+  int in = 0x12345678;
+  int ex = 0x56781234;
+
+  int out = _swap2 (in);
+  if (out != ex)
+    {
+      return 1;
+    }
+  else
+    {
+      exit (0);
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/swap2-O2-volatile-scan.c
b/gcc/testsuite/gcc.target/tic6x/swap2-O2-volatile-scan.c
new file mode 100644
index 0000000..ada1a33
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/swap2-O2-volatile-scan.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x" } */
+/* { dg-final { scan-assembler "packlh2" } } */
+/* { dg-final { scan-assembler-not "\\(_swap2\\)" } } */
+
+/*
+ * Check if _swap2 is resolved to the correct machine instruction
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+unsigned fn_swap2 (unsigned x)
+{
+  return _swap2 (x);
+}
+
+int main (void)
+{
+  volatile int in = 0x12345678;
+  int ex = 0x56781234;
+
+  int out = fn_swap2 (in);
+  if (out != ex)
+    {
+      exit (1);
+    }
+  else
+    {
+      return 0;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/swap4-O2-scan.c
b/gcc/testsuite/gcc.target/tic6x/swap4-O2-scan.c
new file mode 100644
index 0000000..0d8c30d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/swap4-O2-scan.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x" } */
+/* { dg-final { scan-assembler "\\(exit\\)" } } */
+/* { dg-final { scan-assembler-not "\[\\t \]swap4\[\\t \]" } } */
+
+/*
+ *  Check if the instruction definition is correct so that it will allow
+ *  to evaluate and optimize away _swap4 in the compile time.
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+int main (void)
+{
+  int in = 0x12345678;
+  int ex = 0x34127856;
+
+  int out = _swap4 (in);
+  if (out != ex)
+    {
+      return 1;
+    }
+  else
+    {
+      exit (0);
+    }
+}
diff --git a/gcc/testsuite/gcc.target/tic6x/swap4-O2-volatile-scan.c
b/gcc/testsuite/gcc.target/tic6x/swap4-O2-volatile-scan.c
new file mode 100644
index 0000000..862c940
--- /dev/null
+++ b/gcc/testsuite/gcc.target/tic6x/swap4-O2-volatile-scan.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=c64x" } */
+/* { dg-final { scan-assembler "swap4" } } */
+/* { dg-final { scan-assembler-not "\\(_swap4\\)" } } */
+
+/*
+ * Check if _swap4 is resolved to the correct machine instruction
+ */
+
+#include <c6x_intrinsics.h>
+#include <stdlib.h>
+
+int fn_swap4 (int x)
+{
+  return _swap4 (x);
+}
+
+int main (void)
+{
+  volatile int in = 0x12345678;
+  int ex = 0x34127856;
+
+  int out = fn_swap4 (in);
+  if (out != ex)
+    {
+      exit (1);
+    }
+  else
+    {
+      return 0;
+    }
+}



More information about the Gcc-bugs mailing list