Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-05-18 Thread Richard Sandiford
Richard Sandiford rdsandif...@googlemail.com writes:
 I think a cleaner way of doing it would be to have helper functions
 that switch in and out of the eliminated form, storing the old form
 in fields of a new structure (either separate from address_info,
 or a local inheritance of it).  We probably also want to have arrays
 of address_infos, one for each operand, so that we don't analyse the
 same address too many times during the same insn.

In the end maintaining the array of address_infos seemed like too much
work.  It was hard to keep it up-to-date with various other changes
that can be made, including swapping commutative operands, to the point
where it wasn't obvious whether it was really an optimisation or not.

Here's a patch that does the first.  Tested on x86_64-linux-gnu.
This time I also compared the assembly output for gcc.dg, g++.dg
and gcc.c-torture at -O2 on:

  arch64-linux-gnu arm-eabi mipsisa64-sde-elf s390x-linux-gnu
  powerpc64-linux-gnu x86_64-linux-gnu

s390x in particular is very good at exposing problems with this code.
(It caught bugs in the aborted attempt to keep an array of address_infos.)

OK to install?

Thanks,
Richard


gcc/
* lra-constraints.c (valid_address_p): Move earlier in file.
(address_eliminator): New structure.
(satisfies_memory_constraint_p): New function.
(satisfies_address_constraint_p): Likewise.
(process_alt_operands, process_address, curr_insn_transform): Use them.

Index: gcc/lra-constraints.c
===
--- gcc/lra-constraints.c   2014-05-17 17:49:19.071639652 +0100
+++ gcc/lra-constraints.c   2014-05-18 20:36:17.499181467 +0100
@@ -317,6 +317,118 @@ in_mem_p (int regno)
   return get_reg_class (regno) == NO_REGS;
 }
 
