summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2014-04-28 20:20:37 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2014-04-28 20:20:37 +0000
commit1cee90adce76bf3df916a16cbf24460b25578892 (patch)
tree809e0ddad6cc875da3ddceead9d1ce04c946ef69 /gcc
parentf084c625c4363731ccff2183b6b60bb3f8338558 (diff)
downloadgcc-1cee90adce76bf3df916a16cbf24460b25578892.tar.gz
Use target-independent semantics for wi::clz and wi::ctz.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@209872 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/builtins.c11
-rw-r--r--gcc/simplify-rtx.c13
-rw-r--r--gcc/wide-int.cc46
3 files changed, 21 insertions, 49 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index a7a80ea7435..140d6ba1a5b 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -8080,6 +8080,7 @@ fold_builtin_bitop (tree fndecl, tree arg)
/* Optimize for constant argument. */
if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
{
+ tree type = TREE_TYPE (arg);
int result;
switch (DECL_FUNCTION_CODE (fndecl))
@@ -8089,11 +8090,17 @@ fold_builtin_bitop (tree fndecl, tree arg)
break;
CASE_INT_FN (BUILT_IN_CLZ):
- result = wi::clz (arg);
+ if (wi::ne_p (arg, 0))
+ result = wi::clz (arg);
+ else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
+ result = TYPE_PRECISION (type);
break;
CASE_INT_FN (BUILT_IN_CTZ):
- result = wi::ctz (arg);
+ if (wi::ne_p (arg, 0))
+ result = wi::ctz (arg);
+ else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
+ result = TYPE_PRECISION (type);
break;
CASE_INT_FN (BUILT_IN_CLRSB):
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index f7d3e79a28a..7fb1c6db63d 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1656,6 +1656,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
wide_int result;
enum machine_mode imode = op_mode == VOIDmode ? mode : op_mode;
rtx_mode_t op0 = std::make_pair (op, imode);
+ int int_value;
#if TARGET_SUPPORTS_WIDE_INT == 0
/* This assert keeps the simplification from producing a result
@@ -1686,7 +1687,11 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
break;
case CLZ:
- result = wi::shwi (wi::clz (op0), mode);
+ if (wi::ne_p (op0, 0))
+ int_value = wi::clz (op0);
+ else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, int_value))
+ int_value = GET_MODE_PRECISION (mode);
+ result = wi::shwi (int_value, mode);
break;
case CLRSB:
@@ -1694,7 +1699,11 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
break;
case CTZ:
- result = wi::shwi (wi::ctz (op0), mode);
+ if (wi::ne_p (op0, 0))
+ int_value = wi::ctz (op0);
+ else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, int_value))
+ int_value = GET_MODE_PRECISION (mode);
+ result = wi::shwi (int_value, mode);
break;
case POPCOUNT:
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index dd880d1b921..0627cf5e5fd 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -1137,46 +1137,6 @@ wi::add_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *op0,
return canonize (val, len, prec);
}
-/* This is bogus. We should always return the precision and leave the
- caller to handle target dependencies. */
-static int
-clz_zero (unsigned int precision)
-{
- unsigned int count;
-
- enum machine_mode mode = mode_for_size (precision, MODE_INT, 0);
- if (mode == BLKmode)
- mode_for_size (precision, MODE_PARTIAL_INT, 0);
-
- /* Even if the value at zero is undefined, we have to come up
- with some replacement. Seems good enough. */
- if (mode == BLKmode)
- count = precision;
- else if (!CLZ_DEFINED_VALUE_AT_ZERO (mode, count))
- count = precision;
- return count;
-}
-
-/* This is bogus. We should always return the precision and leave the
- caller to handle target dependencies. */
-static int
-ctz_zero (unsigned int precision)
-{
- unsigned int count;
-
- enum machine_mode mode = mode_for_size (precision, MODE_INT, 0);
- if (mode == BLKmode)
- mode_for_size (precision, MODE_PARTIAL_INT, 0);
-
- /* Even if the value at zero is undefined, we have to come up
- with some replacement. Seems good enough. */
- if (mode == BLKmode)
- count = precision;
- else if (!CTZ_DEFINED_VALUE_AT_ZERO (mode, count))
- count = precision;
- return count;
-}
-
/* Subroutines of the multiplication and division operations. Unpack
the first IN_LEN HOST_WIDE_INTs in INPUT into 2 * IN_LEN
HOST_HALF_WIDE_INTs of RESULT. The rest of RESULT is filled by
@@ -2002,10 +1962,6 @@ wi::clz (const wide_int_ref &x)
/* The upper bit is set, so there are no leading zeros. */
return 0;
- /* Check whether the value is zero. */
- if (high == 0 && x.len == 1)
- return clz_zero (x.precision);
-
/* We don't need to look below HIGH. Either HIGH is nonzero,
or the top bit of the block below is nonzero; clz_hwi is
HOST_BITS_PER_WIDE_INT in the latter case. */
@@ -2047,7 +2003,7 @@ int
wi::ctz (const wide_int_ref &x)
{
if (x.len == 1 && x.ulow () == 0)
- return ctz_zero (x.precision);
+ return x.precision;
/* Having dealt with the zero case, there must be a block with a
nonzero bit. We don't care about the bits above the first 1. */