public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PR target/48551] Make double_reg_address_ok a per-mode test
@ 2016-11-21  5:33 Jeff Law
  0 siblings, 0 replies; only message in thread
From: Jeff Law @ 2016-11-21  5:33 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2191 bytes --]

Sigh.  Reload.

Reload has the assumption that if reg+reg addressing is valid in QImode 
that it is valid in all modes.  This has been baked into reload as long 
as I can remember.

It's part of a larger problem that reload doesn't handle some cases 
where address validity is dependent upon the context in which the 
address is used.  I'm not going to try to solve that problem as a whole, 
but I can make this tiny piece better.

In BZ48551 we have a case where we want to reload an address like
(plus (fp) (-largeint)) for a DFmode memory access.  We need the reload 
because the target has a limited range for displacements.

Reload has multiple strategies for handling this situation, including 
loading the integer into an index register and using reg+reg style 
addressing.  This case is predicated on checking double_reg_address_ok.

The problem is when we initialize double_reg_address_ok, we only do so 
for QImode.  So if the target only allows reg+reg style addressing in 
QImode, but not other modes modes, then we can end up generating bogus 
RTL leading to an insn recognition failure as seen in this BZ as well as 
building libgfortran on m68k-elf.

The easy solution here is to have double_reg_address_ok for all modes.

In this particular case that will cause reload to compute (plus (fp) 
-largeint) into an address register, then use simple register indirect.

This should be safe on other ports still using reload.  If they have 
properties similar to coldfire, then this could potentially avoid the 
same problem on those ports.  If they were the opposite (reg+reg not 
allowed for QImode, but is allowed in other modes), then this could 
allows those ports to generate slightly more efficient code.  Either way 
it seems like the right thing to do.

This fixes BZ 48551 as well as the libgfortran build failures for 
m68k-elf.  Another win for retro-computing.  Verified against the 
testcase in BZ48551 as well as building libgfortran for m68k-elf.

Then I went back to gcc-4.7, which is pre-lra and did a bootstrap and 
comparison test on x86_64-linux-gnu to exercise the code path a little 
harder.  That (of course) was successful.

Installing on the trunk.

Jeff

[-- Attachment #2: P --]
[-- Type: text/plain, Size: 4408 bytes --]

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 91cbe82..40d6f8a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2016-11-20  Jeff Law  <law@redhat.com>
+
+	PR target/48551
+	* reload.h (struct target_reload): Make x_double_reg_address_ok
+	be per-mode rather.
+	* reload.c (find_reloads_address): Check if double_reg_address_ok
+	is true for the mode of the memory reference.
+	* reload1.c (init_reload): Initialize double_reg_address_ok for
+	each mode.
+
 2016-11-20  Aldy Hernandez  <aldyh@redhat.com>
 
 	PR middle-end/61409
diff --git a/gcc/reload.c b/gcc/reload.c
index 7d16817..4cba220 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -5090,7 +5090,7 @@ find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad,
 	    loc = &XEXP (*loc, 0);
 	}
 
-      if (double_reg_address_ok
+      if (double_reg_address_ok[mode]
 	  && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as,
 				  PLUS, CONST_INT))
 	{
diff --git a/gcc/reload.h b/gcc/reload.h
index 98b75e3..1fc8ecb 100644
--- a/gcc/reload.h
+++ b/gcc/reload.h
@@ -159,9 +159,6 @@ struct target_reload {
      which these are valid is the same as spill_indirect_levels, above.  */
   bool x_indirect_symref_ok;
 
-  /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid.  */
-  bool x_double_reg_address_ok;
-
   /* Nonzero if indirect addressing is supported on the machine; this means
      that spilling (REG n) does not require reloading it into a register in
      order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))).  The
@@ -181,6 +178,10 @@ struct target_reload {
 		     [FIRST_PSEUDO_REGISTER]
 		     [MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1]);
 
+  /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid
+     in the given mode.  */
+  bool x_double_reg_address_ok[MAX_MACHINE_MODE];
+
   /* We will only make a register eligible for caller-save if it can be
      saved in its widest mode with a simple SET insn as long as the memory
      address is valid.  We record the INSN_CODE is those insns here since
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 4ee3840..b855268 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -448,11 +448,10 @@ init_reload (void)
       /* This way, we make sure that reg+reg is an offsettable address.  */
       tem = plus_constant (Pmode, tem, 4);
 
-      if (memory_address_p (QImode, tem))
-	{
-	  double_reg_address_ok = 1;
-	  break;
-	}
+      for (int mode = 0; mode < MAX_MACHINE_MODE; mode++)
+	if (!double_reg_address_ok[mode]
+	    && memory_address_p ((enum machine_mode)mode, tem))
+	  double_reg_address_ok[mode] = 1;
     }
 
   /* Initialize obstack for our rtl allocation.  */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6a23d90..37e8403 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-11-20  Jeff Law  <law@redhat.com>
+
+	PR target/48551
+	* gcc.target/m68k/pr48551.c: New test.
+
 2016-11-20  Harald Anlauf  <anlauf@gmx.de>
  
 	PR fortran/69741
diff --git a/gcc/testsuite/gcc.target/m68k/pr48551.c b/gcc/testsuite/gcc.target/m68k/pr48551.c
new file mode 100644
index 0000000..48ea4b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/pr48551.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcpu=5475" } */
+
+/* This tickles a problem with reload on the m68k.  There's a reasonable
+   chance it will get stale over time.  */
+
+int frob;
+typedef double SplashCoord;
+void transform (SplashCoord xi, SplashCoord yi);
+void
+arf (SplashCoord x0, SplashCoord y0, SplashCoord x1, SplashCoord y1,
+     SplashCoord x2, SplashCoord y2, SplashCoord x3, SplashCoord y3,
+     SplashCoord * matrix, SplashCoord flatness2)
+{
+  SplashCoord cx[(1 << 10) + 1][3];
+  SplashCoord cy[(1 << 10) + 1][3];
+  SplashCoord xl0, xl1, xl2, xr0, xr1, xr2, xr3, xx1, xx2, xh;
+  SplashCoord yl0, yl1, yl2, yr0, yr1, yr2, yr3, yy1, yy2, yh;
+  int p1, p2, p3;
+  while (p1  < (1 << 10))
+    {
+      xl0 = cx[p1][0];
+      xx2 = cx[p1][2];
+      yy2 = cy[p1][2];
+      transform (xx2, yy2);
+      if (frob)
+	{
+	  xl1 = (xl0 + xx1);
+	  xh = (xx1 + xx2);
+	  yl2 = (yl1 + yh);
+	  xr2 = (xx2 + xr3);
+	  yr2 = (yy2 + yr3) * 0.5;
+	  xr1 = (xh + xr2);
+	  yr1 = (yh + yr2);
+	  xr0 = (xl2 + xr1);
+	  yr0 = (yl2 + yr1);
+	  cx[p1][1] = xl1;
+	  cy[p1][1] = yl1;
+	  cx[p1][2] = xl2;
+	  cx[p3][0] = xr0;
+	  cy[p3][0] = yr0;
+	}
+    }
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2016-11-21  5:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-21  5:33 [PR target/48551] Make double_reg_address_ok a per-mode test Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).