+/* Return 1 if ADDR is a valid memory address for mode MODE in address
+   space AS, and check that each pseudo has the proper kind of hard
+   reg. */
+static int
+valid_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+rtx addr, addr_space_t as)
+{
+#ifdef GO_IF_LEGITIMATE_ADDRESS
+  lra_assert (ADDR_SPACE_GENERIC_P (as));
+  GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
+  return 0;
+
+ win:
+  return 1;
+#else
+  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
+#endif
+}
+
+namespace {
+  /* Temporarily eliminates registers in an address (for the lifetime of
+ the object).  */
+  class address_eliminator {
+  public:
+address_eliminator (struct address_info *ad);
+~address_eliminator ();
+
+  private:
+struct address_info *m_ad;
+rtx *m_base_loc;
+rtx m_base_reg;
+rtx *m_index_loc;
+rtx m_index_reg;
+  };
+}
+
+address_eliminator::address_eliminator (struct address_info *ad)
+  : m_ad (ad),
+m_base_loc (strip_subreg (ad-base_term)),
+m_base_reg (NULL_RTX),
+m_index_loc (strip_subreg (ad-index_term)),
+m_index_reg (NULL_RTX)
+{
+  if (m_base_loc != NULL)
+{
+  m_base_reg = *m_base_loc;
+  lra_eliminate_reg_if_possible (m_base_loc);
+  if (m_ad-base_term2 != NULL)
+   *m_ad-base_term2 = *m_ad-base_term;
+}
+  if (m_index_loc != NULL)
+{
+  m_index_reg = *m_index_loc;
+  lra_eliminate_reg_if_possible (m_index_loc);
+}
+}
+
+address_eliminator::~address_eliminator ()
+{
+  if (m_base_loc  *m_base_loc != m_base_reg)
+{
+  *m_base_loc = m_base_reg;
+  if (m_ad-base_term2 != NULL)
+   *m_ad-base_term2 = *m_ad-base_term;
+}
+  if (m_index_loc  *m_index_loc != m_index_reg)
+*m_index_loc = m_index_reg;
+}
+
+/* Return true if the eliminated form of AD is a legitimate target address.  */
+static bool
+valid_address_p (struct address_info *ad)
+{
+  address_eliminator eliminator (ad);
+  return valid_address_p (ad-mode, *ad-outer, ad-as);
+}
+
+#ifdef EXTRA_CONSTRAINT_STR
+/* Return true if the eliminated form of memory reference OP satisfies
+   extra address constraint CONSTRAINT.  */
+static bool
+satisfies_memory_constraint_p (rtx op, const char *constraint)
+{
+  struct address_info ad;
+
+  decompose_mem_address (ad, op);
+  address_eliminator eliminator (ad);
+  return EXTRA_CONSTRAINT_STR (op, *constraint, constraint);
+}
+
+/* Return true if the eliminated form of address AD satisfies extra
+   address constraint CONSTRAINT.  */
+static bool
+satisfies_address_constraint_p (struct address_info *ad,
+   const char *constraint)
+{
+  address_eliminator eliminator (ad);
+  return EXTRA_CONSTRAINT_STR (*ad-outer, *constraint, constraint);
+}
+
+/* Return true if the eliminated form of address OP satisfies extra
+   address constraint CONSTRAINT.  */
+static bool
+satisfies_address_constraint_p (rtx op, const char *constraint)
+{
+  struct address_info ad;
+
+  decompose_lea_address (ad, op);
+  return satisfies_address_constraint_p (ad, constraint);
+}
+#endif
+
 /* Initiate equivalences for LRA.  As we keep original equivalences
before any 

RE: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-05-16 Thread Robert Suchanek
I was thinking of something else but it doesn't appear to be good enough
and most likely will follow the suggested way. 

Regards,
Robert

From: Richard Sandiford [rdsandif...@googlemail.com]
Sent: 15 May 2014 22:34
To: Robert Suchanek
Cc: Matthew Fortune; Vladimir Makarov; gcc-patches@gcc.gnu.org; Kyrill Tkachov
Subject: Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

Robert Suchanek robert.sucha...@imgtec.com writes:
 Are you working on the solution to fix the breakage? I'm about
 to look into this and wanted to find out how far we got with this.

You mean the cleaner way I suggested, or something else?
If you want to have a go then feel free.  Otherwise I'll try to get
to it over the weekend.

Richard


RE: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-05-15 Thread Robert Suchanek
Ping.

From: Robert Suchanek
Sent: 14 May 2014 14:24
To: Richard Sandiford; Matthew Fortune
Cc: Vladimir Makarov; gcc-patches@gcc.gnu.org; Kyrill Tkachov
Subject: RE: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

Hi Richard,

Are you working on the solution to fix the breakage? I'm about
to look into this and wanted to find out how far we got with this.

Regards,
Robert

 -Original Message-
 From: Richard Sandiford [mailto:rdsandif...@googlemail.com]
 Sent: 10 May 2014 19:44
 To: Matthew Fortune
 Cc: Vladimir Makarov; Robert Suchanek; gcc-patches@gcc.gnu.org; Kyrill
 Tkachov
 Subject: Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

 Thanks for looking at this.

 Matthew Fortune matthew.fort...@imgtec.com writes:
   Hi all,
   This caused some testsuite failures on arm:
   FAIL: gcc.target/arm/vfp-ldmdbd.c scan-assembler fldmdbd
   FAIL: gcc.target/arm/vfp-ldmdbs.c scan-assembler fldmdbs
   FAIL: gcc.target/arm/vfp-ldmiad.c scan-assembler fldmiad
   FAIL: gcc.target/arm/vfp-ldmias.c scan-assembler fldmias
  
From the vfp-ldmdbd.c test this patch changed the codegen from:
fldmdbdr5!, {d7}
  
   into
subr5, r5, #8
flddd7, [r5]
  
   Which broke the test.
 
  Sorry for the breakage.  I've reverted the patch for now and will send a
  fixed version when I have time.
 
  The problem appears to lie with the new satisfies_memory_constraint_p
  which is passing just the address to valid_address_p but the constraint
  is a memory constraint (which wants the mem to be retained).

 Yeah.

  One option is to re-construct the MEM using the address_info provided
  to valid_address_p. This has mode, address space and whether it was
  actually a MEM to start with so there is enough information.

 We don't want to create garbage rtl though.  The substitution happens
 in-place, so the routine does temporarily turn the original MEM into the
 eliminated form.

 My first reaction after seeing the bug was to pass the operand in as
 another parameter to valid_address_p.  That made the interface a bit
 ridiculous though, so I didn't post it and reverted the original patch
 instead.

 I think a cleaner way of doing it would be to have helper functions
 that switch in and out of the eliminated form, storing the old form
 in fields of a new structure (either separate from address_info,
 or a local inheritance of it).  We probably also want to have arrays
 of address_infos, one for each operand, so that we don't analyse the
 same address too many times during the same insn.

  Another issue noticed while looking at this:
  process_address does not seem to make an attempt to check for
  EXTRA_MEMORY_CONSTRAINT even though it does decompose memory addresses.
  For the lea address case then the address is checked with valid_address_p.
  This seems inconsistent, is it intentional?

 Yeah, I think so.  Memory constraints are different in two main ways:

 (a) it's obvious from the MEM what the mode and address space of the
 access actually are.  legitimate_address_p is all about the most
 general address, so in practice no memory constraint should rely
 on accepting more than legitimate_address_p does.

 (b) it's useful for one pattern to have several alternatives with
 different memory constraints (e.g. ZS, ZT and m in the 32-bit
 MIPS move patterns).  There isn't really anything special about the
 first alternative.

 IMO it'd be good to get rid of this special handling for extra address
 constraints, but I've no idea how easy that would be.

 Thanks,
 Richard


Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-05-15 Thread Richard Sandiford
Robert Suchanek robert.sucha...@imgtec.com writes:
 Are you working on the solution to fix the breakage? I'm about
 to look into this and wanted to find out how far we got with this.

You mean the cleaner way I suggested, or something else?
If you want to have a go then feel free.  Otherwise I'll try to get
to it over the weekend.

Richard


RE: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-05-14 Thread Robert Suchanek
Hi Richard,

Are you working on the solution to fix the breakage? I'm about
to look into this and wanted to find out how far we got with this.

Regards,
Robert

 -Original Message-
 From: Richard Sandiford [mailto:rdsandif...@googlemail.com]
 Sent: 10 May 2014 19:44
 To: Matthew Fortune
 Cc: Vladimir Makarov; Robert Suchanek; gcc-patches@gcc.gnu.org; Kyrill
 Tkachov
 Subject: Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend
 
 Thanks for looking at this.
 
 Matthew Fortune matthew.fort...@imgtec.com writes:
   Hi all,
   This caused some testsuite failures on arm:
   FAIL: gcc.target/arm/vfp-ldmdbd.c scan-assembler fldmdbd
   FAIL: gcc.target/arm/vfp-ldmdbs.c scan-assembler fldmdbs
   FAIL: gcc.target/arm/vfp-ldmiad.c scan-assembler fldmiad
   FAIL: gcc.target/arm/vfp-ldmias.c scan-assembler fldmias
  
From the vfp-ldmdbd.c test this patch changed the codegen from:
fldmdbdr5!, {d7}
  
   into
subr5, r5, #8
flddd7, [r5]
  
   Which broke the test.
 
  Sorry for the breakage.  I've reverted the patch for now and will send a
  fixed version when I have time.
 
  The problem appears to lie with the new satisfies_memory_constraint_p
  which is passing just the address to valid_address_p but the constraint
  is a memory constraint (which wants the mem to be retained).
 
 Yeah.
 
  One option is to re-construct the MEM using the address_info provided
  to valid_address_p. This has mode, address space and whether it was
  actually a MEM to start with so there is enough information.
 
 We don't want to create garbage rtl though.  The substitution happens
 in-place, so the routine does temporarily turn the original MEM into the
 eliminated form.
 
 My first reaction after seeing the bug was to pass the operand in as
 another parameter to valid_address_p.  That made the interface a bit
 ridiculous though, so I didn't post it and reverted the original patch
 instead.
 
 I think a cleaner way of doing it would be to have helper functions
 that switch in and out of the eliminated form, storing the old form
 in fields of a new structure (either separate from address_info,
 or a local inheritance of it).  We probably also want to have arrays
 of address_infos, one for each operand, so that we don't analyse the
 same address too many times during the same insn.
 
  Another issue noticed while looking at this:
  process_address does not seem to make an attempt to check for
  EXTRA_MEMORY_CONSTRAINT even though it does decompose memory addresses.
  For the lea address case then the address is checked with valid_address_p.
  This seems inconsistent, is it intentional?
 
 Yeah, I think so.  Memory constraints are different in two main ways:
 
 (a) it's obvious from the MEM what the mode and address space of the
 access actually are.  legitimate_address_p is all about the most
 general address, so in practice no memory constraint should rely
 on accepting more than legitimate_address_p does.
 
 (b) it's useful for one pattern to have several alternatives with
 different memory constraints (e.g. ZS, ZT and m in the 32-bit
 MIPS move patterns).  There isn't really anything special about the
 first alternative.
 
 IMO it'd be good to get rid of this special handling for extra address
 constraints, but I've no idea how easy that would be.
 
 Thanks,
 Richard


Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-05-10 Thread Richard Sandiford
Thanks for looking at this.

Matthew Fortune matthew.fort...@imgtec.com writes:
  Hi all,
  This caused some testsuite failures on arm:
  FAIL: gcc.target/arm/vfp-ldmdbd.c scan-assembler fldmdbd
  FAIL: gcc.target/arm/vfp-ldmdbs.c scan-assembler fldmdbs
  FAIL: gcc.target/arm/vfp-ldmiad.c scan-assembler fldmiad
  FAIL: gcc.target/arm/vfp-ldmias.c scan-assembler fldmias
 
   From the vfp-ldmdbd.c test this patch changed the codegen from:
   fldmdbdr5!, {d7}
 
  into
   subr5, r5, #8
   flddd7, [r5]
 
  Which broke the test.
 
 Sorry for the breakage.  I've reverted the patch for now and will send a
 fixed version when I have time.

 The problem appears to lie with the new satisfies_memory_constraint_p
 which is passing just the address to valid_address_p but the constraint
 is a memory constraint (which wants the mem to be retained).

Yeah.

 One option is to re-construct the MEM using the address_info provided
 to valid_address_p. This has mode, address space and whether it was
 actually a MEM to start with so there is enough information. 

We don't want to create garbage rtl though.  The substitution happens
in-place, so the routine does temporarily turn the original MEM into the
eliminated form.

My first reaction after seeing the bug was to pass the operand in as
another parameter to valid_address_p.  That made the interface a bit
ridiculous though, so I didn't post it and reverted the original patch
instead.

I think a cleaner way of doing it would be to have helper functions
that switch in and out of the eliminated form, storing the old form
in fields of a new structure (either separate from address_info,
or a local inheritance of it).  We probably also want to have arrays
of address_infos, one for each operand, so that we don't analyse the
same address too many times during the same insn.

 Another issue noticed while looking at this:
 process_address does not seem to make an attempt to check for
 EXTRA_MEMORY_CONSTRAINT even though it does decompose memory addresses.
 For the lea address case then the address is checked with valid_address_p.
 This seems inconsistent, is it intentional?

Yeah, I think so.  Memory constraints are different in two main ways:

(a) it's obvious from the MEM what the mode and address space of the
access actually are.  legitimate_address_p is all about the most
general address, so in practice no memory constraint should rely
on accepting more than legitimate_address_p does.

(b) it's useful for one pattern to have several alternatives with
different memory constraints (e.g. ZS, ZT and m in the 32-bit
MIPS move patterns).  There isn't really anything special about the
first alternative.

IMO it'd be good to get rid of this special handling for extra address
constraints, but I've no idea how easy that would be.

Thanks,
Richard


RE: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-05-09 Thread Matthew Fortune
Richard/Vlad,

Richard Sandiford rdsandif...@googlemail.com writes:
 Kyrill Tkachov kyrylo.tkac...@arm.com writes:
  On 03/05/14 20:21, Richard Sandiford wrote:

...snip...

  Hi all,
  This caused some testsuite failures on arm:
  FAIL: gcc.target/arm/vfp-ldmdbd.c scan-assembler fldmdbd
  FAIL: gcc.target/arm/vfp-ldmdbs.c scan-assembler fldmdbs
  FAIL: gcc.target/arm/vfp-ldmiad.c scan-assembler fldmiad
  FAIL: gcc.target/arm/vfp-ldmias.c scan-assembler fldmias
 
   From the vfp-ldmdbd.c test this patch changed the codegen from:
   fldmdbdr5!, {d7}
 
  into
   subr5, r5, #8
   flddd7, [r5]
 
  Which broke the test.
 
 Sorry for the breakage.  I've reverted the patch for now and will send a
 fixed version when I have time.

The problem appears to lie with the new satisfies_memory_constraint_p
which is passing just the address to valid_address_p but the constraint
is a memory constraint (which wants the mem to be retained).

One option is to re-construct the MEM using the address_info provided
to valid_address_p. This has mode, address space and whether it was
actually a MEM to start with so there is enough information. 

Another issue noticed while looking at this:
process_address does not seem to make an attempt to check for
EXTRA_MEMORY_CONSTRAINT even though it does decompose memory addresses.
For the lea address case then the address is checked with valid_address_p.
This seems inconsistent, is it intentional?

The patch below on top of Richard's addresses both problems and for the
fldmdbd test gets the correct output. I haven't done any more testing
than that though. I suspect there may be a better approach to achieve
the same effect but at least this shows what is wrong with the original
change.

Regards,
Matthew

diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index f59bf55..22bb273 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -348,6 +348,9 @@ valid_address_p (struct address_info *ad, const char 
*constraint = 0)
   rtx saved_index_reg = NULL_RTX;
   rtx *base_term = strip_subreg (ad-base_term);
   rtx *index_term = strip_subreg (ad-index_term);
+#ifdef EXTRA_CONSTRAINT_STR
+  rtx orig_op = NULL_RTX;
+#endif
   if (base_term != NULL)
 {
   saved_base_reg = *base_term;
@@ -360,9 +363,18 @@ valid_address_p (struct address_info *ad, const char 
*constraint = 0)
   saved_index_reg = *index_term;
   lra_eliminate_reg_if_possible (index_term);
 }
+#ifdef EXTRA_CONSTRAINT_STR
+  if (ad-addr_outer_code == MEM)
+{
+  orig_op = gen_rtx_MEM (ad-mode, *ad-outer);
+  MEM_ADDR_SPACE (orig_op) = ad-as;
+}
+  else
+orig_op = *ad-outer;
+#endif
   bool ok_p = (constraint
 #ifdef EXTRA_CONSTRAINT_STR
-  ? EXTRA_CONSTRAINT_STR (*ad-outer, constraint[0], constraint)
+  ? EXTRA_CONSTRAINT_STR (orig_op, constraint[0], constraint)
 #else
   ? false
 #endif
@@ -2865,7 +2877,8 @@ process_address (int nop, rtx *before, rtx *after)
   /* Target hooks sometimes reject extra constraint addresses -- use
  EXTRA_CONSTRAINT_STR for the validation.  */
   if (constraint[0] != 'p'
-   EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint)
+   (EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint)
+ || EXTRA_MEMORY_CONSTRAINT (constraint[0], constraint))
valid_address_p (ad, constraint))
 return change_p;
 #endif


Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-05-06 Thread Kyrill Tkachov

