diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-06-21 16:25:57 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-06-21 16:25:57 +0000 |
commit | 6aaa1f9eb2f11b9afcc7c331b6b035013eca098a (patch) | |
tree | 9c216d752e228b140bcd643fe2591b081c4af049 /gcc/builtins.c | |
parent | d2d4033906e05c5153757c50b9b9d2537914598a (diff) | |
download | ppe42-gcc-6aaa1f9eb2f11b9afcc7c331b6b035013eca098a.tar.gz ppe42-gcc-6aaa1f9eb2f11b9afcc7c331b6b035013eca098a.zip |
PR middle-end/49489
* builtins.c (expand_builtin_unop): Call expand_unop with 0 as
unsignedp argument instead of 1 for clrsb_optab.
(fold_builtin_bitop): Fix masking for width > HOST_BITS_PER_WIDE_INT
and < 2 * HOST_BITS_PER_WIDE_INT. Optimize BUILT_IN_CLRSB*.
(fold_builtin_1): Call fold_builtin_binop for BUILT_IN_CLRSB*.
* optabs.c (widen_leading): Call widen_operand and expand_unop
with 0 as unsignedp argument instead of 1 for clrsb_optab.
(expand_unop): Subtract difference of mode sizes also for
clrsb_optab.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@175265 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 8fc5ac34e54..5a3835f30ed 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -4578,7 +4578,7 @@ expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target, /* Compute op, into TARGET if possible. Set TARGET to wherever the result comes back. */ target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))), - op_optab, op0, target, 1); + op_optab, op0, target, op_optab != clrsb_optab); gcc_assert (target); return convert_to_mode (target_mode, target, 0); @@ -7265,7 +7265,8 @@ fold_builtin_bitop (tree fndecl, tree arg) { hi = TREE_INT_CST_HIGH (arg); if (width < 2 * HOST_BITS_PER_WIDE_INT) - hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT)); + hi &= ~((unsigned HOST_WIDE_INT) (-1) + << (width - HOST_BITS_PER_WIDE_INT)); } else { @@ -7303,6 +7304,26 @@ fold_builtin_bitop (tree fndecl, tree arg) result = width; break; + CASE_INT_FN (BUILT_IN_CLRSB): + if (width > HOST_BITS_PER_WIDE_INT + && (hi & ((unsigned HOST_WIDE_INT) 1 + << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0) + { + hi = ~hi & ~((unsigned HOST_WIDE_INT) (-1) + << (width - HOST_BITS_PER_WIDE_INT - 1)); + lo = ~lo; + } + else if (width <= HOST_BITS_PER_WIDE_INT + && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0) + lo = ~lo & ~((unsigned HOST_WIDE_INT) (-1) << (width - 1)); + if (hi != 0) + result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT; + else if (lo != 0) + result = width - floor_log2 (lo) - 2; + else + result = width - 1; + break; + CASE_INT_FN (BUILT_IN_POPCOUNT): result = 0; while (lo) @@ -9737,6 +9758,7 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore) CASE_INT_FN (BUILT_IN_FFS): CASE_INT_FN (BUILT_IN_CLZ): CASE_INT_FN (BUILT_IN_CTZ): + CASE_INT_FN (BUILT_IN_CLRSB): CASE_INT_FN (BUILT_IN_POPCOUNT): CASE_INT_FN (BUILT_IN_PARITY): return fold_builtin_bitop (fndecl, arg0); |