aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZdenek Dvorak <dvorakz@suse.cz>2005-02-03 00:13:53 +0100
committerZdenek Dvorak <rakdver@gcc.gnu.org>2005-02-02 23:13:53 +0000
commit89d12f5d49829d3dbf9a78040b88df833923c0df (patch)
tree3537b64131b90538c5df621e848c272621fac78d
parent740ca4b2b10f7b6bd13568988b659b436143b1a9 (diff)
downloadgcc-89d12f5d49829d3dbf9a78040b88df833923c0df.zip
gcc-89d12f5d49829d3dbf9a78040b88df833923c0df.tar.gz
gcc-89d12f5d49829d3dbf9a78040b88df833923c0df.tar.bz2
tree.c (build_int_cst_type): Take sign of the value into account when deciding whether sign extend the value.
* tree.c (build_int_cst_type): Take sign of the value into account when deciding whether sign extend the value. From-SVN: r94633
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/tree.c47
2 files changed, 40 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 21fe9ba..31c8ea8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2005-02-02 Zdenek Dvorak <dvorakz@suse.cz>
+
+ * tree.c (build_int_cst_type): Take sign of the value into account
+ when deciding whether sign extend the value.
+
2005-02-02 Joseph S. Myers <joseph@codesourcery.com>
PR c/18502
diff --git a/gcc/tree.c b/gcc/tree.c
index 39309ff..6afc17f 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -497,39 +497,62 @@ build_int_cstu (tree type, unsigned HOST_WIDE_INT low)
return build_int_cst_wide (type, low, 0);
}
-/* Create an INT_CST node with a LOW value zero or sign extended depending
- on the type. */
+/* Create an INT_CST node with a LOW value in TYPE. The value is sign extended
+ if it is negative. This function is similar to build_int_cst, but
+ the extra bits outside of the type precision are cleared. Constants
+ with these extra bits may confuse the fold so that it detects overflows
+ even in cases when they do not occur, and in general should be avoided.
+ We cannot however make this a default behavior of build_int_cst without
+ more intrusive changes, since there are parts of gcc that rely on the extra
+ precision of the integer constants. */
tree
build_int_cst_type (tree type, HOST_WIDE_INT low)
{
unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low;
+ unsigned HOST_WIDE_INT hi;
unsigned bits;
bool signed_p;
bool negative;
- tree ret;
if (!type)
type = integer_type_node;
bits = TYPE_PRECISION (type);
signed_p = !TYPE_UNSIGNED (type);
- negative = ((val >> (bits - 1)) & 1) != 0;
- if (signed_p && negative)
+ if (bits >= HOST_BITS_PER_WIDE_INT)
+ negative = (low < 0);
+ else
{
- if (bits < HOST_BITS_PER_WIDE_INT)
+ /* If the sign bit is inside precision of LOW, use it to determine
+ the sign of the constant. */
+ negative = ((val >> (bits - 1)) & 1) != 0;
+
+ /* Mask out the bits outside of the precision of the constant. */
+ if (signed_p && negative)
val = val | ((~(unsigned HOST_WIDE_INT) 0) << bits);
- ret = build_int_cst_wide (type, val, ~(unsigned HOST_WIDE_INT) 0);
+ else
+ val = val & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
}
- else
+
+ /* Determine the high bits. */
+ hi = (negative ? ~(unsigned HOST_WIDE_INT) 0 : 0);
+
+ /* For unsigned type we need to mask out the bits outside of the type
+ precision. */
+ if (!signed_p)
{
- if (bits < HOST_BITS_PER_WIDE_INT)
- val = val & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
- ret = build_int_cst_wide (type, val, 0);
+ if (bits <= HOST_BITS_PER_WIDE_INT)
+ hi = 0;
+ else
+ {
+ bits -= HOST_BITS_PER_WIDE_INT;
+ hi = hi & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
+ }
}
- return ret;
+ return build_int_cst_wide (type, val, hi);
}
/* These are the hash table functions for the hash table of INTEGER_CST