On 03/05/14 20:21, Richard Sandiford wrote:

Vladimir Makarov vmaka...@redhat.com writes:

Not sure how the constraint would/should exclude $sp-based address in
LRA.  In this particular case, a spilled pseudo is changed to memory
giving the following RTL form:

(insn 30 29 31 4 (set (reg:SI 4 $4)
  (and:SI (mem/c:SI (plus:SI (reg/f:SI 78 $frame)
  (const_int 16 [0x10])) [7 %sfp+16 S4 A32])
  (const_int 65535 [0x]))) shell.i:17 161 {*andsi3_mips16}
   (expr_list:REG_DEAD (reg:SI 194 [ D.1469 ])
  (nil)))

The operand 1 during alternative selection is not marked as a bad
operand as it is a memory operand. $frame appears to be fine as it
could be eliminated later to hard register. No reloads are inserted
for the instructions concerned. Unless, $frame should be temporarily
eliminated and then a reload would be inserted?

Yeah, I think the lack of elimination is the problem.  process_address
eliminates $frame temporarily before checking whether the address
is valid, but the places that check EXTRA_CONSTRAINT_STR pass the
original uneliminated address.  So the legitimate_address_p hook sees
the $sp-based address but the W constraint only sees the $frame-based
address (which might or might not be valid, depending on whether $frame
is eliminated to the stack or hard frame pointer).  I think the constraints
should see the eliminated address too.

This patch seems to fix it for me.  Tested on x86_64-linux-gnu.
Vlad, is this OK for trunk?

BTW, we might want to define something like:

#define MODE_BASE_REG_CLASS(MODE) \
(TARGET_MIPS16 \
 ? ((MODE) == SImode || (MODE) == DImode ? M16_SP_REGS : M16_REGS) \
 : GR_REGS)

instead of BASE_REG_CLASS.  It might lead to slightly better code
(or not -- if it doesn't then don't bother :-)).

If this patch is OK then I think the only thing blocking the switch
to LRA is the asm-subreg-1.c failure.  I think it'd be fine to XFAIL
that test on MIPS for now, until there's a consensus about what X means
for asms.


gcc/
* lra-constraints.c (valid_address_p): Move earlier in file.
Add a constraint argument to the address_info version.
(satisfies_memory_constraint_p): New function.
(satisfies_address_constraint_p): Likewise.
(process_alt_operands, curr_insn_transform): Use them.
(process_address): Pass the constraint to valid_address_p when
checking address operands.



Yes, it looks ok for me, Richard.  Thanks on working on this.

I am on vacation till May 4th. If the patch results in problems on other
targets, I hope you revert it.  But to be honest, I believe it is very
safe and don't expect any problems at all.

Thanks Vlad, belatedly committed on that basis.  Like you say I'll revert
it at the first sign of trouble (although it ended up being closer to
your return than originally intended. :-))


Hi all,
This caused some testsuite failures on arm:
FAIL: gcc.target/arm/vfp-ldmdbd.c scan-assembler fldmdbd
FAIL: gcc.target/arm/vfp-ldmdbs.c scan-assembler fldmdbs
FAIL: gcc.target/arm/vfp-ldmiad.c scan-assembler fldmiad
FAIL: gcc.target/arm/vfp-ldmias.c scan-assembler fldmias

From the vfp-ldmdbd.c test this patch changed the codegen from:
fldmdbdr5!, {d7}

into
subr5, r5, #8
flddd7, [r5]

Which broke the test.

Kyrill




Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-05-06 Thread Richard Sandiford
Kyrill Tkachov kyrylo.tkac...@arm.com writes:
 On 03/05/14 20:21, Richard Sandiford wrote:
 Vladimir Makarov vmaka...@redhat.com writes:
 Not sure how the constraint would/should exclude $sp-based address in
 LRA.  In this particular case, a spilled pseudo is changed to memory
 giving the following RTL form:

 (insn 30 29 31 4 (set (reg:SI 4 $4)
   (and:SI (mem/c:SI (plus:SI (reg/f:SI 78 $frame)
   (const_int 16 [0x10])) [7 %sfp+16 S4 A32])
   (const_int 65535 [0x]))) shell.i:17 161 {*andsi3_mips16}
(expr_list:REG_DEAD (reg:SI 194 [ D.1469 ])
   (nil)))

 The operand 1 during alternative selection is not marked as a bad
 operand as it is a memory operand. $frame appears to be fine as it
 could be eliminated later to hard register. No reloads are inserted
 for the instructions concerned. Unless, $frame should be temporarily
 eliminated and then a reload would be inserted?
 Yeah, I think the lack of elimination is the problem.  process_address
 eliminates $frame temporarily before checking whether the address
 is valid, but the places that check EXTRA_CONSTRAINT_STR pass the
 original uneliminated address.  So the legitimate_address_p hook sees
 the $sp-based address but the W constraint only sees the $frame-based
 address (which might or might not be valid, depending on whether $frame
 is eliminated to the stack or hard frame pointer).  I think the constraints
 should see the eliminated address too.

 This patch seems to fix it for me.  Tested on x86_64-linux-gnu.
 Vlad, is this OK for trunk?

 BTW, we might want to define something like:

 #define MODE_BASE_REG_CLASS(MODE) \
 (TARGET_MIPS16 \
  ? ((MODE) == SImode || (MODE) == DImode ? M16_SP_REGS : M16_REGS) \
  : GR_REGS)

 instead of BASE_REG_CLASS.  It might lead to slightly better code
 (or not -- if it doesn't then don't bother :-)).

 If this patch is OK then I think the only thing blocking the switch
 to LRA is the asm-subreg-1.c failure.  I think it'd be fine to XFAIL
 that test on MIPS for now, until there's a consensus about what X means
 for asms.


 gcc/
* lra-constraints.c (valid_address_p): Move earlier in file.
Add a constraint argument to the address_info version.
(satisfies_memory_constraint_p): New function.
(satisfies_address_constraint_p): Likewise.
(process_alt_operands, curr_insn_transform): Use them.
(process_address): Pass the constraint to valid_address_p when
checking address operands.


 Yes, it looks ok for me, Richard.  Thanks on working on this.

 I am on vacation till May 4th. If the patch results in problems on other
 targets, I hope you revert it.  But to be honest, I believe it is very
 safe and don't expect any problems at all.
 Thanks Vlad, belatedly committed on that basis.  Like you say I'll revert
 it at the first sign of trouble (although it ended up being closer to
 your return than originally intended. :-))

 Hi all,
 This caused some testsuite failures on arm:
 FAIL: gcc.target/arm/vfp-ldmdbd.c scan-assembler fldmdbd
 FAIL: gcc.target/arm/vfp-ldmdbs.c scan-assembler fldmdbs
 FAIL: gcc.target/arm/vfp-ldmiad.c scan-assembler fldmiad
 FAIL: gcc.target/arm/vfp-ldmias.c scan-assembler fldmias

  From the vfp-ldmdbd.c test this patch changed the codegen from:
  fldmdbdr5!, {d7}

 into
  subr5, r5, #8
  flddd7, [r5]

 Which broke the test.

Sorry for the breakage.  I've reverted the patch for now and will send a
fixed version when I have time.

Thanks,
Richard



Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-05-03 Thread Richard Sandiford
Vladimir Makarov vmaka...@redhat.com writes:
 Not sure how the constraint would/should exclude $sp-based address in
 LRA.  In this particular case, a spilled pseudo is changed to memory
 giving the following RTL form:

 (insn 30 29 31 4 (set (reg:SI 4 $4)
  (and:SI (mem/c:SI (plus:SI (reg/f:SI 78 $frame)
  (const_int 16 [0x10])) [7 %sfp+16 S4 A32])
  (const_int 65535 [0x]))) shell.i:17 161 {*andsi3_mips16}
   (expr_list:REG_DEAD (reg:SI 194 [ D.1469 ])
  (nil)))

 The operand 1 during alternative selection is not marked as a bad
 operand as it is a memory operand. $frame appears to be fine as it
 could be eliminated later to hard register. No reloads are inserted
 for the instructions concerned. Unless, $frame should be temporarily
 eliminated and then a reload would be inserted?

 Yeah, I think the lack of elimination is the problem.  process_address
 eliminates $frame temporarily before checking whether the address
 is valid, but the places that check EXTRA_CONSTRAINT_STR pass the
 original uneliminated address.  So the legitimate_address_p hook sees
 the $sp-based address but the W constraint only sees the $frame-based
 address (which might or might not be valid, depending on whether $frame
 is eliminated to the stack or hard frame pointer).  I think the constraints
 should see the eliminated address too.

 This patch seems to fix it for me.  Tested on x86_64-linux-gnu.
 Vlad, is this OK for trunk?

 BTW, we might want to define something like:

 #define MODE_BASE_REG_CLASS(MODE) \
(TARGET_MIPS16 \
 ? ((MODE) == SImode || (MODE) == DImode ? M16_SP_REGS : M16_REGS) \
 : GR_REGS)

 instead of BASE_REG_CLASS.  It might lead to slightly better code
 (or not -- if it doesn't then don't bother :-)).

 If this patch is OK then I think the only thing blocking the switch
 to LRA is the asm-subreg-1.c failure.  I think it'd be fine to XFAIL
 that test on MIPS for now, until there's a consensus about what X means
 for asms.


 gcc/
  * lra-constraints.c (valid_address_p): Move earlier in file.
  Add a constraint argument to the address_info version.
  (satisfies_memory_constraint_p): New function.
  (satisfies_address_constraint_p): Likewise.
  (process_alt_operands, curr_insn_transform): Use them.
  (process_address): Pass the constraint to valid_address_p when
  checking address operands.



 Yes, it looks ok for me, Richard.  Thanks on working on this.

 I am on vacation till May 4th. If the patch results in problems on other 
 targets, I hope you revert it.  But to be honest, I believe it is very 
 safe and don't expect any problems at all.

