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]

Re: [PATCH] Optimize manual byte swap implementations -refreshed


On Fri, Jun 12, 2009 at 12:28 PM, Andreas
Krebbel<krebbel@linux.vnet.ibm.com> wrote:
> Hi,
>
> here is a refreshed version of the bswap optimization pass. ?I again
> tried to do some measurements with builds of the Linux kernel. This
> time I've also tried to evaluate how much of the time is consumed by
> just walking the statements.
>
> Unfortunately I must admit that there is quite a deviation in the
> results. ?At least for the statement walk measurements the standard
> deviation is so high that you should look at it with care. My
> statistics teacher probably would kick me through the hallway for
> these numbers ;)
>
> With the latest version - after integrating some more comments from
> Richard - the overhead went down to 0.24%.
>
> I've built the Linux kernel with -j4 (version 2.6.28) 5 times. The
> timings show the total time spent in user space measured with the
> \time command - not the bash builtin.
>
> x86_64 Intel Quad Core 9550 8GB 2.83 GHz
>
> GCC svn revision: 147107
>
> clean ? ? ? ? ? stmt walk only ?optimized
> 3599.21s ? ? ? ?3599.23s ? ? ? ?3607.28s
> 3604.17s ? ? ? ?3609.16s ? ? ? ?3608.33s
> 3600.32s ? ? ? ?3601.75s ? ? ? ?3610.47s
> 3600.49s ? ? ? ?3608.81s ? ? ? ?3611.62s
> 3601.26s ? ? ? ?3604.6s ? ? ? ? 3611.51s
>
> +-1.87s +-0.05% +-4.34s +-0.12% +-1.95s +-0.05% ?<- standard deviation
>
> 3601.09 ? ? ? ? 3604.71 +0.10% ?3609.84 +0.24%
>
> Bootstrapped on x86_64. No regressions.
>
> Ok for mainline?

Ok.

Thanks,
Richard.

