This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] REQ_EQUAL notes vs. libcalls
- From: Roger Sayle <roger at www dot eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 1 Mar 2003 10:05:10 -0700 (MST)
- Subject: [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