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] REQ_EQUAL notes vs. libcalls


In a recent discussion with Richard Henderson on the forms of REG_EQUAL
notes attached to libcalls, we discovered that GCC isn't currently
aggressive enough replacing libcalls by their constant values.

The example that was discussed was:

double foo()
{
  double x = 2.0;
  double y = 3.0;
  return x*y;
}

when compiled under i686-pc-linux-gnu with "-O2 -msoft-float".  CVS
mainline currently generates code that calls __muldf3 even though the
RTL optimizers manage to attach a REG_EQUAL note to the libcall indicating
that the returned value is always 6.0!

The patch below fixes this.  The most significant hunk is the change
to dead_libcall_p.  Simply inserting the constant in the set instruction
fails to validate.  Being a bit more aggressive, we should also try
putting the constant in the function's constant pool, and indeed for the
example above, the substituted instruction is then recognized by i386.md.

Whilst tracking down the issue, I made several minor tweaks to related
pieces of code.  We should always use set_unique_reg_note to place
REG_EQUAL notes on instructions rather than generate RTL ourselves.
Similarly, we should simplify the resulting RTL before placing it in
a REG_EQUAL note.  And in emit_move_insn, we should add REG_EQUAL notes
to moves, if the backend has obfuscated the constant being loaded.


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

Ok for mainline?


2003-03-01  Roger Sayle  <roger at eyesopen dot com>

	* cse.c (cse_insn): Simplify REG_EQUAL note on libcalls when
	making a substitution.
	(dead_libcall_p): If directly replacing a libcall with a
	constant value produces an invalid instruction, also try forcing
	the constant into the constant pool.
	* expr.c (emit_move_insn): Add a REG_EQUAL note when it is not
	obvious that the source is a constant.
	(compress_float_constant): Use set_unique_reg_note to place
	REG_EQUAL notes on instructions.


Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.255
diff -c -3 -p -r1.255 cse.c
*** cse.c	26 Feb 2003 10:48:34 -0000	1.255
--- cse.c	1 Mar 2003 00:04:35 -0000
*************** cse_insn (insn, libcall_insn)
*** 5550,5557 ****
  		  && (GET_CODE (sets[i].orig_src) == REG
  		      || GET_CODE (sets[i].orig_src) == SUBREG
  		      || GET_CODE (sets[i].orig_src) == MEM))
! 		replace_rtx (REG_NOTES (libcall_insn), sets[i].orig_src,
! 			     copy_rtx (new));

  	      /* The result of apply_change_group can be ignored; see
  		 canon_reg.  */
--- 5550,5557 ----
  		  && (GET_CODE (sets[i].orig_src) == REG
  		      || GET_CODE (sets[i].orig_src) == SUBREG
  		      || GET_CODE (sets[i].orig_src) == MEM))
! 		simplify_replace_rtx (REG_NOTES (libcall_insn),
! 				      sets[i].orig_src, copy_rtx (new));

  	      /* The result of apply_change_group can be ignored; see
  		 canon_reg.  */
*************** dead_libcall_p (insn, counts)
*** 7614,7646 ****
       rtx insn;
       int *counts;
  {
!   rtx note;
    /* See if there's a REG_EQUAL note on this insn and try to
       replace the source with the REG_EQUAL expression.

       We assume that insns with REG_RETVALs can only be reg->reg
       copies at this point.  */
    note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
!   if (note)
!     {
!       rtx set = single_set (insn);
!       rtx new = simplify_rtx (XEXP (note, 0));

!       if (!new)
! 	new = XEXP (note, 0);

!       /* While changing insn, we must update the counts accordingly.  */
!       count_reg_usage (insn, counts, NULL_RTX, -1);

!       if (set && validate_change (insn, &SET_SRC (set), new, 0))
  	{
!           count_reg_usage (insn, counts, NULL_RTX, 1);
  	  remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
  	  remove_note (insn, note);
  	  return true;
  	}
-        count_reg_usage (insn, counts, NULL_RTX, 1);
      }
    return false;
  }