Thanks Vlad, belatedly committed on that basis.  Like you say I'll revert
it at the first sign of trouble (although it ended up being closer to
your return than originally intended. :-))

Richard


RE: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-23 Thread Robert Suchanek
 Yeah, I think the lack of elimination is the problem.  process_address
 eliminates $frame temporarily before checking whether the address
 is valid, but the places that check EXTRA_CONSTRAINT_STR pass the
 original uneliminated address.  So the legitimate_address_p hook sees
 the $sp-based address but the W constraint only sees the $frame-based
 address (which might or might not be valid, depending on whether $frame
 is eliminated to the stack or hard frame pointer).  I think the constraints
 should see the eliminated address too.

That makes sense and explains why it worked when $frame was eliminated
to hard frame pointer but didn't for the stack pointer.

 BTW, we might want to define something like:
 
 #define MODE_BASE_REG_CLASS(MODE) \
   (TARGET_MIPS16 \
? ((MODE) == SImode || (MODE) == DImode ? M16_SP_REGS : M16_REGS) \
: GR_REGS)
 
 instead of BASE_REG_CLASS.  It might lead to slightly better code
 (or not -- if it doesn't then don't bother :-)).

I have already tried it and no visible difference was seen.

 If this patch is OK then I think the only thing blocking the switch
 to LRA is the asm-subreg-1.c failure.  I think it'd be fine to XFAIL
 that test on MIPS for now, until there's a consensus about what X means
 for asms.

The patch worked for me and passed the regression test. Thanks.

If we were going to XFAIL the test then it would apply specifically for -mips16 
-O1.
In any other combination it appears to work. Would that be a stopper?

Below is the revised patch addressing all the comments and changes so far.

Regards,
Robert

2014-03-26  Robert Suchanek  robert.sucha...@imgtec.com

* lra-constraints.c (base_to_reg): New function.
(process_address): Use new function.

* config/mips/constraints.md (d): BASE_REG_CLASS
replaced by TARGET_MIPS16 ? M16_REGS : GR_REGS.
* config/mips/mips.c (mips_regno_mode_ok_for_base_p):
Remove use !strict_p for MIPS16.
(mips_register_priority): New function that implements
the target hook TARGET_REGISTER_PRIORITY.
(mips_spill_class): Likewise for TARGET_SPILL_CLASS
(mips_lra_p): Likewise for TARGET_LRA_P.
* config/mips/mips.h (reg_class): Add M16_SP_REGS and SPILL_REGS
classes.
(REG_CLASS_NAMES): Likewise.
(REG_CLASS_CONTENTS): Likewise.
(BASE_REG_CLASS): Use M16_SP_REGS.
* config/mips/mips.md (*mul_acc_si, *mul_sub_si): Add alternative
tuned for LRA. New set attribute to enable alternatives
depending on the register allocator used.
(*lea64): Disable pattern for MIPS16.
* config/mips/mips.opt
(mlra): New option

diff --git gcc/config/mips/constraints.md gcc/config/mips/constraints.md
index f6834fd..fa33c30 100644
--- gcc/config/mips/constraints.md
+++ gcc/config/mips/constraints.md
@@ -19,7 +19,7 @@
 
 ;; Register constraints
 
