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]
Other format: [Raw text]

[PATCH] Optimize subregs of zero and sign extensions


The following patch is an enhancement to simplify_subreg to optimize
subreg truncations of zero and sign extensions.  It was originally
developed to implement Paolo Bonzini's (subreg (zero_extend ...)) =>
const0_rtx optimization, but whilst I was there I also noticed we were
missing several related optimizations.

(subreg:SI (zero_extend:DI (foo:SI)) 0) => (foo:SI)
(subreg:SI (sign_extend:DI (foo:SI)) 0) => (foo:SI)
(subreg:HI (zero_extend:DI (foo:SI)) 0) => (subreg:HI (foo:SI) 0)
(subreg:HI (sign_extend:DI (foo:SI)) 0) => (subreg:HI (foo:SI) 0)
(subreg:SI (zero_extend:DI (foo:HI)) 0) => (zero_extend:SI (foo:HI))
(subreg:SI (sign_extend:DI (foo:HI)) 0) => (sign_extend:SI (foo:HI))


I'd expect these transformations to really help 64-bit targets, and
targets that hold 32-bit (or shorter) quantities in 64-bit registers.

The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all languages except treelang, and regression tested
with a top-level "make -k check" with no new failures.

Ok for mainline?

2004-01-21  Roger Sayle  <roger@eyesopen.com>
	    Paolo Bonzini  <bonzini@gnu.org>

	* simplify-rtx.c (simplify_subreg): Optimize subregs of zero and
	sign extensions.


Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.173
diff -c -3 -p -r1.173 simplify-rtx.c
*** simplify-rtx.c	19 Jan 2004 21:51:06 -0000	1.173
--- simplify-rtx.c	21 Jan 2004 15:23:54 -0000
*************** simplify_subreg (enum machine_mode outer
*** 3379,3386 ****
        res = simplify_subreg (outermode, part, GET_MODE (part), final_offset);
        if (res)
  	return res;
!       /* We can at least simplify it by referring directly to the relevant part.  */
        return gen_rtx_SUBREG (outermode, part, final_offset);
      }

    return NULL_RTX;
--- 3379,3435 ----
        res = simplify_subreg (outermode, part, GET_MODE (part), final_offset);
        if (res)
  	return res;
!       /* We can at least simplify it by referring directly to the
! 	 relevant part.  */
        return gen_rtx_SUBREG (outermode, part, final_offset);
+     }
+
+   /* Optimize SUBREG truncations of zero and sign extended values.  */
+   if ((GET_CODE (op) == ZERO_EXTEND
+        || GET_CODE (op) == SIGN_EXTEND)
+       && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode))
+     {
+       unsigned int lsbword, lsbbyte, lsbbitpos;
+
+       if (WORDS_BIG_ENDIAN)
+ 	lsbword = (GET_MODE_SIZE (innermode)
+ 		   - (byte + GET_MODE_SIZE (outermode))) / UNITS_PER_WORD;
+       else
+ 	lsbword = byte / UNITS_PER_WORD;
+       lsbbitpos = lsbword * BITS_PER_WORD;
+
+       if (BYTES_BIG_ENDIAN)
+ 	lsbbyte = (GET_MODE_SIZE (innermode)
+ 		   - (byte + GET_MODE_SIZE (outermode))) % UNITS_PER_WORD;
+       else
+ 	lsbbyte = byte % UNITS_PER_WORD;
+       lsbbitpos += lsbbyte * BITS_PER_UNIT;
+
+       /* If we're requesting the lowpart of a zero or sign extension,
+ 	 there are three possibilities.  If the outermode is the same
+ 	 as the origmode, we can omit both the extension and the subreg.
+ 	 If the outermode is not larger than the origmode, we can apply
+ 	 the truncation without the extension.  Finally, if the outermode
+ 	 is larger than the origmode, but both are integer modes, we
+ 	 can just extend to the appropriate mode.  */
+       if (lsbbitpos == 0)
+ 	{
+ 	  enum machine_mode origmode = GET_MODE (XEXP (op, 0));
+ 	  if (outermode == origmode)
+ 	    return XEXP (op, 0);
+ 	  if (GET_MODE_BITSIZE (outermode) <= GET_MODE_BITSIZE (origmode))
+ 	    return simplify_gen_subreg (outermode, XEXP (op, 0),
+ 					origmode, byte);
+ 	  if (SCALAR_INT_MODE_P (outermode))
+ 	    return simplify_gen_unary (GET_CODE (op), outermode,
+ 				       XEXP (op, 0), origmode);
+ 	}
+
+       /* A SUBREG resulting from a zero extension may fold to zero if
+ 	 it extracts higher bits that the ZERO_EXTEND's source bits.  */
+       if (GET_CODE (op) == ZERO_EXTEND
+ 	  && lsbbitpos >= GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))))
+ 	return const0_rtx;
      }

    return NULL_RTX;

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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