> Bye,
>
> -Andreas-
>
>
> 2009-06-12 ?Andreas Krebbel ?<Andreas.Krebbel@de.ibm.com>
>
> ? ? ? ?* passes.c: Add bswap pass.
> ? ? ? ?* tree-pass.h: Add pass_optimize_bswap declaration.
> ? ? ? ?* tree-ssa-math-opts.c: Include diagnostics.h for print_gimple_stmt.
> ? ? ? ?Include rtl.h, expr.h and optabs.h for optab_handler check.
> ? ? ? ?(struct symbolic_number, pass_optimize_bswap): New definition.
> ? ? ? ?(do_shift_rotate, verify_symbolic_number_p): New functions.
> ? ? ? ?(find_bswap_1, find_bswap, execute_optimize_bswap): New functions.
> ? ? ? ?(gate_optimize_bswap): New function.
> ? ? ? ?* tree.c (widest_int_cst_value): New function.
> ? ? ? ?* tree.h (widest_int_cst_value): Prototype added.
>
> 2009-06-12 ?Andreas Krebbel ?<Andreas.Krebbel@de.ibm.com>
>
> ? ? ? ?* gcc.dg/optimize-bswap-1.c: New testcase.
>
> Index: gcc/passes.c
> ===================================================================
> --- gcc/passes.c.orig ? 2009-04-28 19:33:58.000000000 +0200
> +++ gcc/passes.c ? ? ? ?2009-05-14 19:59:58.000000000 +0200
> @@ -641,6 +641,7 @@
> ? ? ? NEXT_PASS (pass_copy_prop);
> ? ? ? NEXT_PASS (pass_fold_builtins);
> ? ? ? NEXT_PASS (pass_cse_sincos);
> + ? ? ?NEXT_PASS (pass_optimize_bswap);
> ? ? ? NEXT_PASS (pass_split_crit_edges);
> ? ? ? NEXT_PASS (pass_pre);
> ? ? ? NEXT_PASS (pass_sink_code);
> Index: gcc/tree-pass.h
> ===================================================================
> --- gcc/tree-pass.h.orig ? ? ? ?2009-04-28 19:33:58.000000000 +0200
> +++ gcc/tree-pass.h ? ? 2009-05-14 19:59:58.000000000 +0200
> @@ -370,6 +370,7 @@
> ?extern struct gimple_opt_pass pass_cse_reciprocals;
> ?extern struct gimple_opt_pass pass_cse_sincos;
> ?extern struct gimple_opt_pass pass_convert_to_rsqrt;
> +extern struct gimple_opt_pass pass_optimize_bswap;
> ?extern struct gimple_opt_pass pass_warn_function_return;
> ?extern struct gimple_opt_pass pass_warn_function_noreturn;
> ?extern struct gimple_opt_pass pass_cselim;
> Index: gcc/tree-ssa-math-opts.c
> ===================================================================
> --- gcc/tree-ssa-math-opts.c.orig ? ? ? 2009-04-28 19:31:42.000000000 +0200
> +++ gcc/tree-ssa-math-opts.c ? ?2009-06-12 10:12:13.000000000 +0200
> @@ -97,7 +97,10 @@
> ?#include "alloc-pool.h"
> ?#include "basic-block.h"
> ?#include "target.h"
> -
> +#include "diagnostic.h"
> +#include "rtl.h"
> +#include "expr.h"
> +#include "optabs.h"
>
> ?/* This structure represents one basic block that either computes a
> ? ?division, or is a common dominator for basic block that compute a
> @@ -879,3 +882,383 @@
> ? ? | TODO_verify_stmts ? ? ? ? ? ? ? ? /* todo_flags_finish */
> ?}
> ?};
> +
> +/* A symbolic number is used to detect byte permutation and selection
> + ? patterns. ?Therefore the field N contains an artificial number
> + ? consisting of byte size markers:
> +
> + ? 0 ? ?- byte has the value 0
> + ? 1..size - byte contains the content of the byte
> + ? number indexed with that value minus one ?*/
> +
> +struct symbolic_number {
> + ?unsigned HOST_WIDEST_INT n;
> + ?int size;
> +};
> +
> +/* Perform a SHIFT or ROTATE operation by COUNT bits on symbolic
> + ? number N. ?Return false if the requested operation is not permitted
> + ? on a symbolic number. ?*/
> +
> +static inline bool
> +do_shift_rotate (enum tree_code code,
> + ? ? ? ? ? ? ? ?struct symbolic_number *n,
> + ? ? ? ? ? ? ? ?int count)
> +{
> + ?if (count % 8 != 0)
> + ? ?return false;
> +
> + ?/* Zero out the extra bits of N in order to avoid them being shifted
> + ? ? into the significant bits. ?*/
> + ?if (n->size < (int)sizeof (HOST_WIDEST_INT))
> + ? ?n->n &= ((unsigned HOST_WIDEST_INT)1 << (n->size * BITS_PER_UNIT)) - 1;
> +
> + ?switch (code)
> + ? ?{
> + ? ?case LSHIFT_EXPR:
> + ? ? ?n->n <<= count;
> + ? ? ?break;
> + ? ?case RSHIFT_EXPR:
> + ? ? ?n->n >>= count;
> + ? ? ?break;
> + ? ?case LROTATE_EXPR:
> + ? ? ?n->n = (n->n << count) | (n->n >> ((n->size * BITS_PER_UNIT) - count));
> + ? ? ?break;
> + ? ?case RROTATE_EXPR:
> + ? ? ?n->n = (n->n >> count) | (n->n << ((n->size * BITS_PER_UNIT) - count));
> + ? ? ?break;
> + ? ?default:
> + ? ? ?return false;
> + ? ?}
> + ?return true;
> +}
> +
> +/* Perform sanity checking for the symbolic number N and the gimple
> + ? statement STMT. ?*/
> +
> +static inline bool
> +verify_symbolic_number_p (struct symbolic_number *n, gimple stmt)
> +{
> + ?tree lhs_type;
> +
> + ?lhs_type = gimple_expr_type (stmt);
> +
> + ?if (TREE_CODE (lhs_type) != INTEGER_TYPE)
> + ? ?return false;
> +
> + ?if (TYPE_PRECISION (lhs_type) != n->size * BITS_PER_UNIT)
> + ? ?return false;
> +
> + ?return true;
> +}
> +
> +/* find_bswap_1 invokes itself recursively with N and tries to perform
> + ? the operation given by the rhs of STMT on the result. ?If the
> + ? operation could successfully be executed the function returns the
> + ? tree expression of the source operand and NULL otherwise. ?*/
> +
> +static tree
> +find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit)
> +{
> + ?enum tree_code code;
> + ?tree rhs1, rhs2 = NULL;
> + ?gimple rhs1_stmt, rhs2_stmt;
> + ?tree source_expr1;
> + ?enum gimple_rhs_class rhs_class;
> +
> + ?if (!limit || !is_gimple_assign (stmt))
> + ? ?return NULL_TREE;
> +
> + ?rhs1 = gimple_assign_rhs1 (stmt);
> +
> + ?if (TREE_CODE (rhs1) != SSA_NAME)
> + ? ?return NULL_TREE;
> +
> + ?code = gimple_assign_rhs_code (stmt);
> + ?rhs_class = gimple_assign_rhs_class (stmt);
> + ?rhs1_stmt = SSA_NAME_DEF_STMT (rhs1);
> +
> + ?if (rhs_class == GIMPLE_BINARY_RHS)
> + ? ?rhs2 = gimple_assign_rhs2 (stmt);
> +
> + ?/* Handle unary rhs and binary rhs with integer constants as second
> + ? ? operand. ?*/
> +
> + ?if (rhs_class == GIMPLE_UNARY_RHS
> + ? ? ?|| (rhs_class == GIMPLE_BINARY_RHS
> + ? ? ? ? && TREE_CODE (rhs2) == INTEGER_CST))
> + ? ?{
> + ? ? ?if (code != BIT_AND_EXPR
> + ? ? ? ? && code != LSHIFT_EXPR
> + ? ? ? ? && code != RSHIFT_EXPR
> + ? ? ? ? && code != LROTATE_EXPR
> + ? ? ? ? && code != RROTATE_EXPR
> + ? ? ? ? && code != NOP_EXPR
> + ? ? ? ? && code != CONVERT_EXPR)
> + ? ? ? return NULL_TREE;
> +
> + ? ? ?source_expr1 = find_bswap_1 (rhs1_stmt, n, limit - 1);
> +
> + ? ? ?/* If find_bswap_1 returned NULL STMT is a leaf node and we have
> + ? ? ? ?to initialize the symbolic number. ?*/
> + ? ? ?if (!source_expr1)
> + ? ? ? {
> + ? ? ? ? /* Set up the symbolic number N by setting each byte to a
> + ? ? ? ? ? ?value between 1 and the byte size of rhs1. ?The highest
> + ? ? ? ? ? ?order byte is set to 1 and the lowest order byte to
> + ? ? ? ? ? ?n.size. ?*/
> + ? ? ? ? n->size = TYPE_PRECISION (TREE_TYPE (rhs1));
> + ? ? ? ? if (n->size % BITS_PER_UNIT != 0)
> + ? ? ? ? ? return NULL_TREE;
> + ? ? ? ? n->size /= BITS_PER_UNIT;
> + ? ? ? ? n->n = (sizeof (HOST_WIDEST_INT) < 8 ? 0 :
> + ? ? ? ? ? ? ? ? (unsigned HOST_WIDEST_INT)0x01020304 << 32 | 0x05060708);
> + ? ? ? ? n->n >>= (sizeof (HOST_WIDEST_INT) - n->size) * BITS_PER_UNIT;
> +
> + ? ? ? ? source_expr1 = rhs1;
> + ? ? ? }
> +
> + ? ? ?switch (code)
> + ? ? ? {
> + ? ? ? case BIT_AND_EXPR:
> + ? ? ? ? {
> + ? ? ? ? ? int i;
> + ? ? ? ? ? unsigned HOST_WIDEST_INT val = widest_int_cst_value (rhs2);
> + ? ? ? ? ? unsigned HOST_WIDEST_INT tmp = val;
> +
> + ? ? ? ? ? /* Only constants masking full bytes are allowed. ?*/
> + ? ? ? ? ? for (i = 0; i < n->size; i++, tmp >>= BITS_PER_UNIT)
> + ? ? ? ? ? ? if ((tmp & 0xff) != 0 && (tmp & 0xff) != 0xff)
> + ? ? ? ? ? ? ? return NULL_TREE;
> +
> + ? ? ? ? ? n->n &= val;
> + ? ? ? ? }
> + ? ? ? ? break;
> + ? ? ? case LSHIFT_EXPR:
> + ? ? ? case RSHIFT_EXPR:
> + ? ? ? case LROTATE_EXPR:
> + ? ? ? case RROTATE_EXPR:
> + ? ? ? ? if (!do_shift_rotate (code, n, (int)TREE_INT_CST_LOW (rhs2)))
> + ? ? ? ? ? return NULL_TREE;
> + ? ? ? ? break;
> + ? ? ? CASE_CONVERT:
> + ? ? ? ? {
> + ? ? ? ? ? int type_size;
> +
> + ? ? ? ? ? type_size = TYPE_PRECISION (gimple_expr_type (stmt));
> + ? ? ? ? ? if (type_size % BITS_PER_UNIT != 0)
> + ? ? ? ? ? ? return NULL_TREE;
> +
> + ? ? ? ? ? type_size /= BITS_PER_UNIT;
> +
> + ? ? ? ? ? if (type_size / BITS_PER_UNIT < (int)(sizeof (HOST_WIDEST_INT)))
> + ? ? ? ? ? ? {
> + ? ? ? ? ? ? ? /* If STMT casts to a smaller type mask out the bits not
> + ? ? ? ? ? ? ? ? ?belonging to the target type. ?*/
> + ? ? ? ? ? ? ? n->size = type_size / BITS_PER_UNIT;
> + ? ? ? ? ? ? ? n->n &= ((unsigned HOST_WIDEST_INT)1 << type_size) - 1;
> + ? ? ? ? ? ? }
> + ? ? ? ? }
> + ? ? ? ? break;
> + ? ? ? default:
> + ? ? ? ? return NULL_TREE;
> + ? ? ? };
> + ? ? ?return verify_symbolic_number_p (n, stmt) ? source_expr1 : NULL;
> + ? ?}
> +
> + ?/* Handle binary rhs. ?*/
> +
> + ?if (rhs_class == GIMPLE_BINARY_RHS)
> + ? ?{
> + ? ? ?struct symbolic_number n1, n2;
> + ? ? ?tree source_expr2;
> +
> + ? ? ?if (code != BIT_IOR_EXPR)
> + ? ? ? return NULL_TREE;
> +
> + ? ? ?if (TREE_CODE (rhs2) != SSA_NAME)
> + ? ? ? return NULL_TREE;
> +
> + ? ? ?rhs2_stmt = SSA_NAME_DEF_STMT (rhs2);
> +
> + ? ? ?switch (code)
> + ? ? ? {
> + ? ? ? case BIT_IOR_EXPR:
> + ? ? ? ? source_expr1 = find_bswap_1 (rhs1_stmt, &n1, limit - 1);
> +
> + ? ? ? ? if (!source_expr1)
> + ? ? ? ? ? return NULL_TREE;
> +
> + ? ? ? ? source_expr2 = find_bswap_1 (rhs2_stmt, &n2, limit - 1);
> +
> + ? ? ? ? if (source_expr1 != source_expr2
> + ? ? ? ? ? ? || n1.size != n2.size)
> + ? ? ? ? ? return NULL_TREE;
> +
> + ? ? ? ? n->size = n1.size;
> + ? ? ? ? n->n = n1.n | n2.n;
> +
> + ? ? ? ? if (!verify_symbolic_number_p (n, stmt))
> + ? ? ? ? ? return NULL_TREE;
> +
> + ? ? ? ? break;
> + ? ? ? default:
> + ? ? ? ? return NULL_TREE;
> + ? ? ? }
> + ? ? ?return source_expr1;
> + ? ?}
> + ?return NULL_TREE;
> +}
> +
> +/* Check if STMT completes a bswap implementation consisting of ORs,
> + ? SHIFTs and ANDs. ?Return the source tree expression on which the
> + ? byte swap is performed and NULL if no bswap was found. ?*/
> +
> +static tree
> +find_bswap (gimple stmt)
> +{
> +/* The number which the find_bswap result should match in order to
> + ? have a full byte swap. ?The insignificant bytes are masked out
> + ? before using it. ?*/
> + ?unsigned HOST_WIDEST_INT cmp =
> + ? ?sizeof (HOST_WIDEST_INT) < 8 ? 0 :
> + ? ?(unsigned HOST_WIDEST_INT)0x08070605 << 32 | 0x04030201;
> +
> + ?struct symbolic_number n;
> + ?tree source_expr;
> +
> + ?source_expr = ?find_bswap_1 (stmt, &n,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?TREE_INT_CST_LOW (
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?TYPE_SIZE_UNIT (gimple_expr_type (stmt))));
> +
> + ?if (!source_expr)
> + ? ?return NULL_TREE;
> +
> + ?/* Zero out the extra bits of N and CMP. ?*/
> + ?if (n.size < (int)sizeof (HOST_WIDEST_INT))
> + ? ?{
> + ? ? ?unsigned HOST_WIDEST_INT mask =
> + ? ? ? ((unsigned HOST_WIDEST_INT)1 << (n.size * BITS_PER_UNIT)) - 1;
> +
> + ? ? ?n.n &= mask;
> + ? ? ?cmp &= mask;
> + ? ?}
> +
> + ?/* A complete byte swap should make the symbolic number to start
> + ? ? with the largest digit in the highest order byte. ?*/
> + ?if (cmp != n.n)
> + ? ?return NULL_TREE;
> +
> + ?return source_expr;
> +}
> +
> +/* Find manual byte swap implementations and turn them into a bswap
> + ? builtin invokation. ?*/
> +
> +static unsigned int
> +execute_optimize_bswap (void)
> +{
> + ?basic_block bb;
> + ?bool bswap32_p, bswap64_p;
> + ?bool changed = false;
> +
> + ?if (BITS_PER_UNIT != 8)
> + ? ?return 0;
> +
> + ?if (sizeof (HOST_WIDEST_INT) < 8)
> + ? ?return 0;
> +
> + ?bswap32_p = (built_in_decls[BUILT_IN_BSWAP32]
> + ? ? ? ? ? ? ?&& optab_handler (bswap_optab, SImode)->insn_code !=
> + ? ? ? ? ? ? ?CODE_FOR_nothing);
> + ?bswap64_p = (built_in_decls[BUILT_IN_BSWAP64]
> + ? ? ? ? ? ? ?&& optab_handler (bswap_optab, DImode)->insn_code !=
> + ? ? ? ? ? ? ?CODE_FOR_nothing);
> +
> + ?if (!bswap32_p && !bswap64_p)
> + ? ?return 0;
> +
> + ?FOR_EACH_BB (bb)
> + ? ?{
> + ? ? ?gimple_stmt_iterator gsi;
> +
> + ? ? ?for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> + ? ? ? ?{
> + ? ? ? ? gimple stmt = gsi_stmt (gsi);
> + ? ? ? ? tree bswap_src;
> + ? ? ? ? tree fndecl = NULL_TREE;
> + ? ? ? ? int type_size;
> + ? ? ? ? gimple call;
> +
> + ? ? ? ? if (!is_gimple_assign (stmt)
> + ? ? ? ? ? ? || gimple_assign_rhs_code (stmt) != BIT_IOR_EXPR)
> + ? ? ? ? ? continue;
> +
> + ? ? ? ? type_size = TYPE_PRECISION (gimple_expr_type (stmt));
> +
> + ? ? ? ? switch (type_size)
> + ? ? ? ? ? {
> + ? ? ? ? ? case 32:
> + ? ? ? ? ? ? if (bswap32_p)
> + ? ? ? ? ? ? ? fndecl = built_in_decls[BUILT_IN_BSWAP32];
> + ? ? ? ? ? ? break;
> + ? ? ? ? ? case 64:
> + ? ? ? ? ? ? if (bswap64_p)
> + ? ? ? ? ? ? ? fndecl = built_in_decls[BUILT_IN_BSWAP64];
> + ? ? ? ? ? ? break;
> + ? ? ? ? ? default:
> + ? ? ? ? ? ? continue;
> + ? ? ? ? ? }
> +
> + ? ? ? ? if (!fndecl)
> + ? ? ? ? ? continue;
> +
> + ? ? ? ? bswap_src = find_bswap (stmt);
> +
> + ? ? ? ? if (!bswap_src)
> + ? ? ? ? ? continue;
> +
> + ? ? ? ? changed = true;
> + ? ? ? ? call = gimple_build_call (fndecl, 1, bswap_src);
> + ? ? ? ? gimple_call_set_lhs (call, gimple_assign_lhs (stmt));
> +
> + ? ? ? ? if (dump_file)
> + ? ? ? ? ? {
> + ? ? ? ? ? ? fprintf (dump_file, "%d bit bswap implementation found at: ",
> + ? ? ? ? ? ? ? ? ? ? ?(int)type_size);
> + ? ? ? ? ? ? print_gimple_stmt (dump_file, stmt, 0, 0);
> + ? ? ? ? ? }
> +
> + ? ? ? ? gsi_insert_after (&gsi, call, GSI_SAME_STMT);
> + ? ? ? ? gsi_remove (&gsi, true);
> + ? ? ? }
> + ? ?}
> +
> + ?return (changed ? TODO_dump_func | TODO_update_ssa | TODO_verify_ssa
> + ? ? ? ? | TODO_verify_stmts : 0);
> +}
> +
> +static bool
> +gate_optimize_bswap (void)
> +{
> + ?return flag_expensive_optimizations && optimize;
> +}
> +
> +struct gimple_opt_pass pass_optimize_bswap =
> +{
> + {
> + ?GIMPLE_PASS,
> + ?"bswap", ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* name */
> + ?gate_optimize_bswap, ? ? ? ? ? ? ? ? ?/* gate */
> + ?execute_optimize_bswap, ? ? ? ? ? ? ?/* execute */
> + ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* sub */
> + ?NULL, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* next */
> + ?0, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* static_pass_number */
> + ?TV_NONE, ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* tv_id */
> + ?PROP_ssa, ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* properties_required */
> + ?0, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* properties_provided */
> + ?0, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* properties_destroyed */
> + ?0, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* todo_flags_start */
> + ?0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* todo_flags_finish */
> + }
> +};
> Index: gcc/testsuite/gcc.dg/optimize-bswap-1.c
> ===================================================================
> --- /dev/null ? 1970-01-01 00:00:00.000000000 +0000
> +++ gcc/testsuite/gcc.dg/optimize-bswap-1.c ? ? 2009-05-14 19:59:58.000000000 +0200
> @@ -0,0 +1,52 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target stdint_types } */
> +/* { dg-options "-O2 -fdump-tree-bswap" } */
> +
> +#include <stdint.h>
> +
> +#define __const_swab32(x) ((uint32_t)( ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
> + ? ? ? ?(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | ? ? ? ? ? ?\
> + ? ? ? ?(((uint32_t)(x) & (uint32_t)0x0000ff00UL) << ?8) | ? ? ? ? ? ?\
> + ? ? ? ?(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> ?8) | ? ? ? ? ? ?\
> + ? ? ? ?(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
> +
> +#define __const_swab64(x) ((uint64_t)( ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
> + ? ? ? (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | ? ? ? ? ? ? \
> + ? ? ? (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | ? ? ? ? ? ? \
> + ? ? ? (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | ? ? ? ? ? ? \
> + ? ? ? (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << ?8) | ? ? ? ? ? ? \
> + ? ? ? (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> ?8) | ? ? ? ? ? ? \
> + ? ? ? (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | ? ? ? ? ? ? \
> + ? ? ? (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | ? ? ? ? ? ? \
> + ? ? ? (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
> +
> +/* This byte swap implementation is used by the Linux kernel and the
> + ? GNU C library. ?*/
> +
> +uint32_t
> +swap32_a (uint32_t in)
> +{
> + ?return __const_swab32 (in);
> +}
> +
> +uint64_t
> +swap64 (uint64_t in)
> +{
> + ?return __const_swab64 (in);
> +}
> +
> +/* The OpenSSH byte swap implementation. ?*/
> +uint32_t
> +swap32_b (uint32_t in)
> +{
> + ?uint32_t a;
> +
> + ?a = (in << 16) | (in >> 16);
> + ?a = ((a & 0x00ff00ff) << 8) | ((a & 0xff00ff00) >> 8);
> +
> + ?return a;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "32 bit bswap implementation found at" 2 "bswap" } } */
> +/* { dg-final { scan-tree-dump-times "64 bit bswap implementation found at" 1 "bswap" } } */
> +/* { dg-final { cleanup-tree-dump "bswap" } } */
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c.orig ? ? 2009-04-28 19:33:58.000000000 +0200
> +++ gcc/tree.c ?2009-05-14 19:59:58.000000000 +0200
> @@ -8368,6 +8368,35 @@
> ? return val;
> ?}
>
> +/* Return value of a constant X and sign-extend it. ?*/
> +
> +HOST_WIDEST_INT
> +widest_int_cst_value (const_tree x)
> +{
> + ?unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
> + ?unsigned HOST_WIDEST_INT val = TREE_INT_CST_LOW (x);
> +
> +#if HOST_BITS_PER_WIDEST_INT > HOST_BITS_PER_WIDE_INT
> + ?gcc_assert (HOST_BITS_PER_WIDEST_INT >= 2 * HOST_BITS_PER_WIDE_INT);
> + ?val |= TREE_INT_CST_HIGH (x) << HOST_BITS_PER_WIDE_INT;
> +#else
> + ?/* Make sure the sign-extended value will fit in a HOST_WIDE_INT. ?*/
> + ?gcc_assert (TREE_INT_CST_HIGH (x) == 0
> + ? ? ? ? ? ? || TREE_INT_CST_HIGH (x) == -1);
> +#endif
> +
> + ?if (bits < HOST_BITS_PER_WIDEST_INT)
> + ? ?{
> + ? ? ?bool negative = ((val >> (bits - 1)) & 1) != 0;
> + ? ? ?if (negative)
> + ? ? ? val |= (~(unsigned HOST_WIDEST_INT) 0) << (bits - 1) << 1;
> + ? ? ?else
> + ? ? ? val &= ~((~(unsigned HOST_WIDEST_INT) 0) << (bits - 1) << 1);
> + ? ?}
> +
> + ?return val;
> +}
> +
> ?/* If TYPE is an integral type, return an equivalent type which is
> ? ? unsigned iff UNSIGNEDP is true. ?If TYPE is not an integral type,
> ? ? return TYPE itself. ?*/
> Index: gcc/tree.h
> ===================================================================
> --- gcc/tree.h.orig ? ? 2009-05-04 21:36:33.000000000 +0200
> +++ gcc/tree.h ?2009-05-14 19:59:58.000000000 +0200
> @@ -4865,6 +4865,7 @@
> ?extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
> ?extern tree build_range_type (tree, tree, tree);
> ?extern HOST_WIDE_INT int_cst_value (const_tree);
> +extern HOST_WIDEST_INT widest_int_cst_value (const_tree);
> ?extern tree build_addr (tree, tree);
>
> ?extern bool fields_compatible_p (const_tree, const_tree);
>


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