From ac868f29d7e81636b988cc4b67f681dce3498175 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 11 Apr 2012 11:13:39 +0000 Subject: re PR target/52624 (missing __builtin_bswap16) PR target/52624 * doc/extend.texi (Other Builtins): Document __builtin_bswap16. (PowerPC AltiVec/VSX Built-in Functions): Remove it. * doc/md.texi (Standard Names): Add bswap. * builtin-types.def (BT_UINT16): New primitive type. (BT_FN_UINT16_UINT16): New function type. * builtins.def (BUILT_IN_BSWAP16): New. * builtins.c (expand_builtin_bswap): Add TARGET_MODE argument. (expand_builtin) : New case. Pass TARGET_MODE to expand_builtin_bswap. (fold_builtin_bswap): Add BUILT_IN_BSWAP16 case. (fold_builtin_1): Likewise. (is_inexpensive_builtin): Likewise. * optabs.c (expand_unop): Deal with bswap in HImode specially. Add missing bits for bswap to libcall code. * tree.c (build_common_tree_nodes): Build uint16_type_node. * tree.h (enum tree_index): Add TI_UINT16_TYPE. (uint16_type_node): New define. * config/rs6000/rs6000-builtin.def (RS6000_BUILTIN_BSWAP_HI): Delete. * config/rs6000/rs6000.c (rs6000_expand_builtin): Remove handling of above builtin. (rs6000_init_builtins): Likewise. * config/rs6000/rs6000.md (bswaphi2): Add TARGET_POWERPC predicate. c-family/ * c-common.h (uint16_type_node): Rename into... (c_uint16_type_node): ...this. * c-common.c (c_common_nodes_and_builtins): Adjust for above renaming. * c-cppbuiltin.c (builtin_define_stdint_macros): Likewise. From-SVN: r186308 --- gcc/optabs.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 565db42..080061a 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -3030,6 +3030,47 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, /* Widening (or narrowing) bswap needs special treatment. */ if (unoptab == bswap_optab) { + /* HImode is special because in this mode BSWAP is equivalent to ROTATE + or ROTATERT. First try these directly; if this fails, then try the + obvious pair of shifts with allowed widening, as this will probably + be always more efficient than the other fallback methods. */ + if (mode == HImode) + { + rtx last, temp1, temp2; + + if (optab_handler (rotl_optab, mode) != CODE_FOR_nothing) + { + temp = expand_binop (mode, rotl_optab, op0, GEN_INT (8), target, + unsignedp, OPTAB_DIRECT); + if (temp) + return temp; + } + + if (optab_handler (rotr_optab, mode) != CODE_FOR_nothing) + { + temp = expand_binop (mode, rotr_optab, op0, GEN_INT (8), target, + unsignedp, OPTAB_DIRECT); + if (temp) + return temp; + } + + last = get_last_insn (); + + temp1 = expand_binop (mode, ashl_optab, op0, GEN_INT (8), NULL_RTX, + unsignedp, OPTAB_WIDEN); + temp2 = expand_binop (mode, lshr_optab, op0, GEN_INT (8), NULL_RTX, + unsignedp, OPTAB_WIDEN); + if (temp1 && temp2) + { + temp = expand_binop (mode, ior_optab, temp1, temp2, target, + unsignedp, OPTAB_WIDEN); + if (temp) + return temp; + } + + delete_insns_since (last); + } + temp = widen_bswap (mode, op0, target); if (temp) return temp; @@ -3222,10 +3263,10 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, /* For certain operations, we need not actually extend the narrow operand, as long as we will truncate the results to the same narrowness. */ - xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, (unoptab == neg_optab - || unoptab == one_cmpl_optab) + || unoptab == one_cmpl_optab + || unoptab == bswap_optab) && mclass == MODE_INT); temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, @@ -3240,6 +3281,20 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, - GET_MODE_PRECISION (mode)), target, true, OPTAB_DIRECT); + /* Likewise for bswap. */ + if (unoptab == bswap_optab && temp != 0) + { + gcc_assert (GET_MODE_PRECISION (wider_mode) + == GET_MODE_BITSIZE (wider_mode) + && GET_MODE_PRECISION (mode) + == GET_MODE_BITSIZE (mode)); + + temp = expand_shift (RSHIFT_EXPR, wider_mode, temp, + GET_MODE_BITSIZE (wider_mode) + - GET_MODE_BITSIZE (mode), + NULL_RTX, true); + } + if (temp) { if (mclass != MODE_INT) -- cgit v1.1