c-typeck.c (build_binary_op): Do not shorten unsigned right shift after sign extension.
authorRichard Henderson <rth@redhat.com>
Tue, 17 Jul 2001 19:01:54 +0000 (12:01 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 17 Jul 2001 19:01:54 +0000 (12:01 -0700)
        * c-typeck.c (build_binary_op): Do not shorten unsigned
        right shift after sign extension.

From-SVN: r44080

gcc/ChangeLog
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20010717-1.c [new file with mode: 0644]

index 49be9d88e57ca30af5193e6b0c5f2e680e4ca25a..39b7e980ca3fed5b53874c912f3cca4cc99000ca 100644 (file)
@@ -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
index 9e50c37da69f4a95abeec5e332f9663140848ae5..7bde430e8cb513f5bb2a3a11b4e0d725585eed45 100644 (file)
@@ -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);
index 5d8d2dc3102672bbf6678bb3e20209f73224d318..b266dfc357faaeb32f454b1b8562949f55ba895f 100644 (file)
@@ -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 (file)
index 0000000..65199da
--- /dev/null
@@ -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;
+}