This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC, patch] implement __builtin_bswap


This patch appears to implement all of builtin_bswap for SI and DImodes. I've tested it with mipsisa64-elf, mips-elf, x86-darwin, x86-linux without regressions. A good chunk of my testing was making sure that the hardware implementation for x86 matched the software implementation in libgcc. Any review of the SI and DImode routines in there would be appreciated.

The current testcases check that the instructions or libgcc routines are generated and work forward and backward.

A scanning routine to generate this automagically would be good, but I haven't done it yet.

Thoughts? OK for 4.3? Other feedback?

-eric

2006-07-10 Eric Christopher <echristo@apple.com>

	* optabs.c (init_optabs): Add bswap_optab.
	(init_integral_libfuncs): Ditto.
	* optabs.h (optab_index): Add OTI_bswap.
	(bswap_optab): New.
	* genopinit.c (optabs): Add handler for bswap_optab.
	* builtins.c (expand_builtin): Add BUILT_IN_BSWAP.
	* builtins.def (BUILT_IN_BSWAP): New.
	(BUILT_IN_BSWAPL): Ditto.
	(BUILT_IN_BSWAPLL): Ditto.
	* rtl.def: Add bswap.
	* libgcc2.c (bswapSI2): New.
	(bswapDI2): Ditto.
	* libgcc2.h (bswapSI2): Declare.
	(bswapDI2): Ditto.
	* mklibgcc.in (lib2funcs): Add __bswapsi2 and __bswapdi2.
	* libgcc-std.ver (GCC_4.2.0): Add __bswapsi2 and __bswapdi2.
	* config/i386/i386.h (x86_bswap): New.
	(TARGET_BSWAP): Ditto.
	* config/i386/i386.c (x86_bswap): New.
	* config/i386/i386.md (bswapsi2): New.
	(bswapdi2): Ditto.

2006-07-10 Eric Christopher <echristo@apple.com>

	* gcc.target/i386/builtin-bswap-1.c: New.
	* gcc.dg/builtin-bswap-1.c: Ditto.
	* gcc.dg/builtin-bswap-2.c: Ditto.
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	(revision 115311)
+++ gcc/optabs.c	(working copy)
@@ -5244,6 +5244,7 @@ init_optabs (void)
   absv_optab = init_optabv (ABS);
   addcc_optab = init_optab (UNKNOWN);
   one_cmpl_optab = init_optab (NOT);
+  bswap_optab = init_optab (BSWAP);
   ffs_optab = init_optab (FFS);
   clz_optab = init_optab (CLZ);
   ctz_optab = init_optab (CTZ);
@@ -5394,6 +5395,7 @@ init_optabs (void)
   init_integral_libfuncs (negv_optab, "negv", '2');
   init_floating_libfuncs (negv_optab, "neg", '2');
   init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
+  init_integral_libfuncs (bswap_optab, "bswap", '2');
   init_integral_libfuncs (ffs_optab, "ffs", '2');
   init_integral_libfuncs (clz_optab, "clz", '2');
   init_integral_libfuncs (ctz_optab, "ctz", '2');
Index: gcc/optabs.h
===================================================================
--- gcc/optabs.h	(revision 115311)
+++ gcc/optabs.h	(working copy)
@@ -146,6 +146,8 @@ enum optab_index
   /* Abs value */
   OTI_abs,
   OTI_absv,
+  /* Byteswap */
+  OTI_bswap,
   /* Bitwise not */
   OTI_one_cmpl,
   /* Bit scanning and counting */
