Global.c/multiple set insns tweak
Jan Hubicka
hubicka@atrey.karlin.mff.cuni.cz
Mon Jan 10 04:31:00 GMT 2000
In multiple sets insns global makes the registers mentioned in outputs to
conflict with all registers used in inputs:
/* If INSN has multiple outputs, then any reg that dies here
and is used inside of an output
must conflict with the other outputs.
It is unsafe to use !single_set here since it will ignore an
unused output. Just because an output is unused does not mean
the compiler can assume the side effect will not occur.
Consider if REG appears in the address of an output and we
reload the output. If we allocate REG to the same hard
register as an unused output we could set the hard register
before the output reload insn. */
I expect this is done because when reload attempts to output output reload,
it might end up in wrong move insn, because the register used in address was
clobbered by another set of the insn.
I am trying to model i386 movs? instructions correctly and they needs exactly
such insn (one set makes the string copy, while other set alters the ESI,
EDI and ECX registers).
The extra conflict results in very bad code even when it is completely
irrelevat, because the BLKmode address can not be reloaded.
So the patch makes global.c to extract insn and do the conflicts only for
real output operands...
This also helps to zero_extract and similar patterns.
Honza
San Jan 9 05:03:20 CET 2000 Jan Hubicka <jh@suse.cz>
* global.c (global_conflicts): Mark conflict only for real output
operands in multiple set insns.
Index: egcs/gcc/global.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/global.c,v
retrieving revision 1.52
diff -c -3 -p -r1.52 global.c
*** global.c 1999/12/20 12:13:01 1.52
--- global.c 2000/01/10 12:27:44
*************** Boston, MA 02111-1307, USA. */
*** 34,39 ****
--- 34,40 ----
#include "reload.h"
#include "output.h"
#include "toplev.h"
+ #include "recog.h"
/* This pass of the compiler performs global register allocation.
It assigns hard register numbers to all the pseudo registers
*************** global_conflicts ()
*** 782,806 ****
register as an unused output we could set the hard register
before the output reload insn. */
if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn))
! for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
! if (REG_NOTE_KIND (link) == REG_DEAD)
! {
! int used_in_output = 0;
! int i;
! rtx reg = XEXP (link, 0);
!
! for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
! {
! rtx set = XVECEXP (PATTERN (insn), 0, i);
! if (GET_CODE (set) == SET
! && GET_CODE (SET_DEST (set)) != REG
! && !rtx_equal_p (reg, SET_DEST (set))
! && reg_overlap_mentioned_p (reg, SET_DEST (set)))
! used_in_output = 1;
! }
! if (used_in_output)
! mark_reg_conflicts (reg);
! }
/* Mark any registers set in INSN and then never used. */
--- 783,812 ----
register as an unused output we could set the hard register
before the output reload insn. */
if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn))
! {
! extract_insn (insn);
! for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
! if (REG_NOTE_KIND (link) == REG_DEAD)
! {
! int used_in_output = 0;
! int i;
! rtx reg = XEXP (link, 0);
!
! for (i = recog_data.n_operands; i >= 0; i--)
! {
! rtx op = recog_data.operand[i];
! if (recog_data.operand_type[i] != OP_IN
! && GET_CODE (op) != REG
! && (GET_CODE (op) != SUBREG
! || GET_CODE (SUBREG_REG (op)) != REG)
! && !rtx_equal_p (reg, op)
! && reg_overlap_mentioned_p (reg, op))
! used_in_output = 1;
! }
! if (used_in_output)
! mark_reg_conflicts (reg);
! }
! }
/* Mark any registers set in INSN and then never used. */
More information about the Gcc-patches
mailing list