[PATCH] Avoid memory wastage in simplify_replace_rtx

Roger Sayle roger@eyesopen.com
Sat Oct 25 18:29:00 GMT 2003


The following patch reduces the amount of RTL unnecessarily allocated
by GCC.  The routine simplify_replace_rtx in simplify-rtx.c is used
to substitute all occurances of one expression with another and return
the simplified substitution, which it does by recursively traversing
the RTX.

The inefficiency is that even if no substitutions are made to the
input expression, we still construct and attempt to simplify a new
identical expression, except at leaf nodes where we return the
original.

The following patch explicitly checks for this case where no change
is made to any of the expression's operands, in which case we can just
return the original.  It turns out that this case is extremely common
accounting for about 40% of the calls to simplify_replace_rtx, hence
we save about 132858 allocations out of 324785 during stage2, stage3
and the run-time libraries of a GCC bootstrap, all languages except
treelang.

In addition to the performance and memory usage improvements, this now
provides the RTL optimizers a simple way of checking whether the call
to simplify_replace_rtx actually changed anything.  This can be used
by the RTL optimizers to avoid re-recognizing instructions, etc... if
no changes were made [another potential performance improvement].


Although not a bug-fix per se, this obvious improvement may be acceptable
in stage3 of mainline?   The following patch has been tested with a full
"make bootstrap" on i686-pc-linux-gnu, all languages except treelang, and
regression tested with a top-level "make -k check" with no new failures.

Ok for mainline?


2003-10-25  Roger Sayle  <roger@eyesopen.com>

	* simplify-rtx.c (simplify_replace_rtx): Avoid allocating duplicate
	RTL nodes.  If an operator's operands are unchanged, return the
	original argument unchanged.


Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.163
diff -c -3 -p -r1.163 simplify-rtx.c
*** simplify-rtx.c	11 Oct 2003 21:06:15 -0000	1.163
--- simplify-rtx.c	24 Oct 2003 22:42:03 -0000
*************** simplify_replace_rtx (rtx x, rtx old, rt
*** 264,269 ****
--- 264,271 ----
  {
    enum rtx_code code = GET_CODE (x);
    enum machine_mode mode = GET_MODE (x);
+   enum machine_mode op_mode;
+   rtx op0, op1, op2;

    /* If X is OLD, return NEW.  Otherwise, if this is an expression, try
       to build a new expression substituting recursively.  If we can't do
*************** simplify_replace_rtx (rtx x, rtx old, rt
*** 275,349 ****
    switch (GET_RTX_CLASS (code))
      {
      case '1':
!       {
! 	enum machine_mode op_mode = GET_MODE (XEXP (x, 0));
! 	rtx op = (XEXP (x, 0) == old
! 		  ? new : simplify_replace_rtx (XEXP (x, 0), old, new));
!
! 	return simplify_gen_unary (code, mode, op, op_mode);
!       }

      case '2':
      case 'c':
!       return
! 	simplify_gen_binary (code, mode,
! 			     simplify_replace_rtx (XEXP (x, 0), old, new),
! 			     simplify_replace_rtx (XEXP (x, 1), old, new));
      case '<':
!       {
! 	enum machine_mode op_mode = (GET_MODE (XEXP (x, 0)) != VOIDmode
! 				     ? GET_MODE (XEXP (x, 0))
! 				     : GET_MODE (XEXP (x, 1)));
! 	rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
! 	rtx op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
! 	return simplify_gen_relational (code, mode, op_mode, op0, op1);
!       }

      case '3':
      case 'b':
!       {
! 	enum machine_mode op_mode = GET_MODE (XEXP (x, 0));
! 	rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
!
! 	return
! 	  simplify_gen_ternary (code, mode,
! 				(op_mode != VOIDmode
! 				 ? op_mode
! 				 : GET_MODE (op0)),
! 				op0,
! 				simplify_replace_rtx (XEXP (x, 1), old, new),
! 				simplify_replace_rtx (XEXP (x, 2), old, new));
!       }

      case 'x':
        /* The only case we try to handle is a SUBREG.  */
        if (code == SUBREG)
  	{
! 	  rtx exp;
! 	  exp = simplify_gen_subreg (GET_MODE (x),
! 				     simplify_replace_rtx (SUBREG_REG (x),
! 							   old, new),
  				     GET_MODE (SUBREG_REG (x)),
  				     SUBREG_BYTE (x));
! 	  if (exp)
! 	    x = exp;
  	}
!       return x;

      case 'o':
        if (code == MEM)
! 	return replace_equiv_address_nv (x,
! 					 simplify_replace_rtx (XEXP (x, 0),
! 							       old, new));
        else if (code == LO_SUM)
  	{
! 	  rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
! 	  rtx op1 = simplify_replace_rtx (XEXP (x, 1), old, new);

  	  /* (lo_sum (high x) x) -> x  */
  	  if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1))
  	    return op1;

  	  return gen_rtx_LO_SUM (mode, op0, op1);
  	}
        else if (code == REG)
