[PATCH] Add reg_truncated_to_mode to rtl_hooks

Adam Nemet anemet@sonic.net
Fri Feb 17 09:31:00 GMT 2006


This patch adds reg_truncated_to_mode to rtl_hooks.  With this we can
now turn TRUNCATEs into SUBREGs in simplify_unary_operation_1.  The
patch is similar to the respective part of Paolo Bonzini's patch from
http://gcc.gnu.org/ml/gcc-patches/2006-02/msg00684.html.

With these changes we remove seven truncations in
gcc.c-torture/execute.  They all seem to have been unnecessary.

While working on this I noticed a bug in simplify_unary_operation_1:

   620	      /* If we know that the value is already truncated, we can
   621	         replace the TRUNCATE with a SUBREG if TRULY_NOOP_TRUNCATION
   622	         is nonzero for the corresponding modes.  But don't do this
   623	         for an (LSHIFTRT (MULT ...)) since this will cause problems
   624	         with the umulXi3_highpart patterns.  */
   625	      if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
   626					 GET_MODE_BITSIZE (GET_MODE (op)))
   627		  && num_sign_bit_copies (op, GET_MODE (op))
   628		     >= (unsigned int) (GET_MODE_BITSIZE (mode) + 1)
   629		  && ! (GET_CODE (op) == LSHIFTRT
   630			&& GET_CODE (XEXP (op, 0)) == MULT))
   631		return rtl_hooks.gen_lowpart_no_emit (mode, op);

I think in the num_sign_bit_copies check the number of sign bits
should be greater than GET_MODE (op) - GET_MODE_BITSIZE (mode).  The
code happens to work because this type of truncate is typically used
to truncate to mode half the size of the original mode.  I am changing
this piece of code but I would prefer to submit a separate patch with
the fix.

Regression tested on mipsisa64-elf and bootstrapped and
regression-tested on i686-pc-linux-gnu.

OK to apply?

Adam

2006-02-16  Paolo Bonzini  <bonzini@gnu.org>
	    Adam Nemet  <anemet@caviumnetworks.com>

	* rtl.h (truncated_to_mode): Declare it.
	(struct rtl_hooks): Add reg_truncated_to_mode hook.
	* rtlhooks-def.h (RTL_HOOKS_REG_TRUNCATED_TO_MODE): New macro.
	(RTL_HOOKS_INITIALIZER): Include it.
	* rtlhooks.c (reg_truncated_to_mode_general): New function.
	* combine.c (RTL_HOOKS_REG_TRUNCATED_TO_MODE): Override to
	reg_truncated_to_mode.
	* rtlanal.c (truncated_to_mode): Define it.
	* simplify-rtx.c (simplify_unary_operation_1): Use it.

Index: rtlhooks.c
===================================================================
*** rtlhooks.c	(revision 110908)
--- rtlhooks.c	(working copy)
*************** reg_nonzero_bits_general (rtx x ATTRIBUT
*** 117,122 ****
--- 117,129 ----
    return NULL;
  }
  
+ bool
+ reg_truncated_to_mode_general (enum machine_mode mode ATTRIBUTE_UNUSED,
+ 			       rtx x ATTRIBUTE_UNUSED)
+ {
+   return false;
+ }
+ 
  /* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a fixed-point
     number, return an rtx (MEM, SUBREG, or CONST_INT) that refers to the
     least-significant part of X.
Index: rtlanal.c
===================================================================
*** rtlanal.c	(revision 110908)
--- rtlanal.c	(working copy)
*************** get_condition (rtx jump, rtx *earliest, 
*** 4786,4791 ****
--- 4786,4801 ----
  				 allow_cc_mode, valid_at_insn_p);
  }
  
+ /* Suppose that truncation from the machine mode of X to MODE is not a
+    no-op.  See if there is anything special about X so that we can
+    assume it already contains a truncated value of MODE.  */
+ 
+ bool
+ truncated_to_mode (enum machine_mode mode, rtx x)
+ {
+   return REG_P (x) && rtl_hooks.reg_truncated_to_mode (mode, x);
+ }
+ 
  
  /* Initialize non_rtx_starting_operands, which is used to speed up
     for_each_rtx.  */
Index: rtlhooks-def.h
===================================================================
*** rtlhooks-def.h	(revision 110908)
--- rtlhooks-def.h	(working copy)
*************** Boston, MA 02110-1301, USA.  */
*** 27,32 ****
--- 27,33 ----
  #define RTL_HOOKS_GEN_LOWPART_NO_EMIT gen_lowpart_no_emit_general
  #define RTL_HOOKS_REG_NONZERO_REG_BITS reg_nonzero_bits_general
  #define RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES reg_num_sign_bit_copies_general
+ #define RTL_HOOKS_REG_TRUNCATED_TO_MODE reg_truncated_to_mode_general
  
  /* The structure is defined in rtl.h.  */
  #define RTL_HOOKS_INITIALIZER {			\
