From 91a18fe0e6d96ec2cdad7d4f12ada3b4f5ed11e6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 17 Jul 2001 12:01:54 -0700 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 +++++ gcc/c-typeck.c | 16 +++----------- gcc/testsuite/ChangeLog | 4 ++++ .../gcc.c-torture/execute/20010717-1.c | 22 +++++++++++++++++++ 4 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/20010717-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 49be9d88e57..39b7e980ca3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2001-07-17 Richard Henderson + + * 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 * combine.c (combine_simplify_rtx): Attempt to simplify diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 9e50c37da69..7bde430e8cb 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 5d8d2dc3102..b266dfc357f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-07-17 Richard Henderson + + * gcc.c-torture/execute/20010717-1.c: New. + 2001-07-17 Joseph S. Myers * 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 00000000000..65199da9035 --- /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; +} -- 2.30.2