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]

Re: Tweak IRA checks for singleton register classes


On 12-09-30 2:21 PM, Richard Sandiford wrote:
IRA has code to check whether there is only a single acceptable register
for a given operand.  This code uses conditions like:

   ira_class_hard_regs_num[cl] != 0
   && (ira_class_hard_regs_num[cl] <= ira_reg_class_max_nregs[cl][mode])

i.e. the number of registers needed to store the mode is >=
the number of alloctable registers in the class.  Then:

ira_class_hard_regs[cl][0]

gives the register in question.

MIPS has a slightly strange situation in which HI can only be allocated
alongside LO; it can't be allocated independently.  At the moment,
HI and LO have their own register classes (MD0_REG and MD1_REG,
with the mapping depending on endianness) and MD_REGS is used when both
HI and LO are required.  There is also ACC_REGS, which is equivalent to
MD_REGS when the DSP ASE is not being used.  MD_REGS and ACC_REGS are
already mapped to constraints.

Having MD0_REG and MD1_REG leads to some confusing costs and makes
HI and LO irregular WRT the DSP ASE accumulator registers.  I've been
experimenting with patches to remove these classes and just have MD_REGS.
I wanted to get to a situtation where this change has no effect on cc1 .ii
files for -mno-dsp; the patch below is one of those needed to get to that
stage.

MD_REGS has only one SImode register.  As describe above, the same goes
for ACC_REGS unless the DSP ASE is being used.  However, both classes
fail the check above because HI (which doesn't accept SImode) is also
allocatable.  That is, the classes have two allocatable registers,
but only one of them can be used for SImode.

The patch below adds a new array for tracking which class/mode
combinations specify a single register, and for recording which
register that is.  The net effect will be the same on almost all
targets.

I deliberately didn't change:

	      for (p2 = &reg_class_subclasses[cl2][0];
		   *p2 != LIM_REG_CLASSES; p2++)
		if (ira_class_hard_regs_num[*p2] > 0
		    && (ira_reg_class_max_nregs[*p2][mode]
			<= ira_class_hard_regs_num[*p2]))
		  cost = MAX (cost, ira_register_move_cost[mode][cl1][*p2]);

	      for (p1 = &reg_class_subclasses[cl1][0];
		   *p1 != LIM_REG_CLASSES; p1++)
		if (ira_class_hard_regs_num[*p1] > 0
		    && (ira_reg_class_max_nregs[*p1][mode]
			<= ira_class_hard_regs_num[*p1]))
		  cost = MAX (cost, ira_register_move_cost[mode][*p1][cl2]);

from ira_init_register_move_cost because that had more effect
than I was expecting and wasn't needed for the MIPS patch.
It could be done as a follow-up if I ever find time...

I checked that this produced no difference in assembly output for
a set of x86_64 gcc .ii files (tested with -O2 -march=native on gcc20).
Also tested on x86_64-linux-gnu (including -m32) and mipsisa64-elf.
OK to install?
It is OK for me, Richard. Although it was hard to me understand correctness of the following changes.

Thanks for the patch.
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c 2012-09-30 12:56:14.344185269 +0100
+++ gcc/ira-lives.c 2012-09-30 17:45:14.962463976 +0100
@@ -849,9 +849,10 @@ single_reg_class (const char *constraint
next_cl = (c == 'r'
? GENERAL_REGS
: REG_CLASS_FROM_CONSTRAINT (c, constraints));
- if ((cl != NO_REGS && next_cl != cl)
- || (ira_class_hard_regs_num[next_cl]
- > ira_reg_class_max_nregs[next_cl][GET_MODE (op)]))
+ if (cl == NO_REGS
+ ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
+ : (ira_class_singleton[cl][GET_MODE (op)]
+ != ira_class_singleton[next_cl][GET_MODE (op)]))
return NO_REGS;
cl = next_cl;
break;
@@ -861,10 +862,10 @@ single_reg_class (const char *constraint
next_cl
= single_reg_class (recog_data.constraints[c - '0'],
recog_data.operand[c - '0'], NULL_RTX);
- if ((cl != NO_REGS && next_cl != cl)
- || next_cl == NO_REGS
- || (ira_class_hard_regs_num[next_cl]
- > ira_reg_class_max_nregs[next_cl][GET_MODE (op)]))
+ if (cl == NO_REGS
+ ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
+ : (ira_class_singleton[cl][GET_MODE (op)]
+ != ira_class_singleton[next_cl][GET_MODE (op)]))
return NO_REGS;
cl = next_cl;
break;




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