-(define_register_constraint d BASE_REG_CLASS
+(define_register_constraint d TARGET_MIPS16 ? M16_REGS : GR_REGS
   An address register.  This is equivalent to @code{r} unless
generating MIPS16 code.)
 
diff --git gcc/config/mips/mips.c gcc/config/mips/mips.c
index 45256e9..81b6c26 100644
--- gcc/config/mips/mips.c
+++ gcc/config/mips/mips.c
@@ -655,7 +655,7 @@ const enum reg_class 
mips_regno_to_class[FIRST_PSEUDO_REGISTER] = {
   M16_REGS,M16_STORE_REGS,  LEA_REGS,LEA_REGS,
   LEA_REGS,LEA_REGS,LEA_REGS,LEA_REGS,
   T_REG,   PIC_FN_ADDR_REG, LEA_REGS,LEA_REGS,
-  LEA_REGS,LEA_REGS,LEA_REGS,LEA_REGS,
+  LEA_REGS,M16_SP_REGS, LEA_REGS,LEA_REGS,
 
   FP_REGS, FP_REGS,FP_REGS,FP_REGS,
   FP_REGS, FP_REGS,FP_REGS,FP_REGS,
@@ -2241,22 +2241,9 @@ mips_regno_mode_ok_for_base_p (int regno, enum 
machine_mode mode,
 return true;
 
   /* In MIPS16 mode, the stack pointer can only address word and doubleword
- values, nothing smaller.  There are two problems here:
-
-   (a) Instantiating virtual registers can introduce new uses of the
-  stack pointer.  If these virtual registers are valid addresses,
-  the stack pointer should be too.
-
-   (b) Most uses of the stack pointer are not made explicit until
-  FRAME_POINTER_REGNUM and ARG_POINTER_REGNUM have been eliminated.
-  We don't know until that stage whether we'll be eliminating to the
-  stack pointer (which needs the restriction) or the hard frame
-  pointer (which doesn't).
-
- All in all, it seems more consistent to only enforce this restriction
- during and after reload.  */
+ values, nothing smaller.  */
   if (TARGET_MIPS16  regno == STACK_POINTER_REGNUM)
-return !strict_p || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
+return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
 
   return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
 }
@@ -12115,6 +12102,18 @@ 

Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-23 Thread Richard Sandiford
Robert Suchanek robert.sucha...@imgtec.com writes:
 If we were going to XFAIL the test then it would apply specifically
 for -mips16 -O1.  In any other combination it appears to work. Would
 that be a stopper?

Hmm, in that case maybe we should just leave it failing.  The alternative
would be to skip the test altogther for MIPS, with a PR referencing it,
but that seems a bit over-the-top.

 2014-03-26  Robert Suchanek  robert.sucha...@imgtec.com

   * lra-constraints.c (base_to_reg): New function.
   (process_address): Use new function.

   * config/mips/constraints.md (d): BASE_REG_CLASS
   replaced by TARGET_MIPS16 ? M16_REGS : GR_REGS.
   * config/mips/mips.c (mips_regno_mode_ok_for_base_p):
   Remove use !strict_p for MIPS16.
   (mips_register_priority): New function that implements
   the target hook TARGET_REGISTER_PRIORITY.
   (mips_spill_class): Likewise for TARGET_SPILL_CLASS
   (mips_lra_p): Likewise for TARGET_LRA_P.
   * config/mips/mips.h (reg_class): Add M16_SP_REGS and SPILL_REGS
   classes.
   (REG_CLASS_NAMES): Likewise.
   (REG_CLASS_CONTENTS): Likewise.
   (BASE_REG_CLASS): Use M16_SP_REGS.
   * config/mips/mips.md (*mul_acc_si, *mul_sub_si): Add alternative
   tuned for LRA. New set attribute to enable alternatives
   depending on the register allocator used.
   (*lea64): Disable pattern for MIPS16.
   * config/mips/mips.opt
   (mlra): New option

Looks good.

 @@ -12115,6 +12102,18 @@ mips_register_move_cost (enum machine_mode mode,
return 0;
  }
  
 +/* Return a register priority for hard reg REGNO.  */
 +
 +static int
 +mips_register_priority (int hard_regno)
 +{
 +  /* Treat MIPS16 registers with higher priority than other regs.  */
 +  if (TARGET_MIPS16
 +   TEST_HARD_REG_BIT (reg_class_contents[M16_REGS], hard_regno))
 +return 1;
 +  return 0;
 +}
 +
  /* Implement TARGET_MEMORY_MOVE_COST.  */
  
  static int
 @@ -18897,6 +18896,21 @@ mips_atomic_assign_expand_fenv (tree *hold, tree 
 *clear, tree *update)
*update = build2 (COMPOUND_EXPR, void_type_node, *update,
   atomic_feraiseexcept_call);
  }
 +
 +static reg_class_t
 +mips_spill_class (reg_class_t rclass ATTRIBUTE_UNUSED,
 +   enum machine_mode mode ATTRIBUTE_UNUSED)
 +{
 +  if (TARGET_MIPS16)
 +return SPILL_REGS;
 +  return NO_REGS;
 +}
 +
 +static bool
 +mips_lra_p (void)
 +{
 +  return mips_lra_flag;
 +}
  
  /* Initialize the GCC target structure.  */
  #undef TARGET_ASM_ALIGNED_HI_OP

Please use comments of the form:

  /* Implement TARGET_FOO.  */

above all three functions (instead of the current one in the case of
mips_register_priority), just so that it's painfully obvious that
these are target hooks.

OK for the MIPS part with that change, thanks.

Out of interest, do you see any difference if you include $sp in SPILL_REGS?
That obviously doesn't make much conceptual sense, but it would give a
cleaner class hierarchy.

Richard


RE: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-23 Thread Robert Suchanek
 Hmm, in that case maybe we should just leave it failing.  The alternative
 would be to skip the test altogther for MIPS, with a PR referencing it,
 but that seems a bit over-the-top.

I'd leave it as it is for now until the consensus regarding the 'X' constraint
is reached.
 
 Please use comments of the form:
 
   /* Implement TARGET_FOO.  */
 
 above all three functions (instead of the current one in the case of
 mips_register_priority), just so that it's painfully obvious that
 these are target hooks.

Modified as requested and attached the patch below. I tried to keep 
to the conventions but apparently I seem to overlook certain things.
I'll remember this part now :).

 Out of interest, do you see any difference if you include $sp in SPILL_REGS?
 That obviously doesn't make much conceptual sense, but it would give a
 cleaner class hierarchy.

Including $sp does not make any difference, exactly the same code size.
Although I haven't thoroughly tested it, I limited the check to -Os.

Regards,
Robert

2014-03-26  Robert Suchanek  robert.sucha...@imgtec.com

* lra-constraints.c (base_to_reg): New function.
(process_address): Use new function.

* config/mips/constraints.md (d): BASE_REG_CLASS
replaced by TARGET_MIPS16 ? M16_REGS : GR_REGS.
* config/mips/mips.c (mips_regno_mode_ok_for_base_p):
Remove use !strict_p for MIPS16.
(mips_register_priority): New function that implements
the target hook TARGET_REGISTER_PRIORITY.
(mips_spill_class): Likewise for TARGET_SPILL_CLASS
(mips_lra_p): Likewise for TARGET_LRA_P.
* config/mips/mips.h (reg_class): Add M16_SP_REGS and SPILL_REGS
classes.
(REG_CLASS_NAMES): Likewise.
(REG_CLASS_CONTENTS): Likewise.
(BASE_REG_CLASS): Use M16_SP_REGS.
* config/mips/mips.md (*mul_acc_si, *mul_sub_si): Add alternative
tuned for LRA. New set attribute to enable alternatives
depending on the register allocator used.
(*lea64): Disable pattern for MIPS16.
* config/mips/mips.opt
(mlra): New option

diff --git gcc/config/mips/constraints.md gcc/config/mips/constraints.md
index f6834fd..fa33c30 100644
--- gcc/config/mips/constraints.md
+++ gcc/config/mips/constraints.md
@@ -19,7 +19,7 @@
 
 ;; Register constraints
 
-(define_register_constraint d BASE_REG_CLASS
+(define_register_constraint d TARGET_MIPS16 ? M16_REGS : GR_REGS
   An address register.  This is equivalent to @code{r} unless
generating MIPS16 code.)
 
diff --git gcc/config/mips/mips.c gcc/config/mips/mips.c
index 45256e9..f8d90b2 100644
--- gcc/config/mips/mips.c
+++ gcc/config/mips/mips.c
@@ -655,7 +655,7 @@ const enum reg_class 
mips_regno_to_class[FIRST_PSEUDO_REGISTER] = {
   M16_REGS,M16_STORE_REGS,  LEA_REGS,LEA_REGS,
   LEA_REGS,LEA_REGS,LEA_REGS,LEA_REGS,
   T_REG,   PIC_FN_ADDR_REG, LEA_REGS,LEA_REGS,
-  LEA_REGS,LEA_REGS,LEA_REGS,LEA_REGS,
+  LEA_REGS,M16_SP_REGS, LEA_REGS,LEA_REGS,
 
   FP_REGS, FP_REGS,FP_REGS,FP_REGS,
   FP_REGS, FP_REGS,FP_REGS,FP_REGS,
@@ -2241,22 +2241,9 @@ mips_regno_mode_ok_for_base_p (int regno, enum 
machine_mode mode,
 return true;
 
   /* In MIPS16 mode, the stack pointer can only address word and doubleword
- values, nothing smaller.  There are two problems here:
-
-   (a) Instantiating virtual registers can introduce new uses of the
-  stack pointer.  If these virtual registers are valid addresses,
-  the stack pointer should be too.
-
-   (b) Most uses of the stack pointer are not made explicit until
-  FRAME_POINTER_REGNUM and ARG_POINTER_REGNUM have been eliminated.
-  We don't know until that stage whether we'll be eliminating to the
-  stack pointer (which needs the restriction) or the hard frame
-  pointer (which doesn't).
-
- All in all, it seems more consistent to only enforce this restriction
- during and after reload.  */
+ values, nothing smaller.  */
   if (TARGET_MIPS16  regno == STACK_POINTER_REGNUM)
-return !strict_p || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
+return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
 
   return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
 }
@@ -12115,6 +12102,18 @@ mips_register_move_cost (enum machine_mode mode,
   return 0;
 }
 
+/* Implement TARGET_REGISTER_PRIORITY.  */
+
+static int
+mips_register_priority (int hard_regno)
+{
+  /* Treat MIPS16 registers with higher priority than other regs.  */
+  if (TARGET_MIPS16
+   TEST_HARD_REG_BIT (reg_class_contents[M16_REGS], hard_regno))
+return 1;
+  return 0;
+}
+
 /* Implement TARGET_MEMORY_MOVE_COST.  */
 
 static int
@@ -18897,6 +18896,25 @@ mips_atomic_assign_expand_fenv (tree *hold, tree 
*clear, tree *update)
   *update = build2 (COMPOUND_EXPR, 

Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-23 Thread Vladimir Makarov

On 2014-04-21, 8:23 AM, Richard Sandiford wrote:

Robert Suchanek robert.sucha...@imgtec.com writes:

Did you see the failures even after your mips_regno_mode_ok_for_base_p
change?  LRA should know how to reload a W address.


Yes but I realize there is more. It fails because $sp is now included
in BASE_REG_CLASS and W is based on it. However, I suppose that
it would be too eager to say it is wrong and likely there is
something missing
in LRA if we want to keep all alternatives. Currently there is no check
if a reloaded operand has a valid address, use of $sp in lbu/lhu cases.
Even if we added extra checks we are less likely to benefit as we need
to reload the base into register.


Not sure what you mean, sorry.  W exists specifically to exclude
$sp-based and $pc-based addresses.  LRA AFAIK should already be able
to reload addresses that are valid in the TARGET_LEGITIMATE_ADDRESS_P
sense but which do not match the constraints for a particular insn.

Can you remember one of the tests that fails?


I couldn't trigger the problem with the original testcase but found
another one that reveals it. The following needs to compiled with
-mips32r2 -mips16 -Os:

struct { int addr; } c;
struct command { int args[1]; };
unsigned short a;

fn1 (struct command *p1)
{
 unsigned short d;
 d = fn2 ();
 a = p1-args[0];
 fn3 (a);
 if (c.addr)
 {
 fn4 (p1-args[0]);
 return;
 }
 (c)-addr = fn5 ();
 fn6 (d);
}


Thanks.


Not sure how the constraint would/should exclude $sp-based address in
LRA.  In this particular case, a spilled pseudo is changed to memory
giving the following RTL form:

(insn 30 29 31 4 (set (reg:SI 4 $4)
 (and:SI (mem/c:SI (plus:SI (reg/f:SI 78 $frame)
 (const_int 16 [0x10])) [7 %sfp+16 S4 A32])
 (const_int 65535 [0x]))) shell.i:17 161 {*andsi3_mips16}
  (expr_list:REG_DEAD (reg:SI 194 [ D.1469 ])
 (nil)))

The operand 1 during alternative selection is not marked as a bad
operand as it is a memory operand. $frame appears to be fine as it
could be eliminated later to hard register. No reloads are inserted
for the instructions concerned. Unless, $frame should be temporarily
eliminated and then a reload would be inserted?


Yeah, I think the lack of elimination is the problem.  process_address
eliminates $frame temporarily before checking whether the address
is valid, but the places that check EXTRA_CONSTRAINT_STR pass the
original uneliminated address.  So the legitimate_address_p hook sees
the $sp-based address but the W constraint only sees the $frame-based
address (which might or might not be valid, depending on whether $frame
is eliminated to the stack or hard frame pointer).  I think the constraints
should see the eliminated address too.

This patch seems to fix it for me.  Tested on x86_64-linux-gnu.
Vlad, is this OK for trunk?

BTW, we might want to define something like:

#define MODE_BASE_REG_CLASS(MODE) \
   (TARGET_MIPS16 \
? ((MODE) == SImode || (MODE) == DImode ? M16_SP_REGS : M16_REGS) \
: GR_REGS)

instead of BASE_REG_CLASS.  It might lead to slightly better code
(or not -- if it doesn't then don't bother :-)).

If this patch is OK then I think the only thing blocking the switch
to LRA is the asm-subreg-1.c failure.  I think it'd be fine to XFAIL
that test on MIPS for now, until there's a consensus about what X means
for asms.


gcc/
* lra-constraints.c (valid_address_p): Move earlier in file.
Add a constraint argument to the address_info version.
(satisfies_memory_constraint_p): New function.
(satisfies_address_constraint_p): Likewise.
(process_alt_operands, curr_insn_transform): Use them.
(process_address): Pass the constraint to valid_address_p when
checking address operands.




Yes, it looks ok for me, Richard.  Thanks on working on this.

I am on vacation till May 4th. If the patch results in problems on other 
targets, I hope you revert it.  But to be honest, I believe it is very 
safe and don't expect any problems at all.


Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-21 Thread Richard Sandiford
Robert Suchanek robert.sucha...@imgtec.com writes:
  Did you see the failures even after your mips_regno_mode_ok_for_base_p
  change?  LRA should know how to reload a W address.
 
  Yes but I realize there is more. It fails because $sp is now included
  in BASE_REG_CLASS and W is based on it. However, I suppose that 
  it would be too eager to say it is wrong and likely there is
  something missing
  in LRA if we want to keep all alternatives. Currently there is no check
  if a reloaded operand has a valid address, use of $sp in lbu/lhu cases.
  Even if we added extra checks we are less likely to benefit as we need
  to reload the base into register.

 Not sure what you mean, sorry.  W exists specifically to exclude
 $sp-based and $pc-based addresses.  LRA AFAIK should already be able
 to reload addresses that are valid in the TARGET_LEGITIMATE_ADDRESS_P
 sense but which do not match the constraints for a particular insn.

 Can you remember one of the tests that fails?

 I couldn't trigger the problem with the original testcase but found
 another one that reveals it. The following needs to compiled with
 -mips32r2 -mips16 -Os:

 struct { int addr; } c;
 struct command { int args[1]; };
 unsigned short a;

 fn1 (struct command *p1)
 {
 unsigned short d;
 d = fn2 ();
 a = p1-args[0];
 fn3 (a);
 if (c.addr)
 {
 fn4 (p1-args[0]);
 return;
 }
 (c)-addr = fn5 ();
 fn6 (d);
 }

Thanks.

 Not sure how the constraint would/should exclude $sp-based address in
 LRA.  In this particular case, a spilled pseudo is changed to memory
 giving the following RTL form:

 (insn 30 29 31 4 (set (reg:SI 4 $4)
 (and:SI (mem/c:SI (plus:SI (reg/f:SI 78 $frame)
 (const_int 16 [0x10])) [7 %sfp+16 S4 A32])
 (const_int 65535 [0x]))) shell.i:17 161 {*andsi3_mips16}
  (expr_list:REG_DEAD (reg:SI 194 [ D.1469 ])
 (nil)))

 The operand 1 during alternative selection is not marked as a bad
 operand as it is a memory operand. $frame appears to be fine as it
 could be eliminated later to hard register. No reloads are inserted
 for the instructions concerned. Unless, $frame should be temporarily
 eliminated and then a reload would be inserted?

Yeah, I think the lack of elimination is the problem.  process_address
eliminates $frame temporarily before checking whether the address
is valid, but the places that check EXTRA_CONSTRAINT_STR pass the
original uneliminated address.  So the legitimate_address_p hook sees
the $sp-based address but the W constraint only sees the $frame-based
address (which might or might not be valid, depending on whether $frame
is eliminated to the stack or hard frame pointer).  I think the constraints
should see the eliminated address too.

This patch seems to fix it for me.  Tested on x86_64-linux-gnu.
Vlad, is this OK for trunk?

BTW, we might want to define something like:

#define MODE_BASE_REG_CLASS(MODE) \
  (TARGET_MIPS16 \
   ? ((MODE) == SImode || (MODE) == DImode ? M16_SP_REGS : M16_REGS) \
   : GR_REGS)

instead of BASE_REG_CLASS.  It might lead to slightly better code
(or not -- if it doesn't then don't bother :-)).

If this patch is OK then I think the only thing blocking the switch
to LRA is the asm-subreg-1.c failure.  I think it'd be fine to XFAIL
that test on MIPS for now, until there's a consensus about what X means
for asms.

Thanks,
Richard

gcc/
* lra-constraints.c (valid_address_p): Move earlier in file.
Add a constraint argument to the address_info version.
(satisfies_memory_constraint_p): New function.
(satisfies_address_constraint_p): Likewise.
(process_alt_operands, curr_insn_transform): Use them.
(process_address): Pass the constraint to valid_address_p when
checking address operands.

Index: gcc/lra-constraints.c
===
--- gcc/lra-constraints.c   2014-04-21 10:36:06.715026374 +0100
+++ gcc/lra-constraints.c   2014-04-21 13:18:46.228298176 +0100
@@ -317,6 +317,94 @@ in_mem_p (int regno)
   return get_reg_class (regno) == NO_REGS;
 }
 
+/* Return 1 if ADDR is a valid memory address for mode MODE in address
+   space AS, and check that each pseudo has the proper kind of hard
+   reg. */
+static int
+valid_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+rtx addr, addr_space_t as)
+{
+#ifdef GO_IF_LEGITIMATE_ADDRESS
+  lra_assert (ADDR_SPACE_GENERIC_P (as));
+  GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
+  return 0;
+
+ win:
+  return 1;
+#else
+  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
+#endif
+}
+
+/* Return whether address AD is valid.  If CONSTRAINT is null,
+   check for general addresses, otherwise check the extra constraint
+   CONSTRAINT.  */
+static bool
+valid_address_p (struct address_info *ad, const char *constraint = 0)
+{
+  /* Some ports do not check displacements for eliminable registers,
+

RE: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-16 Thread Robert Suchanek
  Did you see the failures even after your mips_regno_mode_ok_for_base_p
  change?  LRA should know how to reload a W address.
 
  Yes but I realize there is more. It fails because $sp is now included
  in BASE_REG_CLASS and W is based on it. However, I suppose that 
  it would be too eager to say it is wrong and likely there is something 
  missing 
  in LRA if we want to keep all alternatives. Currently there is no check
  if a reloaded operand has a valid address, use of $sp in lbu/lhu cases.
  Even if we added extra checks we are less likely to benefit as we need
  to reload the base into register.

 Not sure what you mean, sorry.  W exists specifically to exclude
 $sp-based and $pc-based addresses.  LRA AFAIK should already be able
 to reload addresses that are valid in the TARGET_LEGITIMATE_ADDRESS_P
 sense but which do not match the constraints for a particular insn.

 Can you remember one of the tests that fails?

I couldn't trigger the problem with the original testcase but found another
one that reveals it. The following needs to compiled with -mips32r2 -mips16 -Os:

struct { int addr; } c;
struct command { int args[1]; };
unsigned short a;

fn1 (struct command *p1)
{
unsigned short d;
d = fn2 ();
a = p1-args[0];
fn3 (a);
if (c.addr)
{
fn4 (p1-args[0]);
return;
}
(c)-addr = fn5 ();
fn6 (d);
}

Not sure how the constraint would/should exclude $sp-based address in LRA.
In this particular case, a spilled pseudo is changed to memory giving the 
following RTL form:

(insn 30 29 31 4 (set (reg:SI 4 $4)
(and:SI (mem/c:SI (plus:SI (reg/f:SI 78 $frame)
(const_int 16 [0x10])) [7 %sfp+16 S4 A32])
(const_int 65535 [0x]))) shell.i:17 161 {*andsi3_mips16}
 (expr_list:REG_DEAD (reg:SI 194 [ D.1469 ])
(nil)))

The operand 1 during alternative selection is not marked as a bad operand as it 
is a memory
operand. $frame appears to be fine as it could be eliminated later to hard 
register. No reloads
are inserted for the instructions concerned. Unless, $frame should be 
temporarily eliminated
and then a reload would be inserted?

Regards,
Robert
 



Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-15 Thread Richard Sandiford
Robert Suchanek robert.sucha...@imgtec.com writes:
 Hmm, marking them fixed was supposed to be a temporary reload-only thing,
 until the move to LRA.  It should never be worse to spill to these GPRs
 over spilling to the stack, if the value isn't live across a call.

 I would say this also affects IRA/LRA integration. I found that it is more
 profitable to hide registers (MIPS16 only) in IRA to encourage spilling to
 memory. Otherwise $8-$15 would be treated like any other registers and LRA
 would inserts reloads to move in/out values of these registers. My assumption 
 is
 that if we could hide some of the registers in IRA but enable them in LRA
 then all registers in SPILL_REGS would be available keeping reasonable code
 size. Another way would be to increase the cost of moving values between 
 M16_REGS and GR_REGS but it was already mentioned, and is true that there 
 should be no difference of costs and it feels like a hack to make things work.

OK.

This definitely sounds like it ought to be made to work, with some mixture
of target and generic changes.  But if it doesn't work out of the box
then let's leave that for future work.

 Did you see the failures even after your mips_regno_mode_ok_for_base_p
 change?  LRA should know how to reload a W address.

 Yes but I realize there is more. It fails because $sp is now included
 in BASE_REG_CLASS and W is based on it. However, I suppose that 
 it would be too eager to say it is wrong and likely there is something 
 missing 
 in LRA if we want to keep all alternatives. Currently there is no check
 if a reloaded operand has a valid address, use of $sp in lbu/lhu cases.
 Even if we added extra checks we are less likely to benefit as we need
 to reload the base into register.

Not sure what you mean, sorry.  W exists specifically to exclude
$sp-based and $pc-based addresses.  LRA AFAIK should already be able
to reload addresses that are valid in the TARGET_LEGITIMATE_ADDRESS_P
sense but which do not match the constraints for a particular insn.

Can you remember one of the tests that fails?

 Even that might be too loose, since invalid scales will need to be reloaded
 as a multiplication or shift, and there's no guarantee that the target
 can do that without clobbering the flags.  So maybe we should do something
 like the patch below.

 Alternatively we could stick to the decompose_mem_address-based check
 above and teach LRA to keep invalid addresses for 'X'.  The problem then
 is that we might ICE while printing the operand.

 Tightening validity for 'X' appears to be reasonable. Will you commit
 this patch?

OK, just submitted separately.

Thanks,
Richard


RE: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-14 Thread Robert Suchanek
 So yeah, I agree this is right after all, sorry.  Let's delete the
 comment starting at There are two problems here: at the same time.

Ok.

 mips_regno_to_class should then map $sp to the new class, since it's now
 the smallest containing class.  (We really should set that up automatically
 one day...)

Indeed, it is easy to overlook it.

 How about M16_SP_REGS, to match M16_T_REGS?
 
 Also, the BASE_REG_CLASS/ADDR_REG_CLASS distinction isn't all that
 obvious from the names.  ADDR_REG_CLASS is only needed for the d
 constraint so maybe we could just use TARGET_MIPS16 ? M16_REGS : GR_REGS
 directly for now.

Fair enough. I'll remove ADDR_REG_CLASS.

 I can imagine including all M16_REGS makes sense, but it seems odd to
 drop the 2 temporaries.  Does 0x0303fffc have the same problem?

It's a midway between 0x0003fffc and 0x0300fffc. I think 0x0303fffc will be
a good trade-off. The difference between 0x0303fffc and others is about 
~600 bytes in CSiBE which is less than 0.01% of code size change.

 Hmm, marking them fixed was supposed to be a temporary reload-only thing,
 until the move to LRA.  It should never be worse to spill to these GPRs
 over spilling to the stack, if the value isn't live across a call.

I would say this also affects IRA/LRA integration. I found that it is more
profitable to hide registers (MIPS16 only) in IRA to encourage spilling to
memory. Otherwise $8-$15 would be treated like any other registers and LRA
would inserts reloads to move in/out values of these registers. My assumption is
that if we could hide some of the registers in IRA but enable them in LRA
then all registers in SPILL_REGS would be available keeping reasonable code
size. Another way would be to increase the cost of moving values between 
M16_REGS and GR_REGS but it was already mentioned, and is true that there 
should be no difference of costs and it feels like a hack to make things work.

 Did you see the failures even after your mips_regno_mode_ok_for_base_p
 change?  LRA should know how to reload a W address.

Yes but I realize there is more. It fails because $sp is now included
in BASE_REG_CLASS and W is based on it. However, I suppose that 
it would be too eager to say it is wrong and likely there is something missing 
in LRA if we want to keep all alternatives. Currently there is no check
if a reloaded operand has a valid address, use of $sp in lbu/lhu cases.
Even if we added extra checks we are less likely to benefit as we need
to reload the base into register.

 Even that might be too loose, since invalid scales will need to be reloaded
 as a multiplication or shift, and there's no guarantee that the target
 can do that without clobbering the flags.  So maybe we should do something
 like the patch below.

 Alternatively we could stick to the decompose_mem_address-based check
 above and teach LRA to keep invalid addresses for 'X'.  The problem then
 is that we might ICE while printing the operand.

Tightening validity for 'X' appears to be reasonable. Will you commit this 
patch?

Regards,
Robert


Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-10 Thread Richard Sandiford
Richard Sandiford rdsandif...@googlemail.com writes:
 Robert Suchanek robert.sucha...@imgtec.com writes:
 I'm not particularly happy with this either. This was an attempt to fix an 
 ICE for 
 the following RTL (gcc.dg/torture/asm-subreg-1.c compiled with -mips32r2 
 -mips16 -O1):

 (insn 9 8 0 2 (asm_operands/v () () 0 [
 (mem/v/j/c:HI (lo_sum:SI (const:SI (unspec:SI [
 (const_int 0 [0])
 ] UNSPEC_GP))
 (symbol_ref:SI (_const_32) [flags 0x6]  var_decl 
 0x7f50acd17558 _const_32)) [0 _const_32+0 S2 A32])]
  [(asm_input:HI (X) (null):0)]
  [] asm-subreg-1.c:13) asm-subreg-1.c:13 -1 (nil))

 Any suggestions to handle this case?

 Thanks for the pointer.  I think this shows a more fundamental problem
 with the handling of X constraints.  With something like:

 void
 foo (int **x, int y, int z)
 {
   int *ptr = *x + y * z / 11;
   __asm__ __volatile__ ( : : X (*ptr));
 }

 the entire expression gets treated as a MEM address, which neither
 reload nor LRA can handle.  And with something like that, it isn't
 obvious what class all the registers in the address should have.
 With a sufficiently-complicated expression you could run out of registers.

 So perhaps we should limit the propagation to things that
 decompose_mem_address can handle.

Even that might be too loose, since invalid scales will need to be reloaded
as a multiplication or shift, and there's no guarantee that the target
can do that without clobbering the flags.  So maybe we should do something
like the patch below.

Alternatively we could stick to the decompose_mem_address-based check
above and teach LRA to keep invalid addresses for 'X'.  The problem then
is that we might ICE while printing the operand.

Thanks,
Richard


gcc/
* recog.c (asm_operand_ok): Tighten MEM validity for 'X'.

gcc/testsuite/
* gcc.dg/torture/asm-x-constraint-1.c: New test.

Index: gcc/recog.c
===
--- gcc/recog.c 2014-04-10 21:18:02.778009424 +0100
+++ gcc/recog.c 2014-04-10 21:18:02.996011570 +0100
@@ -1840,7 +1840,11 @@ asm_operand_ok (rtx op, const char *cons
  break;
 
case 'X':
- result = 1;
+ /* Still enforce memory requirements for non-constant addresses,
+since we can't reload MEMs with completely arbitrary addresses.  */
+ result = (!MEM_P (op)
+   || CONSTANT_P (XEXP (op, 0))
+   || memory_operand (op, VOIDmode));
  break;
 
case 'g':
Index: gcc/testsuite/gcc.dg/torture/asm-x-constraint-1.c
===
--- /dev/null   2014-04-10 19:40:00.640011981 +0100
+++ gcc/testsuite/gcc.dg/torture/asm-x-constraint-1.c   2014-04-10 
21:19:05.405623027 +0100
@@ -0,0 +1,6 @@
+void
+foo (int **x, int y, int z)
+{
+  int *ptr = *x + y * z / 11;
+  __asm__ __volatile__ (foo %0 : : X (*ptr));
+}


RE: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-09 Thread Robert Suchanek
 FYI, all other targets that have LRA optionally selectable or deselectable
 use -mno-lra for this (even when -mlra is the default), it would be better
 for consistency not to invent new switch names for that.

Agreed.

 -return !strict_p || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) 
 == 8;
 +return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
  