@@ -315,6 +317,7 @@ extern GTY(()) optab optab_table[OTI_MAX
 #define abs_optab (optab_table[OTI_abs])
 #define absv_optab (optab_table[OTI_absv])
 #define one_cmpl_optab (optab_table[OTI_one_cmpl])
+#define bswap_optab (optab_table[OTI_bswap])
 #define ffs_optab (optab_table[OTI_ffs])
 #define clz_optab (optab_table[OTI_clz])
 #define ctz_optab (optab_table[OTI_ctz])
Index: gcc/genopinit.c
===================================================================
--- gcc/genopinit.c	(revision 115311)
+++ gcc/genopinit.c	(working copy)
@@ -148,6 +148,7 @@ static const char * const optabs[] =
   "atan_optab->handlers[$A].insn_code = CODE_FOR_$(atan$a2$)",
   "strlen_optab->handlers[$A].insn_code = CODE_FOR_$(strlen$a$)",
   "one_cmpl_optab->handlers[$A].insn_code = CODE_FOR_$(one_cmpl$a2$)",
+  "bswap_optab->handlers[$A].insn_code = CODE_FOR_$(bswap$a2$)",
   "ffs_optab->handlers[$A].insn_code = CODE_FOR_$(ffs$a2$)",
   "clz_optab->handlers[$A].insn_code = CODE_FOR_$(clz$a2$)",
   "ctz_optab->handlers[$A].insn_code = CODE_FOR_$(ctz$a2$)",
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 115311)
+++ gcc/builtins.c	(working copy)
@@ -5825,6 +5825,13 @@ expand_builtin (tree exp, rtx target, rt
       expand_stack_restore (TREE_VALUE (arglist));
       return const0_rtx;
 
+    CASE_INT_FN (BUILT_IN_BSWAP):
+      target = expand_builtin_unop (target_mode, arglist, target,
+				    subtarget, bswap_optab);
+      if (target)
+	return target;
+      break;
+
     CASE_INT_FN (BUILT_IN_FFS):
     case BUILT_IN_FFSIMAX:
       target = expand_builtin_unop (target_mode, arglist, target,
Index: gcc/builtins.def
===================================================================
--- gcc/builtins.def	(revision 115311)
+++ gcc/builtins.def	(working copy)
@@ -594,6 +594,9 @@ DEF_EXT_LIB_BUILTIN    (BUILT_IN_ALLOCA,
 DEF_GCC_BUILTIN        (BUILT_IN_APPLY, "apply", BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_ARGS_INFO, "args_info", BT_FN_INT_INT, ATTR_NULL)
+DEF_GCC_BUILTIN        (BUILT_IN_BSWAP, "bswap", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_BSWAPL, "bswapl", BT_FN_LONG_LONG, ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_BSWAPLL, "bswapll", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LIST)
 DEF_LIB_BUILTIN        (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LIST)
Index: gcc/rtl.def
===================================================================
--- gcc/rtl.def	(revision 115311)
+++ gcc/rtl.def	(working copy)
@@ -567,6 +567,9 @@ DEF_RTL_EXPR(ABS, "abs", "e", RTX_UNARY)
 /* Square root */
 DEF_RTL_EXPR(SQRT, "sqrt", "e", RTX_UNARY)
 
+/* Swap bytes.  */
+DEF_RTL_EXPR(BSWAP, "bswap", "e", RTX_UNARY)
+
 /* Find first bit that is set.
    Value is 1 + number of trailing zeros in the arg.,
    or 0 if arg is 0.  */
Index: gcc/libgcc2.c
===================================================================
--- gcc/libgcc2.c	(revision 115311)
+++ gcc/libgcc2.c	(working copy)
@@ -492,6 +492,24 @@ __ashrdi3 (DWtype u, word_type b)
 }
 #endif
 
+#ifdef L_bswapsi2
+Wtype
+__bswapSI2 (Wtype u)
+{
+  return ((((u) & 0xff000000) >> 24) | (((u) & 0x00ff0000) >>  8) |
+	  (((u) & 0x0000ff00) <<  8) | (((u) & 0x000000ff) << 24));
+}
+#endif
+#ifdef L_bswapdi2
+DWtype
+__bswapDI2 (DWtype u)
+{
+  return ((((u) & 0xff00000000000000ull) >> 56) | (((u) & 0x00ff000000000000ull) >> 40) |
+	  (((u) & 0x0000ff0000000000ull) >> 24) | (((u) & 0x000000ff00000000ull) >>  8) |
+	  (((u) & 0x00000000ff000000ull) <<  8) | (((u) & 0x0000000000ff0000ull) << 24) |
+	  (((u) & 0x000000000000ff00ull) << 40) | (((u) & 0x00000000000000ffull) << 56));
+}
+#endif
 #ifdef L_ffssi2
 #undef int
 int
Index: gcc/libgcc2.h
===================================================================
--- gcc/libgcc2.h	(revision 115311)
+++ gcc/libgcc2.h	(working copy)
@@ -304,11 +304,14 @@ typedef int word_type __attribute__ ((mo
 #define __ctzSI2	__NW(ctz,2)
 #define __popcountSI2	__NW(popcount,2)
 #define __paritySI2	__NW(parity,2)
+#define __bswapSI2	__NW(bswap,2)
 #define __ffsDI2	__NDW(ffs,2)
 #define __clzDI2	__NDW(clz,2)
 #define __ctzDI2	__NDW(ctz,2)
 #define __popcountDI2	__NDW(popcount,2)
 #define __parityDI2	__NDW(parity,2)
+#define __bswapDI2	__NDW(bswap,2)
+
 
 extern DWtype __muldi3 (DWtype, DWtype);
 extern DWtype __divdi3 (DWtype, DWtype);
@@ -345,11 +348,13 @@ extern Wtype __addvSI3 (Wtype, Wtype);
 extern Wtype __subvSI3 (Wtype, Wtype);
 extern Wtype __mulvSI3 (Wtype, Wtype);
 extern Wtype __negvSI2 (Wtype);
+extern Wtype __bswapSI2 (Wtype);
 extern DWtype __absvDI2 (DWtype);
 extern DWtype __addvDI3 (DWtype, DWtype);
 extern DWtype __subvDI3 (DWtype, DWtype);
 extern DWtype __mulvDI3 (DWtype, DWtype);
 extern DWtype __negvDI2 (DWtype);
+extern DWtype __bswapDI2 (DWtype);
 
 #ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
 extern SItype __absvsi2 (SItype);
Index: gcc/mklibgcc.in
===================================================================
--- gcc/mklibgcc.in	(revision 115311)
+++ gcc/mklibgcc.in	(working copy)
@@ -91,7 +91,7 @@ lib2funcs='_muldi3 _negdi2 _lshrdi3 _ash
 	_ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab
 	_popcountsi2 _popcountdi2 _paritysi2 _paritydi2 _powisf2 _powidf2
 	_powixf2 _powitf2 _mulsc3 _muldc3 _mulxc3 _multc3 _divsc3 _divdc3
-	_divxc3 _divtc3'
+	_divxc3 _divtc3 _bswapsi2 _bswapdi2'
 
 if [ "$LIB2_SIDITI_CONV_FUNCS" ]; then
   for func in $swfloatfuncs; do
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	(revision 115311)
+++ gcc/config/i386/i386.h	(working copy)
@@ -164,6 +164,7 @@ extern const int x86_use_bt;
 extern const int x86_cmpxchg, x86_cmpxchg8b, x86_cmpxchg16b, x86_xadd;
 extern const int x86_use_incdec;
 extern const int x86_pad_returns;
+extern const int x86_bswap;
 extern int x86_prefetch_sse;
 
 #define TARGET_USE_LEAVE (x86_use_leave & TUNEMASK)
@@ -236,6 +237,7 @@ extern int x86_prefetch_sse;
 #define TARGET_CMPXCHG8B (x86_cmpxchg8b & (1 << ix86_arch))
 #define TARGET_CMPXCHG16B (x86_cmpxchg16b & (1 << ix86_arch))
 #define TARGET_XADD (x86_xadd & (1 << ix86_arch))
+#define TARGET_BSWAP (x86_bswap & (1 << ix86_arch))
 
 #ifndef TARGET_64BIT_DEFAULT
 #define TARGET_64BIT_DEFAULT 0
Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md	(revision 115311)
+++ gcc/config/i386/i386.md	(working copy)
@@ -14142,6 +14142,22 @@
   "bsr{q}\t{%1, %0|%0, %1}"
   [(set_attr "prefix_0f" "1")])
 
+(define_insn "bswapsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(bswap:SI (match_operand:SI 1 "register_operand" "0")))
+   (clobber (reg:CC FLAGS_REG))]
+  "!TARGET_64BIT && TARGET_BSWAP"
+  "bswap\t%1"
+  [(set_attr "prefix_0f" "1")])
+
+(define_insn "bswapdi2"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(bswap:DI (match_operand:DI 1 "register_operand" "0")))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT && TARGET_BSWAP"
+  "bswap\t%1"
+  [(set_attr "prefix_0f" "1")])
+
 ;; Thread-local storage patterns for ELF.
 ;;
 ;; Note that these code sequences must appear exactly as shown
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 115311)
+++ gcc/config/i386/i386.c	(working copy)
@@ -829,6 +829,8 @@ const int x86_cmpxchg8b = ~(m_386 | m_48
 const int x86_cmpxchg16b = m_NOCONA;
 /* Exchange and add was added for 80486.  */
 const int x86_xadd = ~m_386;
+/* Byteswap was added for 80486.  */
+const int x86_bswap = ~m_386;
 const int x86_pad_returns = m_ATHLON_K8 | m_GENERIC;
 
 /* In case the average insn count for single function invocation is
Index: gcc/libgcc-std.ver
===================================================================
--- gcc/libgcc-std.ver	(revision 115311)
+++ gcc/libgcc-std.ver	(working copy)
@@ -273,4 +273,6 @@ GCC_4.2.0 {
   __floatuntixf
   __floatuntitf
   _Unwind_GetIPInfo
+  __bswapsi2
+  __bswapdi2
 }
Index: gcc/testsuite/gcc.target/i386/builtin-bswap-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/builtin-bswap-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/builtin-bswap-1.c	(revision 0)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=i486" } */
+/* { dg-final { scan-assembler "bswap" } } */
+
+int foo (int a)
+{
+  int b;
+
+  b = __builtin_bswap (a);
+
+  return b;
+}
Index: gcc/testsuite/gcc.dg/builtin-bswap-1.c
===================================================================
--- gcc/testsuite/gcc.dg/builtin-bswap-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/builtin-bswap-1.c	(revision 0)
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-final { scan-assembler-not "__builtin_" } } */
+
+extern void abort (void);
+
+int foo (int a)
+{
+  int b;
+
+  b = __builtin_bswap (a);
+
+  return b;
+}
Index: gcc/testsuite/gcc.dg/builtin-bswap-2.c
===================================================================
--- gcc/testsuite/gcc.dg/builtin-bswap-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/builtin-bswap-2.c	(revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "" } */
+
+extern void abort (void);
+
+int main (void)
+{
+  int a = 4;
+  int b;
+
+  b = __builtin_bswap (a);
+  a = __builtin_bswap (b);
+
+  if (a != 4)
+    abort ();
+
+  return 0;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]