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]

POINTER_EXTEND_UNSIGNED performance issues


I noticed that we were generating particularly bad code in the case
where ptr_mode != Pmode and tracked it down to some missing cases.  This
provides major performance enhancements and I ran it by Mark given the
status of the sources and he agrees it could go in now.

Basically, what this does is eliminate a lot of the SUBREG and
ZERO_EXTEND or SIGN_EXTEND operations relating to pointers so that CSE
and the other optimizers can do a much better job of tracking values.

Mon Feb  5 21:56:16 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>

	* combine.c (nonzero_bits, case PLUS): If pointers extend unsigned
	and this is the sum of a pointer and a constant, we know the result
	did not overflow.
	(num_sign_bit_copies, case PLUS): Likewise.
	* explow.c (convert_memory_address): Remove opposite SUBREG.
	* function.c (instantiate_new_reg): New function (from common code).
	(instantiate_virtual_regs_1): Call it.
	For PLUS, handle if (plus (subreg (virt-reg) (const_int))
	if pointers sign- or zero-extend.
	* simplify-rtx.c (simplify_unary_operation, case ZERO_EXTEND):
	If pointers extend unsigned, use inside of SUBREG.
	(simplify_unary_operation, case SIGN_EXTEND): Likewise, if sign extend.

*** combine.c	2001/01/30 22:27:44	1.182
--- combine.c	2001/02/06 02:50:47
*************** nonzero_bits (x, mode)
*** 8309,8312 ****
--- 8309,8322 ----
  	if (result_low > 0)
  	  nonzero &= ~(((HOST_WIDE_INT) 1 << result_low) - 1);
+ 
+ #ifdef POINTERS_EXTEND_UNSIGNED
+ 	/* If pointers extend unsigned and this is an addition or subtraction
+ 	   to a pointer in Pmode, all the bits above ptr_mode are known to be
+ 	   zero.  */
+ 	if (POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
+ 	    && (code == PLUS || code == MINUS)
+ 	    && GET_CODE (XEXP (x, 0)) == REG && REG_POINTER (XEXP (x, 0)))
+ 	  nonzero &= GET_MODE_MASK (ptr_mode);
+ #endif
        }
        break;
*************** num_sign_bit_copies (x, mode)
*** 8647,8651 ****
        num0 = num_sign_bit_copies (XEXP (x, 0), mode);
        num1 = num_sign_bit_copies (XEXP (x, 1), mode);
!       return MAX (1, MIN (num0, num1) - 1);
  
      case MULT:
--- 8657,8674 ----
        num0 = num_sign_bit_copies (XEXP (x, 0), mode);
        num1 = num_sign_bit_copies (XEXP (x, 1), mode);
!       result = MAX (1, MIN (num0, num1) - 1);
! 
! #ifdef POINTERS_EXTEND_UNSIGNED
!       /* If pointers extend signed and this is an addition or subtraction
! 	 to a pointer in Pmode, all the bits above ptr_mode are known to be
! 	 sign bit copies.  */
!       if (! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
! 	  && (code == PLUS || code == MINUS)
! 	  && GET_CODE (XEXP (x, 0)) == REG && REG_POINTER (XEXP (x, 0)))
! 	result = MAX ((GET_MODE_BITSIZE (Pmode)
! 		       - GET_MODE_BITSIZE (ptr_mode) + 1),
! 		      result);
! #endif
!       return result;
  
      case MULT:
*** explow.c	2001/02/01 12:29:18	1.57
--- explow.c	2001/02/06 02:51:28
*************** convert_memory_address (to_mode, x)
*** 387,390 ****
--- 387,395 ----
        return x;
  
+     case SUBREG:
+       if (GET_MODE (SUBREG_REG (x)) == to_mode)
+ 	return SUBREG_REG (x);
+       break;
+ 
      case LABEL_REF:
        temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0));
*** function.c	2001/01/20 13:40:23	1.248
--- function.c	2001/02/06 02:51:47
*************** static void instantiate_decls	PARAMS ((t
*** 270,273 ****
--- 270,274 ----
  static void instantiate_decls_1	PARAMS ((tree, int));
  static void instantiate_decl	PARAMS ((rtx, HOST_WIDE_INT, int));
+ static rtx instantiate_new_reg	PARAMS ((rtx, HOST_WIDE_INT *));
  static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int));
  static void delete_handlers	PARAMS ((void));
*************** instantiate_decl (x, size, valid_only)
*** 3681,3684 ****
--- 3682,3714 ----
  }
  