return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
  }
 Not sure about this one.  We would need to update the comment that
 explains why !strict_p is there, but AFAIK reason (1) would still apply.

 Was this needed for correctness or because it gave better code?

!strict_p has been removed because of correctness issue. When LRA validates 
memory addresses pseudos are temporarily eliminated to hard registers (if 
possible)
but the target hook is always called as non-strict. This only affects MIPS16 
instructions with
not directly accessible $sp. The strict variant, as I understand, was used in 
the reload
pass to indicate if a pseudo-register has been allocated a hard register. 
Unless LRA
should be setting the strict/non-strict depending on whether a temporal 
elimination
to hard reg was successful or there is something else that I missed? 

 Easier as:

  if (TARGET_MIPS16
   TEST_HARD_REG_BIT (reg_class_contents[M16_REGS], hard_regno))
return 1;
  return 0;

Indeed. 

 +  M16F_REGS,/* mips16 + frame */

 Constraints are supposed to be operating on real registers, after
 elimination, so it seems odd to include a fake register.  What went
 wrong with just M16_REGS?

Only the stack pointer has been added to M16_REGS. A number of patterns need to 
accept
it otherwise LRA inserts a lot of reloads and the code size goes up by about 
10%. 
The change does have also a positive effect on reload but marginally.
frame meant to indicate inclusion of both the stack and hard frame pointers 
in the class
but perhaps I should name it differently to avoid confusion.

 +  SPILL_REGS,   /* All but $sp and call preserved regs 
 are in here */
