aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2001-07-17 12:01:54 -0700
committerRichard Henderson <rth@gcc.gnu.org>2001-07-17 12:01:54 -0700
commit91a18fe0e6d96ec2cdad7d4f12ada3b4f5ed11e6 (patch)
treec9572ed6e5246afd03ce187bb2507cce9039341a
parent4fe706d8e0fc99538a988e63a3db7f529cd561d6 (diff)
downloadgcc-91a18fe0e6d96ec2cdad7d4f12ada3b4f5ed11e6.zip
gcc-91a18fe0e6d96ec2cdad7d4f12ada3b4f5ed11e6.tar.gz
gcc-91a18fe0e6d96ec2cdad7d4f12ada3b4f5ed11e6.tar.bz2
c-typeck.c (build_binary_op): Do not shorten unsigned right shift after sign extension.
* c-typeck.c (build_binary_op): Do not shorten unsigned right shift after sign extension. From-SVN: r44080
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/c-typeck.c16
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20010717-1.c22
4 files changed, 34 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 49be9d8..39b7e98 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2001-07-17 Richard Henderson <rth@redhat.com>
+
+ * c-typeck.c (build_binary_op): Do not shorten unsigned
+ right shift after sign extension.
+
Tue Jul 17 16:56:05 CEST 2001 Jan Hubicka <jh@suse.cz>
* combine.c (combine_simplify_rtx): Attempt to simplify
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 9e50c37..7bde430 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -2469,22 +2469,12 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
/* We can shorten only if the shift count is less than the
number of bits in the smaller type size. */
&& compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
- /* If arg is sign-extended and then unsigned-shifted,
- we can simulate this with a signed shift in arg's type
- only if the extended result is at least twice as wide
- as the arg. Otherwise, the shift could use up all the
- ones made by sign-extension and bring in zeros.
- We can't optimize that case at all, but in most machines
- it never happens because available widths are 2**N. */
- && (!TREE_UNSIGNED (final_type)
- || unsigned_arg
- || (2 * TYPE_PRECISION (TREE_TYPE (arg0))
- <= TYPE_PRECISION (result_type))))
+ /* We cannot drop an unsigned shift after sign-extension. */
+ && (!TREE_UNSIGNED (final_type) || unsigned_arg))
{
/* Do an unsigned shift if the operand was zero-extended. */
result_type
- = signed_or_unsigned_type (unsigned_arg,
- TREE_TYPE (arg0));
+ = signed_or_unsigned_type (unsigned_arg, TREE_TYPE (arg0));
/* Convert value-to-be-shifted to that type. */
if (TREE_TYPE (op0) != result_type)
op0 = convert (result_type, op0);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5d8d2dc..b266dfc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2001-07-17 Richard Henderson <rth@redhat.com>
+
+ * gcc.c-torture/execute/20010717-1.c: New.
+
2001-07-17 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.c-torture/compile/20010714-1.c, gcc.dg/format/attr-4.c: New
diff --git a/gcc/testsuite/gcc.c-torture/execute/20010717-1.c b/gcc/testsuite/gcc.c-torture/execute/20010717-1.c
new file mode 100644
index 0000000..65199da
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20010717-1.c
@@ -0,0 +1,22 @@
+extern void abort (void);
+
+int
+main ()
+{
+ int i, j;
+ unsigned long u, r1, r2;
+
+ i = -16;
+ j = 1;
+ u = i + j;
+
+ /* no sign extension upon shift */
+ r1 = u >> 1;
+ /* sign extension upon shift, but there shouldn't be */
+ r2 = ((unsigned long) (i + j)) >> 1;
+
+ if (r1 != r2)
+ abort ();
+
+ return 0;
+}