+ /* Given a piece of RTX and a pointer to a HOST_WIDE_INT, if the RTX
+    is a virtual register, return the requivalent hard register and set the
+    offset indirectly through the pointer.  Otherwise, return 0.  */
+ 
+ static rtx
+ instantiate_new_reg (x, poffset)
+      rtx x;
+      HOST_WIDE_INT *poffset;
+ {
+   rtx new;
+   HOST_WIDE_INT offset;
+ 
+   if (x == virtual_incoming_args_rtx)
+     new = arg_pointer_rtx, offset = in_arg_offset;
+   else if (x == virtual_stack_vars_rtx)
+     new = frame_pointer_rtx, offset = var_offset;
+   else if (x == virtual_stack_dynamic_rtx)
+     new = stack_pointer_rtx, offset = dynamic_offset;
+   else if (x == virtual_outgoing_args_rtx)
+     new = stack_pointer_rtx, offset = out_arg_offset;
+   else if (x == virtual_cfa_rtx)
+     new = arg_pointer_rtx, offset = cfa_offset;
+   else
+     return 0;
+ 
+   *poffset = offset;
+   return new;
+ }
+ 
  /* Given a pointer to a piece of rtx and an optional pointer to the
     containing object, instantiate any virtual registers present in it.
*************** instantiate_virtual_regs_1 (loc, object,
*** 3740,3758 ****
  	 appropriate offset.  This is used, for example, in the handling
  	 of non-local gotos.  */