--- 7614,7662 ----
       rtx insn;
       int *counts;
  {
!   rtx note, set, new;
!
    /* See if there's a REG_EQUAL note on this insn and try to
       replace the source with the REG_EQUAL expression.

       We assume that insns with REG_RETVALs can only be reg->reg
       copies at this point.  */
    note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
!   if (!note)
!     return false;
!
!   set = single_set (insn);
!   if (!set)
!     return false;

!   new = simplify_rtx (XEXP (note, 0));
!   if (!new)
!     new = XEXP (note, 0);

!   /* While changing insn, we must update the counts accordingly.  */
!   count_reg_usage (insn, counts, NULL_RTX, -1);

!   if (validate_change (insn, &SET_SRC (set), new, 0))
!     {
!       count_reg_usage (insn, counts, NULL_RTX, 1);
!       remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
!       remove_note (insn, note);
!       return true;
!     }
!
!   if (CONSTANT_P (new))
!     {
!       new = force_const_mem (GET_MODE (SET_DEST (set)), new);
!       if (new && validate_change (insn, &SET_SRC (set), new, 0))
  	{
! 	  count_reg_usage (insn, counts, NULL_RTX, 1);
  	  remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
  	  remove_note (insn, note);
  	  return true;
  	}
      }
+
+   count_reg_usage (insn, counts, NULL_RTX, 1);
    return false;
  }

Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.508
diff -c -3 -p -r1.508 expr.c
*** expr.c	26 Feb 2003 11:09:31 -0000	1.508
--- expr.c	1 Mar 2003 00:04:48 -0000
*************** emit_move_insn (x, y)
*** 3142,3148 ****
  {
    enum machine_mode mode = GET_MODE (x);
    rtx y_cst = NULL_RTX;
!   rtx last_insn;

    x = protect_from_queue (x, 1);
    y = protect_from_queue (y, 0);
--- 3142,3148 ----
  {
    enum machine_mode mode = GET_MODE (x);
    rtx y_cst = NULL_RTX;
!   rtx last_insn, set;

    x = protect_from_queue (x, 1);
    y = protect_from_queue (y, 0);
*************** emit_move_insn (x, y)
*** 3160,3168 ****
  	  && (last_insn = compress_float_constant (x, y)))
  	return last_insn;

        if (!LEGITIMATE_CONSTANT_P (y))
  	{
- 	  y_cst = y;
  	  y = force_const_mem (mode, y);

  	  /* If the target's cannot_force_const_mem prevented the spill,
--- 3160,3169 ----
  	  && (last_insn = compress_float_constant (x, y)))
  	return last_insn;

+       y_cst = y;
+
        if (!LEGITIMATE_CONSTANT_P (y))
  	{
  	  y = force_const_mem (mode, y);

  	  /* If the target's cannot_force_const_mem prevented the spill,
*************** emit_move_insn (x, y)
*** 3193,3199 ****

    last_insn = emit_move_insn_1 (x, y);

!   if (y_cst && GET_CODE (x) == REG)
      set_unique_reg_note (last_insn, REG_EQUAL, y_cst);

    return last_insn;
--- 3194,3203 ----

    last_insn = emit_move_insn_1 (x, y);

!   if (y_cst && GET_CODE (x) == REG
!       && (set = single_set (last_insn)) != NULL_RTX
!       && SET_DEST (set) == x
!       && ! rtx_equal_p (y_cst, SET_SRC (set)))
      set_unique_reg_note (last_insn, REG_EQUAL, y_cst);

    return last_insn;
*************** compress_float_constant (x, y)
*** 3542,3549 ****
        last_insn = get_last_insn ();

        if (GET_CODE (x) == REG)
! 	REG_NOTES (last_insn)
! 	  = gen_rtx_EXPR_LIST (REG_EQUAL, y, REG_NOTES (last_insn));

        return last_insn;
      }
--- 3546,3552 ----
        last_insn = get_last_insn ();

        if (GET_CODE (x) == REG)
! 	set_unique_reg_note (last_insn, REG_EQUAL, y);

        return last_insn;
      }

Roger
--
Roger Sayle,                         E-mail: roger at eyesopen dot 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]