aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1997-01-04 22:15:48 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1997-01-04 22:15:48 -0500
commit5cb1f2fa910c2132a95e9198c2966a1295937875 (patch)
tree5c08e08d93d0b67e716da3cf3a8dcb791ba8ec0d /gcc/tree.c
parent86b5812c1817f234a0f3e283e587f14c70fa90ba (diff)
downloadgcc-5cb1f2fa910c2132a95e9198c2966a1295937875.zip
gcc-5cb1f2fa910c2132a95e9198c2966a1295937875.tar.gz
gcc-5cb1f2fa910c2132a95e9198c2966a1295937875.tar.bz2
(integer_pow2): Mask value to width of type.
(tree_log2): New function. From-SVN: r13374
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index fde0e9d..c54cf6e 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1,5 +1,5 @@
/* Language-independent node constructors for parse phase of GNU compiler.
- Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -1625,6 +1625,7 @@ int
integer_pow2p (expr)
tree expr;
{
+ int prec;
HOST_WIDE_INT high, low;
STRIP_NOPS (expr);
@@ -1637,9 +1638,25 @@ integer_pow2p (expr)
if (TREE_CODE (expr) != INTEGER_CST || TREE_CONSTANT_OVERFLOW (expr))
return 0;
+ prec = (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
+ ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
high = TREE_INT_CST_HIGH (expr);
low = TREE_INT_CST_LOW (expr);
+ /* First clear all bits that are beyond the type's precision in case
+ we've been sign extended. */
+
+ if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+ ;
+ else if (prec > HOST_BITS_PER_WIDE_INT)
+ high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+ else
+ {
+ high = 0;
+ if (prec < HOST_BITS_PER_WIDE_INT)
+ low &= ~((HOST_WIDE_INT) (-1) << prec);
+ }
+
if (high == 0 && low == 0)
return 0;
@@ -1647,6 +1664,45 @@ integer_pow2p (expr)
|| (low == 0 && (high & (high - 1)) == 0));
}
+/* Return the power of two represented by a tree node known to be a
+ power of two. */
+
+int
+tree_log2 (expr)
+ tree expr;
+{
+ int prec;
+ HOST_WIDE_INT high, low;
+
+ STRIP_NOPS (expr);
+
+ if (TREE_CODE (expr) == COMPLEX_CST)
+ return tree_log2 (TREE_REALPART (expr));
+
+ prec = (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
+ ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
+
+ high = TREE_INT_CST_HIGH (expr);
+ low = TREE_INT_CST_LOW (expr);
+
+ /* First clear all bits that are beyond the type's precision in case
+ we've been sign extended. */
+
+ if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+ ;
+ else if (prec > HOST_BITS_PER_WIDE_INT)
+ high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+ else
+ {
+ high = 0;
+ if (prec < HOST_BITS_PER_WIDE_INT)
+ low &= ~((HOST_WIDE_INT) (-1) << prec);
+ }
+
+ return (high != 0 ? HOST_BITS_PER_WIDE_INT + exact_log2 (high)
+ : exact_log2 (low));
+}
+
/* Return 1 if EXPR is the real constant zero. */
int