!       if (SET_DEST (x) == virtual_incoming_args_rtx)
! 	new = arg_pointer_rtx, offset = -in_arg_offset;
!       else if (SET_DEST (x) == virtual_stack_vars_rtx)
! 	new = frame_pointer_rtx, offset = -var_offset;
!       else if (SET_DEST (x) == virtual_stack_dynamic_rtx)
! 	new = stack_pointer_rtx, offset = -dynamic_offset;
!       else if (SET_DEST (x) == virtual_outgoing_args_rtx)
! 	new = stack_pointer_rtx, offset = -out_arg_offset;
!       else if (SET_DEST (x) == virtual_cfa_rtx)
! 	new = arg_pointer_rtx, offset = -cfa_offset;
! 
!       if (new)
  	{
  	  rtx src = SET_SRC (x);
  
  	  instantiate_virtual_regs_1 (&src, NULL_RTX, 0);
  
--- 3770,3781 ----
  	 appropriate offset.  This is used, for example, in the handling
  	 of non-local gotos.  */
!       if ((new = instantiate_new_reg (SET_DEST (x), &offset)) != 0)
  	{
  	  rtx src = SET_SRC (x);
  
+ 	  /* We are setting the register, not using it, so the relevant
+ 	     offset is the negative of the offset to use were we using
+ 	     the register.  */
+ 	  offset = - offset;
  	  instantiate_virtual_regs_1 (&src, NULL_RTX, 0);
  
*************** instantiate_virtual_regs_1 (loc, object,
*** 3794,3809 ****
  	  if (GET_CODE (XEXP (x, 0)) == PLUS)
  	    {
! 	      rtx inner = XEXP (XEXP (x, 0), 0);
! 
! 	      if (inner == virtual_incoming_args_rtx)
! 		new = arg_pointer_rtx, offset = in_arg_offset;
! 	      else if (inner == virtual_stack_vars_rtx)
! 		new = frame_pointer_rtx, offset = var_offset;
! 	      else if (inner == virtual_stack_dynamic_rtx)
! 		new = stack_pointer_rtx, offset = dynamic_offset;
! 	      else if (inner == virtual_outgoing_args_rtx)
! 		new = stack_pointer_rtx, offset = out_arg_offset;
! 	      else if (inner == virtual_cfa_rtx)
! 		new = arg_pointer_rtx, offset = cfa_offset;
  	      else
  		{
--- 3817,3826 ----
  	  if (GET_CODE (XEXP (x, 0)) == PLUS)
  	    {
! 	      if ((new = instantiate_new_reg (XEXP (XEXP (x, 0), 0), &offset)))
! 		{
! 		  instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object,
! 					      extra_insns);
! 		  new = gen_rtx_PLUS (Pmode, new, XEXP (XEXP (x, 0), 1));
! 		}
  	      else
  		{
*************** instantiate_virtual_regs_1 (loc, object,
*** 3811,3831 ****
  		  goto restart;
  		}
- 
- 	      instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object,
- 					  extra_insns);
- 	      new = gen_rtx_PLUS (Pmode, new, XEXP (XEXP (x, 0), 1));
  	    }
  
! 	  else if (XEXP (x, 0) == virtual_incoming_args_rtx)
! 	    new = arg_pointer_rtx, offset = in_arg_offset;
! 	  else if (XEXP (x, 0) == virtual_stack_vars_rtx)
! 	    new = frame_pointer_rtx, offset = var_offset;
! 	  else if (XEXP (x, 0) == virtual_stack_dynamic_rtx)
! 	    new = stack_pointer_rtx, offset = dynamic_offset;
! 	  else if (XEXP (x, 0) == virtual_outgoing_args_rtx)
! 	    new = stack_pointer_rtx, offset = out_arg_offset;
! 	  else if (XEXP (x, 0) == virtual_cfa_rtx)
! 	    new = arg_pointer_rtx, offset = cfa_offset;
! 	  else
  	    {
  	      /* We know the second operand is a constant.  Unless the
--- 3828,3851 ----
  		  goto restart;
  		}
  	    }
  
! #ifdef POINTERS_EXTEND_UNSIGNED
! 	  /* If we have (plus (subreg (virtual-reg)) (const_int)), we know
! 	     we can commute the PLUS and SUBREG because pointers into the
! 	     frame are well-behaved.  */
! 	  else if (GET_CODE (XEXP (x, 0)) == SUBREG && GET_MODE (x) == ptr_mode
! 		   && GET_CODE (XEXP (x, 1)) == CONST_INT
! 		   && 0 != (new
! 			    = instantiate_new_reg (SUBREG_REG (XEXP (x, 0)),
! 						   &offset))
! 		   && validate_change (object, loc,
! 				       plus_constant (gen_lowpart (ptr_mode,
! 								   new),
! 						      offset
! 						      + INTVAL (XEXP (x, 1))),
! 				       0))
! 		return 1;
! #endif
! 	  else if ((new = instantiate_new_reg (XEXP (x, 0), &offset)) == 0)
  	    {
  	      /* We know the second operand is a constant.  Unless the
*************** instantiate_virtual_regs_1 (loc, object,
*** 4026,4041 ****
        /* Try to replace with a PLUS.  If that doesn't work, compute the sum
  	 in front of this insn and substitute the temporary.  */
!       if (x == virtual_incoming_args_rtx)
! 	new = arg_pointer_rtx, offset = in_arg_offset;
!       else if (x == virtual_stack_vars_rtx)
! 	new = frame_pointer_rtx, offset = var_offset;
!       else if (x == virtual_stack_dynamic_rtx)
! 	new = stack_pointer_rtx, offset = dynamic_offset;
!       else if (x == virtual_outgoing_args_rtx)
! 	new = stack_pointer_rtx, offset = out_arg_offset;
!       else if (x == virtual_cfa_rtx)
! 	new = arg_pointer_rtx, offset = cfa_offset;
! 
!       if (new)
  	{
  	  temp = plus_constant (new, offset);
--- 4046,4050 ----
        /* Try to replace with a PLUS.  If that doesn't work, compute the sum
  	 in front of this insn and substitute the temporary.  */
!       if ((new = instantiate_new_reg (x, &offset)) != 0)
  	{
  	  temp = plus_constant (new, offset);
*** simplify-rtx.c	2001/01/24 21:43:11	1.40
--- simplify-rtx.c	2001/02/06 02:52:01
*************** simplify_unary_operation (code, mode, op
*** 624,628 ****
  	  if (! POINTERS_EXTEND_UNSIGNED
  	      && mode == Pmode && GET_MODE (op) == ptr_mode
! 	      && CONSTANT_P (op))
  	    return convert_memory_address (Pmode, op);
  #endif
--- 624,632 ----
  	  if (! POINTERS_EXTEND_UNSIGNED
  	      && mode == Pmode && GET_MODE (op) == ptr_mode
! 	      && (CONSTANT_P (op)
! 		  || (GET_CODE (op) == SUBREG
! 		      && GET_CODE (SUBREG_REG (op)) == REG
! 		      && REG_POINTER (SUBREG_REG (op))
! 		      && GET_MODE (SUBREG_REG (op)) == Pmode)))
  	    return convert_memory_address (Pmode, op);
  #endif
*************** simplify_unary_operation (code, mode, op
*** 633,637 ****
  	  if (POINTERS_EXTEND_UNSIGNED
  	      && mode == Pmode && GET_MODE (op) == ptr_mode
! 	      && CONSTANT_P (op))
  	    return convert_memory_address (Pmode, op);
  	  break;
--- 637,645 ----
  	  if (POINTERS_EXTEND_UNSIGNED
  	      && mode == Pmode && GET_MODE (op) == ptr_mode
! 	      && (CONSTANT_P (op)
! 		  || (GET_CODE (op) == SUBREG
! 		      && GET_CODE (SUBREG_REG (op)) == REG
! 		      && REG_POINTER (SUBREG_REG (op))
! 		      && GET_MODE (SUBREG_REG (op)) == Pmode)))
  	    return convert_memory_address (Pmode, op);
  	  break;

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