...
 +  { 0x0003fffc, 0x, 0x, 0x, 0x, 0x 
 },   /* SPILL_REGS */\

 These two don't seem to match.  I think literally it would be 0x0300fffc,
 but maybe you had to make SPILL_REGS a superset of M16_REGs?

I initially used 0x0300fffc but did some experiments and it turned out that 
0x0003fffc (with $16, $17 regs)
gives slightly better code. I haven't updated the comment though. There is yet 
more to do 
and need to return to another thread with MIPS16 at some point as I found some 
limitations
of IRA/LRA to generate better code. $8-$15 are currently inaccessible as 
temporary storage
because these registers are marked as fixed (when optimizing for size) but 
leaving them
as fixed are better for the code size. I don't expect a big gain by using hard 
registers
for spilling but it more likely to improve the performance.

 +/* Add costs to hard registers based on frequency. This helps to negate
 +   some of the reduced cost associated with argument registers which 
 +   unfairly promotes their use and increases register pressure */
 +#define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(REGNO)   \
 +  (TARGET_MIPS16  optimize_size   \
 +   ? ((REGNO) = 4  (REGNO) = 7 ? 2 : 0) : 0)

 So we would be trying to use, say, $4 for the first incoming argument
 even after it had been spilled?  Hmm.

 Since this change is aimed specifically at one heuristic, I wonder
 whether we should parameterise that heuristic somehow rather than
 try to use a general hook to undo it.  But I don't think there's
 anything particularly special about MIPS16 here, so maybe it's too
 eager for all targets.

In a number of cases argument registers appeared to be unfairly promoted
increasing the register pressure and increasing the number of reloads.
Bumping up the cost of using those registers encourages IRA to spill
into memory but this appears to help LRA to do a better allocation. Of course,
not always it is a win but generally the gain outweighs the loss. 

I've seen an codesize improvements for other optimization levels
but I'm unsure whether we should make this change generic.
This part of the patch is not crucial though and can be send separately. 

  (define_insn *andmode3_mips16
 ...

 I think we want to keep the LWU case at the very least, since I assume
 otherwise we'll load the full 64-bit spill slot and use a pair of shifts
 to zero-extend it.  Reloading the stack address into a base register
 should always be better than that.

 I agree it's less clear for the byte and halfword cases.  All other
 things -- including size -- being equal, reloading a stack address into
 a base register and using an extending load should be better than
 reloading the full spill slot and extending it, since the reloaded stack
 address is more likely to be reused in other instructions.

 The 

Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-04-09 Thread Richard Sandiford
Robert Suchanek robert.sucha...@imgtec.com writes:
 FYI, all other targets that have LRA optionally selectable or deselectable
 use -mno-lra for this (even when -mlra is the default), it would be better
 for consistency not to invent new switch names for that.

 Agreed.

 -return !strict_p || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) 
 == 8;
 +return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
  
