summaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2011-06-21 14:16:39 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2011-06-21 14:16:39 +0000
commit3801c801f35ca5e0c52b437161141c251aa33daf (patch)
treeee32816cbc97cc6b5823412e083d7944b01b96a7 /gcc/optabs.c
parent95f5c7757f027c4c9afbb97a7a24be0cc9ad7841 (diff)
downloadgcc-3801c801f35ca5e0c52b437161141c251aa33daf.tar.gz
Makefile.in (lib2funcs): Add _clrsbsi2 and _clrsbdi2.
libgcc/ * Makefile.in (lib2funcs): Add _clrsbsi2 and _clrsbdi2. * libgcc-std.ver.in (GCC_4.7.0): New section. gcc/ * doc/extend.texi (__builtin_clrsb, __builtin_clrsbl, __builtin_clrsbll): Document. * doc/rtl.texi (clrsb): New entry. * optabs.c (widen_leading): Renamed from widen_clz. New argument UNOPTAB. All callers changed. Use UNOPTAB instead of clz_optab. (expand_unop): Handle clrsb_optab. (init_optabs): Initialize it. * optabs.h (enum optab_index): New entry OTI_clrsb. (clrsb_optab): Define. * genopinit.c (optabs): Add an entry for it. * builtins.c (expand_builtin): Handle clrsb builtin functions. * builtins.def (BUILT_IN_CLRSB, BUILT_IN_CLRSBIMAX, BUILT_IN_CLRSBL, BUILT_IN_CLRSBLL): New. * rtl.def (CLRSB): New code. * dwarf2out.c (mem_loc_descriptor): Handle it. * simplify-rtx.c (simplify_const_unary_operation): Likewise. Use op_mode rather than mode when optimizing ffs, clz, ctz, parity and popcount. * libgcc2.c (__clrsbSI2, __clrsbDI2): New functions. * libgcc2.h (__clrsbSI2, __clrsbDI2): Define and declare. (__ctzDI2): Move declaration. * config/bfin/bfin.md (clrsbsi2): New expander. (signbitssi2): Use the CLRSB rtx. (clrsbhi2): Renamed from signbitshi2. Use the CLRSB rtx. * config/bfin/bfin.c (bdesc_1arg): Changed accordingly. gcc/testsuite/ * gcc.c-torture/excute/builtin-bitops-1.c (MAKE_FUNS): Make my_clrsb test functions. (main): Test clrsb. * gcc.dg/builtin-protos-1.c (test_s, test_u, test_sl, test_ul, test_sll, test_ull): Add clrsb tests. * gcc.dg/torture/builtin-attr-1.c: Add tests for clrsb, clrsbl, clrsbll. From-SVN: r175261
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 224fb11b59b..7448450d236 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -2327,9 +2327,12 @@ expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
/* Try calculating
(clz:narrow x)
as
- (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)). */
+ (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)).
+
+ A similar operation can be used for clrsb. UNOPTAB says which operation
+ we are trying to expand. */
static rtx
-widen_clz (enum machine_mode mode, rtx op0, rtx target)
+widen_leading (enum machine_mode mode, rtx op0, rtx target, optab unoptab)
{
enum mode_class mclass = GET_MODE_CLASS (mode);
if (CLASS_HAS_WIDER_MODES_P (mclass))
@@ -2339,7 +2342,7 @@ widen_clz (enum machine_mode mode, rtx op0, rtx target)
wider_mode != VOIDmode;
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
{
- if (optab_handler (clz_optab, wider_mode) != CODE_FOR_nothing)
+ if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
{
rtx xop0, temp, last;
@@ -2348,7 +2351,7 @@ widen_clz (enum machine_mode mode, rtx op0, rtx target)
if (target == 0)
target = gen_reg_rtx (mode);
xop0 = widen_operand (op0, wider_mode, mode, true, false);
- temp = expand_unop (wider_mode, clz_optab, xop0, NULL_RTX, true);
+ temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, true);
if (temp != 0)
temp = expand_binop (wider_mode, sub_optab, temp,
GEN_INT (GET_MODE_BITSIZE (wider_mode)
@@ -2844,7 +2847,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
/* Widening (or narrowing) clz needs special treatment. */
if (unoptab == clz_optab)
{
- temp = widen_clz (mode, op0, target);
+ temp = widen_leading (mode, op0, target, unoptab);
if (temp)
return temp;
@@ -2856,7 +2859,15 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
return temp;
}
- goto try_libcall;
+ goto try_libcall;
+ }
+
+ if (unoptab == clrsb_optab)
+ {
+ temp = widen_leading (mode, op0, target, unoptab);
+ if (temp)
+ return temp;
+ goto try_libcall;
}
/* Widening (or narrowing) bswap needs special treatment. */
@@ -3011,7 +3022,8 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
/* All of these functions return small values. Thus we choose to
have them return something that isn't a double-word. */
if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
- || unoptab == popcount_optab || unoptab == parity_optab)
+ || unoptab == clrsb_optab || unoptab == popcount_optab
+ || unoptab == parity_optab)
outmode
= GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node),
optab_libfunc (unoptab, mode)));
@@ -5958,6 +5970,7 @@ init_optabs (void)
init_optab (ffs_optab, FFS);
init_optab (clz_optab, CLZ);
init_optab (ctz_optab, CTZ);
+ init_optab (clrsb_optab, CLRSB);
init_optab (popcount_optab, POPCOUNT);
init_optab (parity_optab, PARITY);
init_optab (sqrt_optab, SQRT);
@@ -6188,6 +6201,9 @@ init_optabs (void)
ctz_optab->libcall_basename = "ctz";
ctz_optab->libcall_suffix = '2';
ctz_optab->libcall_gen = gen_int_libfunc;
+ clrsb_optab->libcall_basename = "clrsb";
+ clrsb_optab->libcall_suffix = '2';
+ clrsb_optab->libcall_gen = gen_int_libfunc;
popcount_optab->libcall_basename = "popcount";
popcount_optab->libcall_suffix = '2';
popcount_optab->libcall_gen = gen_int_libfunc;