*************** Boston, MA 02110-1301, USA.  */
*** 34,39 ****
--- 35,41 ----
    RTL_HOOKS_GEN_LOWPART_NO_EMIT,		\
    RTL_HOOKS_REG_NONZERO_REG_BITS,		\
    RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES,		\
+   RTL_HOOKS_REG_TRUNCATED_TO_MODE,		\
  }
  
  extern rtx gen_lowpart_general (enum machine_mode, rtx);
*************** extern rtx reg_nonzero_bits_general (rtx
*** 45,49 ****
--- 47,52 ----
  extern rtx reg_num_sign_bit_copies_general (rtx, enum machine_mode, rtx,
  					    enum machine_mode,
  					    unsigned int, unsigned int *);
+ extern bool reg_truncated_to_mode_general (enum machine_mode, rtx);
  
  #endif /* GCC_RTL_HOOKS_DEF_H */
Index: simplify-rtx.c
===================================================================
*** simplify-rtx.c	(revision 110990)
--- simplify-rtx.c	(working copy)
*************** simplify_unary_operation_1 (enum rtx_cod
*** 618,631 ****
  				   GET_MODE (XEXP (SUBREG_REG (op), 0)));
  
        /* If we know that the value is already truncated, we can
!          replace the TRUNCATE with a SUBREG if TRULY_NOOP_TRUNCATION
!          is nonzero for the corresponding modes.  But don't do this
!          for an (LSHIFTRT (MULT ...)) since this will cause problems
!          with the umulXi3_highpart patterns.  */
!       if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
  				 GET_MODE_BITSIZE (GET_MODE (op)))
! 	  && num_sign_bit_copies (op, GET_MODE (op))
! 	     >= (unsigned int) (GET_MODE_BITSIZE (mode) + 1)
  	  && ! (GET_CODE (op) == LSHIFTRT
  		&& GET_CODE (XEXP (op, 0)) == MULT))
  	return rtl_hooks.gen_lowpart_no_emit (mode, op);
--- 618,634 ----
  				   GET_MODE (XEXP (SUBREG_REG (op), 0)));
  
        /* If we know that the value is already truncated, we can
!          replace the TRUNCATE with a SUBREG.  Note that this is also
!          valid if TRULY_NOOP_TRUNCATION is false for the corresponding
!          modes we just have to apply a different definition for
!          truncation.  But don't do this for an (LSHIFTRT (MULT ...)) 
!          since this will cause problems with the umulXi3_highpart
!          patterns.  */
!       if ((TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
  				 GET_MODE_BITSIZE (GET_MODE (op)))
! 	   ? (num_sign_bit_copies (op, GET_MODE (op))
! 	      >= (unsigned int) (GET_MODE_BITSIZE (mode) + 1))
! 	   : truncated_to_mode (mode, op))
  	  && ! (GET_CODE (op) == LSHIFTRT
  		&& GET_CODE (XEXP (op, 0)) == MULT))
  	return rtl_hooks.gen_lowpart_no_emit (mode, op);
Index: rtl.h
===================================================================
*** rtl.h	(revision 110908)
--- rtl.h	(working copy)
*************** extern bool subreg_offset_representable_
*** 980,985 ****
--- 980,986 ----
  extern unsigned int subreg_regno (rtx);
  extern unsigned HOST_WIDE_INT nonzero_bits (rtx, enum machine_mode);
  extern unsigned int num_sign_bit_copies (rtx, enum machine_mode);
+ extern bool truncated_to_mode (enum machine_mode, rtx);
  
  
  /* 1 if RTX is a subreg containing a reg that is already known to be
*************** struct rtl_hooks
*** 2190,2197 ****
  			   unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT *);
    rtx (*reg_num_sign_bit_copies) (rtx, enum machine_mode, rtx, enum machine_mode,
  				  unsigned int, unsigned int *);
  
!   /* Whenever you add entries here, make sure you adjust hosthooks-def.h.  */
  };
  
  /* Each pass can provide its own.  */
--- 2191,2199 ----
  			   unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT *);
    rtx (*reg_num_sign_bit_copies) (rtx, enum machine_mode, rtx, enum machine_mode,
  				  unsigned int, unsigned int *);
+   bool (*reg_truncated_to_mode) (enum machine_mode, rtx);
  
!   /* Whenever you add entries here, make sure you adjust rtlhooks-def.h.  */
  };
  
  /* Each pass can provide its own.  */
Index: combine.c
===================================================================
*** combine.c	(revision 110908)
--- combine.c	(working copy)
*************** static rtx gen_lowpart_or_truncate (enum
*** 457,462 ****
--- 457,465 ----
  #undef RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES
  #define RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES  reg_num_sign_bit_copies_for_combine
  
+ #undef RTL_HOOKS_REG_TRUNCATED_TO_MODE
+ #define RTL_HOOKS_REG_TRUNCATED_TO_MODE    reg_truncated_to_mode
+ 
  static const struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER;
  
  



More information about the Gcc-patches mailing list