return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
  }
 Not sure about this one.  We would need to update the comment that
 explains why !strict_p is there, but AFAIK reason (1) would still apply.

 Was this needed for correctness or because it gave better code?

 !strict_p has been removed because of correctness issue. When LRA
 validates memory addresses pseudos are temporarily eliminated to hard
 registers (if possible) but the target hook is always called as
 non-strict. This only affects MIPS16 instructions with not directly
 accessible $sp. The strict variant, as I understand, was used in the
 reload pass to indicate if a pseudo-register has been allocated a hard
 register. Unless LRA should be setting the strict/non-strict depending
 on whether a temporal elimination to hard reg was successful or there
 is something else that I missed?

Hmm, OK, in that case I agree reason (2) doesn't apply.  That part was
always more of a consistency thing anyway, so I agree it's not worth
keeping around for reload.  I also had a look to see why
instantiate_virtual_regs_in_insn didn't complain about cases like:

  struct s { unsigned char c; };
  void foo (int, int, int, int, struct s);
  void bar (struct s *ptr) { foo (1, 2, 3, 4, *ptr); }

and I think it's because of the later:

2008-02-14  Michael Matz  m...@suse.de

PR target/34930
* function.c (instantiate_virtual_regs_in_insn): Reload address
before falling back to reloading the whole operand.

which correctly reloads the address if necessary.

So yeah, I agree this is right after all, sorry.  Let's delete the
comment starting at There are two problems here: at the same time.

 +  M16F_REGS,   /* mips16 + frame */

 Constraints are supposed to be operating on real registers, after
 elimination, so it seems odd to include a fake register.  What went
 wrong with just M16_REGS?

 Only the stack pointer has been added to M16_REGS.

Sorry, I'd read frame as meaning $frame, the soft frame pointer.
I agree M16_REGS + $sp is OK.

mips_regno_to_class should then map $sp to the new class, since it's now
the smallest containing class.  (We really should set that up automatically
one day...)

 A number of patterns need to accept it otherwise LRA inserts a lot of
 reloads and the code size goes up by about 10%.  The change does have
 also a positive effect on reload but marginally.  frame meant to
 indicate inclusion of both the stack and hard frame pointers in the
 class but perhaps I should name it differently to avoid confusion.

How about M16_SP_REGS, to match M16_T_REGS?

Also, the BASE_REG_CLASS/ADDR_REG_CLASS distinction isn't all that
obvious from the names.  ADDR_REG_CLASS is only needed for the d
constraint so maybe we could just use TARGET_MIPS16 ? M16_REGS : GR_REGS
directly for now.

 + SPILL_REGS, /* All but $sp and call preserved regs are in here */
...
 + { 0x0003fffc, 0x, 0x, 0x, 0x,
 0x }, /* SPILL_REGS */ \

 These two don't seem to match.  I think literally it would be 0x0300fffc,
 but maybe you had to make SPILL_REGS a superset of M16_REGs?

 I initially used 0x0300fffc but did some experiments and it turned out
 that 0x0003fffc (with $16, $17 regs) gives slightly better code. I
 haven't updated the comment though.

I can imagine including all M16_REGS makes sense, but it seems odd to
drop the 2 temporaries.  Does 0x0303fffc have the same problem?

 There is yet more to do and need to return to another thread with
 MIPS16 at some point as I found some limitations of IRA/LRA to
 generate better code. $8-$15 are currently inaccessible as temporary
 storage because these registers are marked as fixed (when optimizing
 for size) but leaving them as fixed are better for the code size. I
 don't expect a big gain by using hard registers for spilling but it
 more likely to improve the performance.

Hmm, marking them fixed was supposed to be a temporary reload-only thing,
until the move to LRA.  It should never be worse to spill to these GPRs
over spilling to the stack, if the value isn't live across a call.

But that certainly doesn't need to be part of the initial patch.

 +/* Add costs to hard registers based on frequency. This helps to negate
 +   some of the reduced cost associated with argument registers which 
 +   unfairly promotes their use and increases register pressure */
 +#define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(REGNO)   \
 +  (TARGET_MIPS16  optimize_size   \
 +   ? 

Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-03-29 Thread Richard Sandiford
First of all, thanks a lot for doing this.

Robert Suchanek robert.sucha...@imgtec.com writes:
 diff --git gcc/config/mips/mips.c gcc/config/mips/mips.c
 index 143169b..f27a801 100644
 --- gcc/config/mips/mips.c
 +++ gcc/config/mips/mips.c
 @@ -2255,7 +2255,7 @@ mips_regno_mode_ok_for_base_p (int regno, enum 
 machine_mode mode,
   All in all, it seems more consistent to only enforce this restriction
   during and after reload.  */
if (TARGET_MIPS16  regno == STACK_POINTER_REGNUM)
 -return !strict_p || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 
 8;
 +return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
  
return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
  }

Not sure about this one.  We would need to update the comment that
explains why !strict_p is there, but AFAIK reason (1) would still apply.

Was this needed for correctness or because it gave better code?

 +/* Return a register priority for hard reg REGNO.  */
 +
 +static int
 +mips_register_priority (int hard_regno)
 +{
 +  if (TARGET_MIPS16)
 +   {
 + /* Treat MIPS16 registers with higher priority than other regs.  */
 + switch (hard_regno)
 +   {
 +   case 2:
 +   case 3:
 +   case 4:
 +   case 5:
 +   case 6:
 +   case 7:
 +   case 16:
 +   case 17:
 + return 1;
 +   default:
 + return 0;
 +   }
 +   }
 +  return 0;
 +}
 +

Easier as:

  if (TARGET_MIPS16
   TEST_HARD_REG_BIT (reg_class_contents[M16_REGS], hard_regno))
return 1;
  return 0;

 diff --git gcc/config/mips/mips.h gcc/config/mips/mips.h
 index a786d4c..712008f 100644
 --- gcc/config/mips/mips.h
 +++ gcc/config/mips/mips.h
 @@ -1871,10 +1871,12 @@ enum reg_class
  {
NO_REGS,   /* no registers in set */
M16_REGS,  /* mips16 directly accessible registers */
 +  M16F_REGS, /* mips16 + frame */

Constraints are supposed to be operating on real registers, after
elimination, so it seems odd to include a fake register.  What went
wrong with just M16_REGS?

 +  SPILL_REGS,/* All but $sp and call preserved regs 
 are in here */
...
 +  { 0x0003fffc, 0x, 0x, 0x, 0x, 0x 
 },/* SPILL_REGS */\

These two don't seem to match.  I think literally it would be 0x0300fffc,
but maybe you had to make SPILL_REGS a superset of M16_REGs?

 +/* Add costs to hard registers based on frequency. This helps to negate
 +   some of the reduced cost associated with argument registers which 
 +   unfairly promotes their use and increases register pressure */
 +#define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(REGNO)   \
 +  (TARGET_MIPS16  optimize_size   \
 +   ? ((REGNO) = 4  (REGNO) = 7 ? 2 : 0) : 0)

So we would be trying to use, say, $4 for the first incoming argument
even after it had been spilled?  Hmm.

Since this change is aimed specifically at one heuristic, I wonder
whether we should parameterise that heuristic somehow rather than
try to use a general hook to undo it.  But I don't think there's
anything particularly special about MIPS16 here, so maybe it's too
eager for all targets.

 diff --git gcc/config/mips/mips.md gcc/config/mips/mips.md
 index 1e3e9e6..ababd5e 100644
 --- gcc/config/mips/mips.md
 +++ gcc/config/mips/mips.md
 @@ -1622,40 +1622,66 @@
  ;; copy instructions.  Reload therefore thinks that the second alternative
  ;; is two reloads more costly than the first.  We add *?*? to the first
  ;; alternative as a counterweight.
 +;;
 +;; LRA simulates reload but the cost of reloading scratches is lower
 +;; than of the classic reload. For the time being, removing the counterweight
 +;; for LRA is more profitable.
  (define_insn *mul_acc_si
 -  [(set (match_operand:SI 0 register_operand =l*?*?,d?)
 - (plus:SI (mult:SI (match_operand:SI 1 register_operand d,d)
 -   (match_operand:SI 2 register_operand d,d))
 -  (match_operand:SI 3 register_operand 0,d)))
 -   (clobber (match_scratch:SI 4 =X,l))
 -   (clobber (match_scratch:SI 5 =X,d))]
 +  [(set (match_operand:SI 0 register_operand =l*?*?,l,d?)
 + (plus:SI (mult:SI (match_operand:SI 1 register_operand d,d,d)
 +   (match_operand:SI 2 register_operand d,d,d))
 +  (match_operand:SI 3 register_operand 0,0,d)))
 +   (clobber (match_scratch:SI 4 =X,X,l))
 +   (clobber (match_scratch:SI 5 =X,X,d))]
GENERATE_MADD_MSUB  !TARGET_MIPS16
@
  madd\t%1,%2
 +madd\t%1,%2
  #
[(set_attr type  imadd)
 (set_attr accum_in  3)
 (set_attr mode  SI)
 -   (set_attr insn_count 1,2)])
 +   (set_attr insn_count 1,1,2)
 +   (set (attr enabled)
 +(cond [(and (eq_attr alternative 0)
 +(match_test TARGET_RELOAD))
 +  (const_string yes)
 +   (and (eq_attr alternative 1)
 +(match_test 

Re: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend

2014-03-29 Thread Jakub Jelinek
On Sat, Mar 29, 2014 at 01:07:40AM +, Robert Suchanek wrote:
 This patch enables LRA by default for MIPS. The classic reload is still
 available and can be enabled via -mreload switch. 

FYI, all other targets that have LRA optionally selectable or deselectable
use -mno-lra for this (even when -mlra is the default), it would be better
for consistency not to invent new switch names for that.

Jakub