Re: [PATCH RFC] Finer grained reg classes.

2013-04-27 Thread Richard Sandiford
David Miller da...@davemloft.net writes:
 So this patch tries to rework the semantics of hard register classes,
 such that if a hard register is present in the set it is implied that
 the rest of the registers in a multi-register group are present as
 well.  So we can add a register class called EVEN_REGS and only have
 to set the even register bits.

It would be great if this could be made to work.  I think the main
problem is going to be stopping registers from other register files
being included accidentally.  E.g. if on a 32-bit target you store
a 128-bit value in an even GPR, using the GPR class itself ensures
that all four registers are GPRs.  The last even GPR is automatically
disallowed.  If instead we say that only the first register needs to
belong to the class, I assume we'd need both an EVEN_REGS and an
EVEN_REGS_EXCEPT_... class.

I must admit I don't really understand why HARD_REGNO_MODE_OK() is a
problem for IRA and LRA.  Although they work on register classes,
most of the internal calculations are done on register sets,
which can be masked as needed.  E.g. ira_prohibited_class_mode_regs
already takes HARD_REGNO_MODE_OK() into account.  And even if the
register class itself only gives the first register, all the conflict
calculations are still going to need to include all registers.

I'm probably repeating a previous discussion here, sorry.

Richard


[PATCH RFC] Finer grained reg classes.

2013-03-19 Thread David Miller

This is very much a work in progress, but I think it has potential
to solve the problem at hand.

A major blocker for using LRA on sparc is a fundamental limitation of
register classes as currently implemented.

If you have an instruction that requires an evenly aligned hard
register pair, you cannot describe this alone using register classes.

That's because register classes must contain all registers of a
multiple register set, which effectively would allow both even
and odd registers, thus not constraining the hard registers which
are valid at all.

Targets work around this by using HARD_REGNO_MODE_OK(), which causes
pre-LRA reload to fix up all the hard register allocation mistakes
made by IRA, the latter of which relies largely upon register classes.

LRA relies upon register classes completely, so targets really have to
express an instruction's exact needs using register classes rather
than ad-hoc constraints like the U constraint sparc is using:

