This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

simplify_shift_const() breaks sign extraction of wider sign-extension


When combine attempts to combine:

(set (reg:DI B) (sign_extend:DI (reg:HI A)))
(set (reg:SI C) (lshiftrt:SI (subreg:SI (reg:DI B))
                             (const_int 31)))

It eventually asks simplify_shift_const() to simplify the LSHIFTRT.
It ends up transforming varop in:

(ashiftrt:DI (ashift:DI (subreg:DI (reg:HI A) 0) (const_int 48))
             (const_int 48))

And it discards the ashiftrt because the enclosing lshiftrt is
extracting just the sign bit.  However, it shouldn't do this if the
mode of varop is wider than that of the result, because then the
enclosed operation may not have the appropriate sign bit.  In this
case, the whole thing would be optimized to zero, because the left
shift would leave all the lower 32-bits as zero (because reg C would
eventually be truncated to HImode).

This patch fixes this problem.  Ok to install?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* combine.c (simplify_shift_const): Even if we're sign-extracting,
	don't discard an ASHIFTRT if we're shifting in a wider mode.

Index: gcc/combine.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/combine.c,v
retrieving revision 1.171
diff -u -p -r1.171 combine.c
--- gcc/combine.c 2000/12/21 18:48:24 1.171
+++ gcc/combine.c 2001/01/01 12:28:08
@@ -9132,7 +9132,9 @@ simplify_shift_const (x, code, result_mo
 	case ASHIFTRT:
 	  /* If we are extracting just the sign bit of an arithmetic right
 	     shift, that shift is not needed.  */
-	  if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1)
+	  if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1
+	      && (GET_MODE_BITSIZE (result_mode)
+		  >= GET_MODE_BITSIZE (GET_MODE (varop))))
 	    {
 	      varop = XEXP (varop, 0);
 	      continue;

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]