--- 277,353 ----
    switch (GET_RTX_CLASS (code))
      {
      case '1':
!       op0 = XEXP (x, 0);
!       op_mode = GET_MODE (op0);
!       op0 = simplify_replace_rtx (op0, old, new);
!       if (op0 == XEXP (x, 0))
! 	return x;
!       return simplify_gen_unary (code, mode, op0, op_mode);

      case '2':
      case 'c':
!       op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
!       op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
!       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
! 	return x;
!       return simplify_gen_binary (code, mode, op0, op1);
!
      case '<':
!       op0 = XEXP (x, 0);
!       op1 = XEXP (x, 1);
!       op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
!       op0 = simplify_replace_rtx (op0, old, new);
!       op1 = simplify_replace_rtx (op1, old, new);
!       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
! 	return x;
!       return simplify_gen_relational (code, mode, op_mode, op0, op1);

      case '3':
      case 'b':
!       op0 = XEXP (x, 0);
!       op_mode = GET_MODE (op0);
!       op0 = simplify_replace_rtx (op0, old, new);
!       op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
!       op2 = simplify_replace_rtx (XEXP (x, 2), old, new);
!       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1) && op2 == XEXP (x, 2))
! 	return x;
!       if (op_mode == VOIDmode)
! 	op_mode = GET_MODE (op0);
!       return simplify_gen_ternary (code, mode, op_mode, op0, op1, op2);

      case 'x':
        /* The only case we try to handle is a SUBREG.  */
        if (code == SUBREG)
  	{
! 	  op0 = simplify_replace_rtx (SUBREG_REG (x), old, new);
! 	  if (op0 == SUBREG_REG (x))
! 	    return x;
! 	  op0 = simplify_gen_subreg (GET_MODE (x), op0,
  				     GET_MODE (SUBREG_REG (x)),
  				     SUBREG_BYTE (x));
! 	  return op0 ? op0 : x;
  	}
!       break;

      case 'o':
        if (code == MEM)
! 	{
! 	  op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
! 	  if (op0 == XEXP (x, 0))
! 	    return x;
! 	  return replace_equiv_address_nv (x, op0);
! 	}
        else if (code == LO_SUM)
  	{
! 	  op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
! 	  op1 = simplify_replace_rtx (XEXP (x, 1), old, new);

  	  /* (lo_sum (high x) x) -> x  */
  	  if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1))
  	    return op1;

+ 	  if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
+ 	    return x;
  	  return gen_rtx_LO_SUM (mode, op0, op1);
  	}
        else if (code == REG)
*************** simplify_replace_rtx (rtx x, rtx old, rt
*** 351,361 ****
  	  if (REG_P (old) && REGNO (x) == REGNO (old))
  	    return new;
  	}
!
!       return x;

      default:
!       return x;
      }
    return x;
  }
--- 355,364 ----
  	  if (REG_P (old) && REGNO (x) == REGNO (old))
  	    return new;
  	}
!       break;

      default:
!       break;
      }
    return x;
  }

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



More information about the Gcc-patches mailing list