(define_constraint U
 Pseudo-register or hard even-numbered integer register
 (and (match_test TARGET_ARCH32)
  (match_code reg)
  (ior (match_test REGNO (op)  FIRST_PSEUDO_REGISTER)
   (not (match_test reload_in_progress  reg_renumber [REGNO (op)]  
0)))
  (match_test register_ok_for_ldd (op

So this patch tries to rework the semantics of hard register classes,
such that if a hard register is present in the set it is implied that
the rest of the registers in a multi-register group are present as
well.  So we can add a register class called EVEN_REGS and only have
to set the even register bits.

The patch below is enough to get zero regressions for the c/c++
testsuite on 32-bit sparc, but I do know that there are some problems
that need to be resolved still.

For example, I think we need some way to validate a regclass based
upon the mode, something slightly different from HARD_REGNO_MODE_OK.

This would be used for things like the a constraint on x86 so that
on 32-bit a user couldn't try to use the a constraint in an inline
asm for a 64-bit value.

In the compiler itself, this really isn't an issue, because the
machine description would only use register classes for the proper
mode.

I intend to also use this new regclass scheme to represent FPU double
register pairs on sparc as well.

Anyways, any comments would be appreciated, thanks.

diff --git a/gcc/config/sparc/constraints.md b/gcc/config/sparc/constraints.md
index 5dec3dd..cd082ad 100644
--- a/gcc/config/sparc/constraints.md
+++ b/gcc/config/sparc/constraints.md
@@ -44,6 +44,9 @@
 (define_register_constraint h (TARGET_V9  TARGET_V8PLUS ? I64_REGS : 
NO_REGS)
  64-bit global or out register in V8+ mode)
 
+(define_register_constraint U (TARGET_ARCH32 ? EVEN_REGS : NO_REGS)
+ Even-numbered integer register)
+
 ;; Floating-point constant constraints
 
 (define_constraint G
@@ -135,51 +138,6 @@
   (match_code mem)
   (match_test memory_ok_for_ldd (op
 
-;; This awkward register constraint is necessary because it is not
-;; possible to express the must be even numbered register condition
-;; using register classes.  The problem is that membership in a
-;; register class requires that all registers of a multi-regno
-;; register be included in the set.  It is add_to_hard_reg_set
-;; and in_hard_reg_set_p which populate and test regsets with these
-;; semantics.
-;;
-;; So this means that we would have to put both the even and odd
-;; register into the register class, which would not restrict things
-;; at all.
-;;
-;; Using a combination of GENERAL_REGS and HARD_REGNO_MODE_OK is not a
-;; full solution either.  In fact, even though IRA uses the macro
-;; HARD_REGNO_MODE_OK to calculate which registers are prohibited from
-;; use in certain modes, it still can allocate an odd hard register
-;; for DImode values.  This is due to how IRA populates the table
-;; ira_useful_class_mode_regs[][].  It suffers from the same problem
-;; as using a register class to describe this restriction.  Namely, it
-;; sets both the odd and even part of an even register pair in the
-;; regset.  Therefore IRA can and will allocate odd registers for
-;; DImode values on 32-bit.
-;;
-;; There are legitimate cases where DImode values can end up in odd
-;; hard registers, the most notable example is argument passing.
-;;
-;; What saves us is reload and the DImode splitters.  Both are
-;; necessary.  The odd register splitters cannot match if, for
-;; example, we have a non-offsetable MEM.  Reload will notice this
-;; case and reload the address into a single hard register.
-;;
-;; The real downfall of this awkward register constraint is that it does
-;; not evaluate to a true register class like a bonafide use of
-;; define_register_constraint would.  This currently means that we cannot
-;; use LRA on Sparc, since the constraint processing of LRA really depends
-;; upon whether an extra constraint is for registers or not.  It uses
-;; REG_CLASS_FROM_CONSTRAINT, and checks it against NO_REGS.

Re: [PATCH RFC] Finer grained reg classes.

2013-03-19 Thread Ian Lance Taylor
On Tue, Mar 19, 2013 at 8:33 AM, David Miller da...@davemloft.net wrote:

 So this patch tries to rework the semantics of hard register classes,
 such that if a hard register is present in the set it is implied that
 the rest of the registers in a multi-register group are present as
 well.  So we can add a register class called EVEN_REGS and only have
 to set the even register bits.

I haven't really looked at your patch, but I just want to say that I
think this is the right way to go.

Ian


Re: [PATCH RFC] Finer grained reg classes.

2013-03-19 Thread Jeff Law

On 03/19/2013 11:58 AM, Ian Lance Taylor wrote:

On Tue, Mar 19, 2013 at 8:33 AM, David Miller da...@davemloft.net wrote:


So this patch tries to rework the semantics of hard register classes,
such that if a hard register is present in the set it is implied that
the rest of the registers in a multi-register group are present as
well.  So we can add a register class called EVEN_REGS and only have
to set the even register bits.


I haven't really looked at your patch, but I just want to say that I
think this is the right way to go.
Likewise.  I've certainly worked on ports where this would have been 
helpful in the past.


Jeff


Re: [PATCH RFC] Finer grained reg classes.

2013-03-19 Thread Steven Bosscher
On Tue, Mar 19, 2013 at 7:31 PM, Jeff Law wrote:
 On 03/19/2013 11:58 AM, Ian Lance Taylor wrote:

 On Tue, Mar 19, 2013 at 8:33 AM, David Miller wrote:


 So this patch tries to rework the semantics of hard register classes,
 such that if a hard register is present in the set it is implied that
 the rest of the registers in a multi-register group are present as
 well.  So we can add a register class called EVEN_REGS and only have
 to set the even register bits.


 I haven't really looked at your patch, but I just want to say that I
 think this is the right way to go.

 Likewise.  I've certainly worked on ports where this would have been helpful
 in the past.

It could also help simplify existing ports. rs6000 has a few places
where this could be useful (dfp). At least arm
(VFP_REGNO_OK_FOR_DOUBLE), avr, and h8300, too. And ISTR s390 plays
funny subreg tricks to get this right. Finally, it's been discussed on
the gcc@ mailing list for out-of-tree ports a few times in recent
history.

So yes, great if this can be done!

Ciao!
Steven