public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
@ 2012-05-07 13:57 Olivier Hainque
  2012-05-07 15:23 ` Olivier Hainque
                   ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Olivier Hainque @ 2012-05-07 13:57 UTC (permalink / raw)
  To: Joseph S. Myers, David Edelsohn; +Cc: Olivier Hainque, GCC Patches

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

Hello,

This is a followup on a discussion we had a while ago, starting with

  http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01543.html

The original issue was the vxworks port unduly clobbering explicit
SPE related options on powerpc, which it still does. The proposed patch
at the time was to prevent the clobbering locally, adding guards in the
vxworks.h code as there are in a few other targets already.

Joseph and David suggested to address this in a more general fashion,
along lines proposed in

  http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01667.html

The attached patch is a first shot in this direction. Only lightly tested
at this point, posted to get a first round of comments to validate that this
corresponds to what was suggested.

This indeed allows significant simplifications - cleaner configuration
model, defaults control factorized, no need for e500-double.h any more.
I'll be happy to do what I can to help in getting this in eventually.

One piece that for sure needs updating is 

The TARGET_NO_LWSYNC change suggests that maybe keeping a TARGET_E500 macro
would make sense after all, to convey "cpu features an E500 core" which happens
to imply SPE support and no LWSYNC. We could have a TARGET_E500MC as well to
make it clear that the latter family differs from the former. That's
actually a detail in the set of changes at hand.

In addition to what I understood of the suggestions made in the
aforementioned thread, this patch includes a change on the choice of
rs6000_cpu in options_override, so that it treats a --with-cpu passed
at configure time as an implicit -mcpu in absence of an explicit one.

This sounds reasonable and is useful for the more general change we're
discussing. 

This patch allowed me to build a few configurations with as-expected
results on gcc 4.7 base. The patch applies as-is on mainline. My first
attempt at building there failed, with

  --target=powerpc-eabispe --with-cpu=8548 --enable-languages=c --disable-libada 

(internal compiler error on unwind-dw2.c) This failure reproduces with
an unpatched tree as well, so there's something already broken in this area.

I suppose I can can look into this one first. I'd appreciate feedback on the
more general patch nevetheless :)   (whether that's the right direction, things
that you think should be done differently, indications as to how you'd like to
proceed further (testing etc), ...)

Thanks much in advance,

Olivier

2012-05-07  Olivier Hainque  <hainque@adacore.com>

	config/rs6000:

	* rs6000-opts.h (enum processor_type): Add PROCESSOR_PPC8548.
	* rs6000-cpus.def: Reference it for cpu="8548".
	* rs6000.md (cpu attribute definition): Add ppc8548.
	* 8540.md: indicate that the units/patterns apply to ppc8548 as well.

	* rs6000.c (rs6000_option_override_internal): Rename default_cpu into
	implicit_cpu, conveying what --with-cpu was passed at configure time.
	Treat implicit_cpu as have_cpu. Pick defaults for SPE related flags,
	check that what is queried is supported by the selected configuration.
	Rework the single/double_float and MASK_STRING resets to hit for all
	the E500 cores (854x + E500MC variants). Select the ppc8540 costs for
	PROCESSOR_PPC8548 as well.
	(rs6000_issue_rate): case CPU_PPC8548 together with CPU_PPC8540.
	(rs6000_use_sched_lookahead): Likewise, rewriting function as a case
	statement instead of a sequence of ifs.

	* rs6000.h (TARGET_E500): Remove.
	(TARGET_NO_LWSYNC): Adjust accordingly.
	* e500.h (TARGET_E500): Remove.
	(CHECK_E500_OPTIONS): Adjust accordingly.
	* eabispe.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Remove.
	(TARGET_DEFAULT): Reformat definition to match the one in linuxspe.h.
	* linuxspe.h: Likewise.
	* vxworks.h: Remove bogus TARGET_E500 overrides and superfluous comments.
	* e500-double.h: Remove.

	gcc:

	* config.gcc (pick a default with_cpu): For powerpc*-*-*spe*,
	default to with_cpu=8548 if --enable-e500-double, and to 8540
	otherwise.
	(set misc flags section): For powerpc*|rs6000*, remove inclusion
	of e500-double.h for --enable-e500-double.

[-- Attachment #2: e500.dif --]
[-- Type: video/x-dv, Size: 25383 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-07 13:57 remove TARGET_E500 and factorize SPE defaults computation in powerpc ports Olivier Hainque
@ 2012-05-07 15:23 ` Olivier Hainque
  2012-05-08 10:33   ` [RS6000] Fix PR53271 " Alan Modra
  2012-05-07 16:11 ` remove TARGET_E500 and factorize SPE defaults computation in powerpc ports Joseph S. Myers
  2012-05-16 12:33 ` Sebastian Huber
  2 siblings, 1 reply; 18+ messages in thread
From: Olivier Hainque @ 2012-05-07 15:23 UTC (permalink / raw)
  To: Joseph S. Myers, David Edelsohn; +Cc: Olivier Hainque, GCC Patches, Alan Modra


On May 7, 2012, at 15:57 , Olivier Hainque wrote:

> My first attempt at building there failed, with
> 
>  --target=powerpc-eabispe --with-cpu=8548 --enable-languages=c --disable-libada 
> 
> (internal compiler error on unwind-dw2.c) This failure reproduces with
> an unpatched tree as well, so there's something already broken in this area.

 This appears to be a fallout of the (very nice !) prologue/epilogue
 cleanup series issued last april, in particular rev 186797  corresponding to
 http://gcc.gnu.org/ml/gcc-patches/2012-04/msg01014.html (Alan cc'ed)

 This piece:

	(emit_frame_save): Don't handle reg+reg addressing.
 
 introduces an assert on which we now trip compiling unwind-dw2.c for SPE
 configurations. We now fall into the TARGET_SPE_ABI part of

   /* Some cases that need register indexed addressing.  */
   gcc_checking_assert (!((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
 			 || (TARGET_VSX && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
			 || (TARGET_E500_DOUBLE && mode == DFmode)
			 || (TARGET_SPE_ABI
			     && SPE_VECTOR_MODE (mode)
			     && !SPE_CONST_OFFSET_OK (offset))));

 in emit_frame_save while compiling uw_install_context.

 The call comes from this part of rs6000_emit_prologue: 

  /* ??? There's no need to emit actual instructions here, but it's the
     easiest way to get the frame unwind information emitted.  */
  if (crtl->calls_eh_return)
    {
      unsigned int i, regno;

      for (i = 0; ; ++i)
	{
	  regno = EH_RETURN_DATA_REGNO (i);
	  if (regno == INVALID_REGNUM)
	    break;

	  emit_frame_save (frame_reg_rtx, reg_mode, regno,
			   info->ehrd_offset + frame_off + reg_size * (int) i,
			   sp_off - frame_off);
	}
    }

 The crash reproduces on this artificial reproducer:

    void install (long offset, void * handler)
    {
      volatile int x [4096];
      __builtin_eh_return (offset, handler);
    }

 configure --enable-languages=c --disable-libada --target=powerpc-eabispe
 make ...

 ./cc1 ice.c
 ...
   ice.c: In function "˜install"€™:
   ice.c:6:1: internal compiler error: in emit_frame_save, at config/rs6000/rs6000.c:18979


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-07 13:57 remove TARGET_E500 and factorize SPE defaults computation in powerpc ports Olivier Hainque
  2012-05-07 15:23 ` Olivier Hainque
@ 2012-05-07 16:11 ` Joseph S. Myers
  2012-05-07 17:00   ` David Edelsohn
  2012-05-16 12:33 ` Sebastian Huber
  2 siblings, 1 reply; 18+ messages in thread
From: Joseph S. Myers @ 2012-05-07 16:11 UTC (permalink / raw)
  To: Olivier Hainque; +Cc: David Edelsohn, GCC Patches

On Mon, 7 May 2012, Olivier Hainque wrote:

> Joseph and David suggested to address this in a more general fashion,
> along lines proposed in
> 
>   http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01667.html
> 
> The attached patch is a first shot in this direction. Only lightly tested
> at this point, posted to get a first round of comments to validate that this
> corresponds to what was suggested.

I haven't checked the details of the patch, but it does look substantially 
along the lines of what I think the logic should be.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-07 16:11 ` remove TARGET_E500 and factorize SPE defaults computation in powerpc ports Joseph S. Myers
@ 2012-05-07 17:00   ` David Edelsohn
  2012-05-07 17:24     ` Olivier Hainque
  2012-05-15 13:47     ` Olivier Hainque
  0 siblings, 2 replies; 18+ messages in thread
From: David Edelsohn @ 2012-05-07 17:00 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Olivier Hainque, GCC Patches

On Mon, May 7, 2012 at 12:10 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Mon, 7 May 2012, Olivier Hainque wrote:
>
>> Joseph and David suggested to address this in a more general fashion,
>> along lines proposed in
>>
>>   http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01667.html
>>
>> The attached patch is a first shot in this direction. Only lightly tested
>> at this point, posted to get a first round of comments to validate that this
>> corresponds to what was suggested.
>
> I haven't checked the details of the patch, but it does look substantially
> along the lines of what I think the logic should be.

Yes, exactly.  If we can work through the fallout, this is exactly the
type of cleanup I envisioned.

Thanks, David

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-07 17:00   ` David Edelsohn
@ 2012-05-07 17:24     ` Olivier Hainque
  2012-05-07 18:31       ` David Edelsohn
  2012-05-15 13:47     ` Olivier Hainque
  1 sibling, 1 reply; 18+ messages in thread
From: Olivier Hainque @ 2012-05-07 17:24 UTC (permalink / raw)
  To: David Edelsohn; +Cc: Olivier Hainque, Joseph S. Myers, GCC Patches, Alan Modra


On May 7, 2012, at 18:59 , David Edelsohn wrote:
> Yes, exactly.  If we can work through the fallout, this is exactly the
> type of cleanup I envisioned.

 Great :)

> Thanks, David

 Do you want a PR for the fallout ? It is not related to this patch
 at all. I can look into it further and make suggestions but this is
 part of a recent prologue/epilogue reorg with which I'm not yet too
 familiar.

 Olivier

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-07 17:24     ` Olivier Hainque
@ 2012-05-07 18:31       ` David Edelsohn
  2012-05-07 19:27         ` Olivier Hainque
  0 siblings, 1 reply; 18+ messages in thread
From: David Edelsohn @ 2012-05-07 18:31 UTC (permalink / raw)
  To: Olivier Hainque; +Cc: Joseph S. Myers, GCC Patches, Alan Modra

On Mon, May 7, 2012 at 1:24 PM, Olivier Hainque <hainque@adacore.com> wrote:
>
> On May 7, 2012, at 18:59 , David Edelsohn wrote:
>> Yes, exactly.  If we can work through the fallout, this is exactly the
>> type of cleanup I envisioned.
>
>  Great :)
>
>> Thanks, David
>
>  Do you want a PR for the fallout ? It is not related to this patch
>  at all. I can look into it further and make suggestions but this is
>  part of a recent prologue/epilogue reorg with which I'm not yet too
>  familiar.

You can open a PR, but I assume that you mean fixing the problem
before the patch is committed.  I would like to give Alan a chance to
comment and look into it.

Thanks, David

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-07 18:31       ` David Edelsohn
@ 2012-05-07 19:27         ` Olivier Hainque
  2012-05-07 20:54           ` Olivier Hainque
  0 siblings, 1 reply; 18+ messages in thread
From: Olivier Hainque @ 2012-05-07 19:27 UTC (permalink / raw)
  To: David Edelsohn; +Cc: Olivier Hainque, Joseph S. Myers, GCC Patches, Alan Modra


On May 7, 2012, at 20:31 , David Edelsohn wrote:
> You can open a PR, but I assume that you mean fixing the problem
> before the patch is committed.

 Yes, that was the intent.

>  I would like to give Alan a chance to
> comment and look into it.

 Of course. That was actually my point in offering
 to open a PR, so that Alan (who did the nice recent
 reorg) can take it from there. He will certainly be
 more efficient than me in resolving this :)

 Olivier

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-07 19:27         ` Olivier Hainque
@ 2012-05-07 20:54           ` Olivier Hainque
  0 siblings, 0 replies; 18+ messages in thread
From: Olivier Hainque @ 2012-05-07 20:54 UTC (permalink / raw)
  To: David Edelsohn; +Cc: Olivier Hainque, Joseph S. Myers, GCC Patches, Alan Modra


On May 7, 2012, at 21:27 , Olivier Hainque wrote:
> Of course. That was actually my point in offering
> to open a PR, so that Alan (who did the nice recent
> reorg) can take it from there. He will certainly be
> more efficient than me in resolving this :)

PR 53271


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RS6000] Fix PR53271 powerpc ports
  2012-05-07 15:23 ` Olivier Hainque
@ 2012-05-08 10:33   ` Alan Modra
  2012-05-08 14:16     ` David Edelsohn
  2012-05-21  2:48     ` [RS6000] save/restore reg tidy Alan Modra
  0 siblings, 2 replies; 18+ messages in thread
From: Alan Modra @ 2012-05-08 10:33 UTC (permalink / raw)
  To: Olivier Hainque, David Edelsohn; +Cc: GCC Patches

On Mon, May 07, 2012 at 05:23:33PM +0200, Olivier Hainque wrote:
> 	(emit_frame_save): Don't handle reg+reg addressing.
>  
>  introduces an assert on which we now trip compiling unwind-dw2.c for SPE
>  configurations. We now fall into the TARGET_SPE_ABI part of
> 
>    /* Some cases that need register indexed addressing.  */
>    gcc_checking_assert (!((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
>  			 || (TARGET_VSX && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
> 			 || (TARGET_E500_DOUBLE && mode == DFmode)
> 			 || (TARGET_SPE_ABI
> 			     && SPE_VECTOR_MODE (mode)
> 			     && !SPE_CONST_OFFSET_OK (offset))));
> 
>  in emit_frame_save while compiling uw_install_context.
> 
>  The call comes from this part of rs6000_emit_prologue: 
> 
>   /* ??? There's no need to emit actual instructions here, but it's the
>      easiest way to get the frame unwind information emitted.  */

OK, the assert is doing its job.  I wanted to minimize the number of
places that need temporary hard regs, so that tracking of which hard
reg is in use can all be done in rs6000_emit_prologue.

The problem is that the insns here need reg+reg addressing on SPE,
but as the ??? comment says we really don't need insns, just the eh
unwind reg info.  So that is what the following patch does, attaching
the eh info to a blockage.

I also make use of gen_frame_store and siblings that I invented for
generating the eh info, elsewhere in rs6000.c where doing so is
blindingly obvious.  We could probably use them in other places too,
but I'll leave that for later.  Bootstrapped and regression tested
powerpc-linux.  OK to apply?

	PR target/53271
	* config/rs6000/rs6000.c (gen_frame_set): New function.
	(gen_frame_load, gen_frame_store): New functions.
	(rs6000_savres_rtx): Use the above.
	(rs6000_emit_epilogue, rs6000_emit_prologue): Here too.
	Correct mode used for CR2 in save/restore_world patterns.
	Don't emit instructions for eh_return frame unwind reg info.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 187275)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -18961,6 +18961,28 @@
   return insn;
 }
 
+static rtx
+gen_frame_set (rtx reg, rtx frame_reg, int offset, bool store)
+{
+  rtx addr, mem;
+
+  addr = gen_rtx_PLUS (Pmode, frame_reg, GEN_INT (offset));
+  mem = gen_frame_mem (GET_MODE (reg), addr);
+  return gen_rtx_SET (VOIDmode, store ? mem : reg, store ? reg : mem);
+}
+
+static rtx
+gen_frame_load (rtx reg, rtx frame_reg, int offset)
+{
+  return gen_frame_set (reg, frame_reg, offset, false);
+}
+
+static rtx
+gen_frame_store (rtx reg, rtx frame_reg, int offset)
+{
+  return gen_frame_set (reg, frame_reg, offset, true);
+}
+
 /* Save a register into the frame, and emit RTX_FRAME_RELATED_P notes.
    Save REGNO into [FRAME_REG + OFFSET] in mode MODE.  */
 
@@ -19301,27 +19323,14 @@
       = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, use_reg));
 
   for (i = 0; i < end_reg - start_reg; i++)
-    {
-      rtx addr, reg, mem;
-      reg = gen_rtx_REG (reg_mode, start_reg + i);
-      addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-			   GEN_INT (save_area_offset + reg_size * i));
-      mem = gen_frame_mem (reg_mode, addr);
+    RTVEC_ELT (p, i + offset)
+      = gen_frame_set (gen_rtx_REG (reg_mode, start_reg + i),
+		       frame_reg_rtx, save_area_offset + reg_size * i,
+		       (sel & SAVRES_SAVE) != 0);
 
-      RTVEC_ELT (p, i + offset) = gen_rtx_SET (VOIDmode,
-					       (sel & SAVRES_SAVE) ? mem : reg,
-					       (sel & SAVRES_SAVE) ? reg : mem);
-    }
-
   if ((sel & SAVRES_SAVE) && (sel & SAVRES_LR))
-    {
-      rtx addr, reg, mem;
-      reg = gen_rtx_REG (Pmode, 0);
-      addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-			   GEN_INT (lr_offset));
-      mem = gen_frame_mem (Pmode, addr);
-      RTVEC_ELT (p, i + offset) = gen_rtx_SET (VOIDmode, mem, reg);
-    }
+    RTVEC_ELT (p, i + offset)
+      = gen_frame_store (gen_rtx_REG (Pmode, 0), frame_reg_rtx, lr_offset);
 
   par = gen_rtx_PARALLEL (VOIDmode, p);
 
@@ -19479,59 +19488,33 @@
       /* We do floats first so that the instruction pattern matches
 	 properly.  */
       for (i = 0; i < 64 - info->first_fp_reg_save; i++)
-	{
-	  rtx reg = gen_rtx_REG ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
-				  ? DFmode : SFmode),
-				 info->first_fp_reg_save + i);
-	  rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				   GEN_INT (info->fp_save_offset
-					    + frame_off + 8 * i));
-	  rtx mem = gen_frame_mem ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
-				    ? DFmode : SFmode), addr);
-
-	  RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
-	}
+	RTVEC_ELT (p, j++)
+	  = gen_frame_store (gen_rtx_REG (TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
+					  ? DFmode : SFmode,
+					  info->first_fp_reg_save + i),
+			     frame_reg_rtx,
+			     info->fp_save_offset + frame_off + 8 * i);
       for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
-	{
-	  rtx reg = gen_rtx_REG (V4SImode, info->first_altivec_reg_save + i);
-	  rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				   GEN_INT (info->altivec_save_offset
-					    + frame_off + 16 * i));
-	  rtx mem = gen_frame_mem (V4SImode, addr);
-
-	  RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
-	}
+	RTVEC_ELT (p, j++)
+	  = gen_frame_store (gen_rtx_REG (V4SImode,
+					  info->first_altivec_reg_save + i),
+			     frame_reg_rtx,
+			     info->altivec_save_offset + frame_off + 16 * i);
       for (i = 0; i < 32 - info->first_gp_reg_save; i++)
-	{
-	  rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
-	  rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				   GEN_INT (info->gp_save_offset
-					    + frame_off + reg_size * i));
-	  rtx mem = gen_frame_mem (reg_mode, addr);
+	RTVEC_ELT (p, j++)
+	  = gen_frame_store (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
+			     frame_reg_rtx,
+			     info->gp_save_offset + frame_off + reg_size * i);
 
-	  RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
-	}
-
-      {
-	/* CR register traditionally saved as CR2.  */
-	rtx reg = gen_rtx_REG (reg_mode, CR2_REGNO);
-	rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				 GEN_INT (info->cr_save_offset
-					  + frame_off));
-	rtx mem = gen_frame_mem (reg_mode, addr);
-
-	RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
-      }
+      /* CR register traditionally saved as CR2.  */
+      RTVEC_ELT (p, j++)
+	= gen_frame_store (gen_rtx_REG (SImode, CR2_REGNO),
+			   frame_reg_rtx, info->cr_save_offset + frame_off);
       /* Explain about use of R0.  */
       if (info->lr_save_p)
-	{
-	  rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				   GEN_INT (info->lr_save_offset
-					    + frame_off));
-	  rtx mem = gen_frame_mem (reg_mode, addr);
-
-	  RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg0);
-	}
+	RTVEC_ELT (p, j++)
+	  = gen_frame_store (reg0,
+			     frame_reg_rtx, info->lr_save_offset + frame_off);
       /* Explain what happens to the stack pointer.  */
       {
 	rtx newval = gen_rtx_PLUS (Pmode, sp_reg_rtx, treg);
@@ -19834,17 +19817,10 @@
       int i;
       p = rtvec_alloc (32 - info->first_gp_reg_save);
       for (i = 0; i < 32 - info->first_gp_reg_save; i++)
-	{
-	  rtx addr, reg, mem;
-	  reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
-	  addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-			       GEN_INT (info->gp_save_offset
-					+ frame_off
-					+ reg_size * i));
-	  mem = gen_frame_mem (reg_mode, addr);
-
-	  RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, mem, reg);
-	}
+	RTVEC_ELT (p, i)
+	  = gen_frame_store (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
+			     frame_reg_rtx,
+			     info->gp_save_offset + frame_off + reg_size * i);
       insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
       rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
 			    NULL_RTX, NULL_RTX);
@@ -19860,22 +19836,37 @@
 			   sp_off - frame_off);
     }
 
-  /* ??? There's no need to emit actual instructions here, but it's the
-     easiest way to get the frame unwind information emitted.  */
   if (crtl->calls_eh_return)
     {
-      unsigned int i, regno;
+      unsigned int i;
+      rtvec p;
 
       for (i = 0; ; ++i)
 	{
-	  regno = EH_RETURN_DATA_REGNO (i);
+	  unsigned int regno = EH_RETURN_DATA_REGNO (i);
 	  if (regno == INVALID_REGNUM)
 	    break;
+	}
 
-	  emit_frame_save (frame_reg_rtx, reg_mode, regno,
-			   info->ehrd_offset + frame_off + reg_size * (int) i,
-			   sp_off - frame_off);
+      p = rtvec_alloc (i);
+
+      for (i = 0; ; ++i)
+	{
+	  unsigned int regno = EH_RETURN_DATA_REGNO (i);
+	  if (regno == INVALID_REGNUM)
+	    break;
+
+	  insn
+	    = gen_frame_store (gen_rtx_REG (reg_mode, regno),
+			       sp_reg_rtx,
+			       info->ehrd_offset + sp_off + reg_size * (int) i);
+	  RTVEC_ELT (p, i) = insn;
+	  RTX_FRAME_RELATED_P (insn) = 1;
 	}
+
+      insn = emit_insn (gen_blockage ());
+      RTX_FRAME_RELATED_P (insn) = 1;
+      add_reg_note (insn, REG_FRAME_RELATED_EXPR, gen_rtx_PARALLEL (VOIDmode, p));
     }
 
   /* In AIX ABI we need to make sure r2 is really saved.  */
@@ -20522,13 +20513,9 @@
 
       {
 	/* CR register traditionally saved as CR2.  */
-	rtx reg = gen_rtx_REG (reg_mode, CR2_REGNO);
-	rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				 GEN_INT (info->cr_save_offset));
-	rtx mem = gen_frame_mem (reg_mode, addr);
-
-	RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
-
+	rtx reg = gen_rtx_REG (SImode, CR2_REGNO);
+	RTVEC_ELT (p, j++)
+	  = gen_frame_load (reg, frame_reg_rtx, info->cr_save_offset);
 	if (flag_shrink_wrap)
 	  {
 	    cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
@@ -20541,24 +20528,18 @@
       for (i = 0; i < 32 - info->first_gp_reg_save; i++)
 	{
 	  rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
-	  rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				   GEN_INT (info->gp_save_offset
-					    + reg_size * i));
-	  rtx mem = gen_frame_mem (reg_mode, addr);
-
-	  RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+	  RTVEC_ELT (p, j++)
+	    = gen_frame_load (reg,
+			      frame_reg_rtx, info->gp_save_offset + reg_size * i);
 	  if (flag_shrink_wrap)
 	    cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
 	}
       for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
 	{
 	  rtx reg = gen_rtx_REG (V4SImode, info->first_altivec_reg_save + i);
-	  rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				   GEN_INT (info->altivec_save_offset
-					    + 16 * i));
-	  rtx mem = gen_frame_mem (V4SImode, addr);
-
-	  RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+	  RTVEC_ELT (p, j++)
+	    = gen_frame_load (reg,
+			      frame_reg_rtx, info->altivec_save_offset + 16 * i);
 	  if (flag_shrink_wrap)
 	    cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
 	}
@@ -20567,13 +20548,8 @@
 	  rtx reg = gen_rtx_REG ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
 				  ? DFmode : SFmode),
 				 info->first_fp_reg_save + i);
-	  rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				   GEN_INT (info->fp_save_offset
-					    + 8 * i));
-	  rtx mem = gen_frame_mem ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
-				    ? DFmode : SFmode), addr);
-
-	  RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+	  RTVEC_ELT (p, j++)
+	    = gen_frame_load (reg, frame_reg_rtx, info->fp_save_offset + 8 * i);
 	  if (flag_shrink_wrap)
 	    cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
 	}
@@ -21076,16 +21052,10 @@
       rtvec p;
       p = rtvec_alloc (32 - info->first_gp_reg_save);
       for (i = 0; i < 32 - info->first_gp_reg_save; i++)
-	{
-	  rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				   GEN_INT (info->gp_save_offset
-					    + frame_off
-					    + reg_size * i));
-	  rtx mem = gen_frame_mem (reg_mode, addr);
-	  rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
-
-	  RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, reg, mem);
-	}
+	RTVEC_ELT (p, i)
+	  = gen_frame_load (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
+			    frame_reg_rtx,
+			    info->gp_save_offset + frame_off + reg_size * i);
       emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
     }
   else
@@ -21277,14 +21247,10 @@
 						       ? 1 : 11));
 	  for (i = 0; i < 64 - info->first_fp_reg_save; i++)
 	    {
-	      rtx addr, mem, reg;
+	      rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
 
-	      addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
-				   GEN_INT (info->fp_save_offset + 8 * i));
-	      mem = gen_frame_mem (DFmode, addr);
-	      reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
-
-	      RTVEC_ELT (p, i + 4) = gen_rtx_SET (VOIDmode, reg, mem);
+	      RTVEC_ELT (p, i + 4)
+		= gen_frame_load (reg, sp_reg_rtx, info->fp_save_offset + 8 * i);
 	      if (flag_shrink_wrap)
 		cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
 					       cfa_restores);

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RS6000] Fix PR53271 powerpc ports
  2012-05-08 10:33   ` [RS6000] Fix PR53271 " Alan Modra
@ 2012-05-08 14:16     ` David Edelsohn
  2012-05-21  2:48     ` [RS6000] save/restore reg tidy Alan Modra
  1 sibling, 0 replies; 18+ messages in thread
From: David Edelsohn @ 2012-05-08 14:16 UTC (permalink / raw)
  To: Olivier Hainque, GCC Patches, Alan Modra

On Tue, May 8, 2012 at 6:32 AM, Alan Modra <amodra@gmail.com> wrote:

> OK, the assert is doing its job.  I wanted to minimize the number of
> places that need temporary hard regs, so that tracking of which hard
> reg is in use can all be done in rs6000_emit_prologue.
>
> The problem is that the insns here need reg+reg addressing on SPE,
> but as the ??? comment says we really don't need insns, just the eh
> unwind reg info.  So that is what the following patch does, attaching
> the eh info to a blockage.
>
> I also make use of gen_frame_store and siblings that I invented for
> generating the eh info, elsewhere in rs6000.c where doing so is
> blindingly obvious.  We could probably use them in other places too,
> but I'll leave that for later.  Bootstrapped and regression tested
> powerpc-linux.  OK to apply?
>
>        PR target/53271
>        * config/rs6000/rs6000.c (gen_frame_set): New function.
>        (gen_frame_load, gen_frame_store): New functions.
>        (rs6000_savres_rtx): Use the above.
>        (rs6000_emit_epilogue, rs6000_emit_prologue): Here too.
>        Correct mode used for CR2 in save/restore_world patterns.
>        Don't emit instructions for eh_return frame unwind reg info.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-07 17:00   ` David Edelsohn
  2012-05-07 17:24     ` Olivier Hainque
@ 2012-05-15 13:47     ` Olivier Hainque
  2012-05-16  1:11       ` David Edelsohn
  1 sibling, 1 reply; 18+ messages in thread
From: Olivier Hainque @ 2012-05-15 13:47 UTC (permalink / raw)
  To: David Edelsohn; +Cc: Olivier Hainque, GCC Patches

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

Hello David,

Back on this one after Alan's correction and extra testing of the
patch on my side.

On May 7, 2012, at 18:59 , David Edelsohn wrote:

>>>   http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01667.html
> 
> Yes, exactly.  If we can work through the fallout, this is exactly the
> type of cleanup I envisioned.

 Attached is a slightly modified version, with a bug fix regarding the
 ISEL deactivation. The original patch kept the logic of the test but
 mistakenly just extracted out of an outer "else" conditional branch, so
 doing it for e500 targets as well. In this version, the test is moved
 in the "default:" part of the case statement introduced to isolate e500
 specific operations, replacing the previous if/else construct.

 This version builds and regtests fine for default languages on
 powerpc-eabisim on an x86_64-linux host. It also bootstraps and regtests
 fine for languages=all,ada on powerpc-generic-linux-gnu.

 OK to commit ?

 With Kind Regards,

 Olivier

2012-05-15  Olivier Hainque  <hainque@adacore.com>

	config/rs6000:

	* rs6000-opts.h (enum processor_type): Add PROCESSOR_PPC8548.
	* rs6000-cpus.def: Reference it for cpu="8548".
	* rs6000.md (cpu attribute definition): Add ppc8548.
	* 8540.md: indicate that the units/patterns apply to ppc8548 as well.

	* rs6000.c (rs6000_option_override_internal): Rename default_cpu into
	implicit_cpu, conveying what --with-cpu was passed at configure time.
	Treat implicit_cpu as have_cpu. Pick defaults for SPE related flags,
	check that what is queried is supported by the selected configuration.
	Rework the single/double_float and MASK_STRING resets to hit for all
	the E500 cores (854x + E500MC variants). Select the ppc8540 costs for
	PROCESSOR_PPC8548 as well.
	(rs6000_issue_rate): case CPU_PPC8548 together with CPU_PPC8540.
	(rs6000_use_sched_lookahead): Likewise, rewriting function as a case
	statement instead of a sequence of ifs.

	* rs6000.h (TARGET_E500): Remove.
	(TARGET_NO_LWSYNC): Adjust accordingly.
	* e500.h (TARGET_E500): Remove.
	(CHECK_E500_OPTIONS): Adjust accordingly.
	* eabispe.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Remove.
	(TARGET_DEFAULT): Reformat definition to match the one in linuxspe.h.
	* linuxspe.h: Likewise.
	* vxworks.h: Remove bogus TARGET_E500 overrides and superfluous comments.
	* e500-double.h: Remove.

	gcc:

	* config.gcc (pick a default with_cpu): For powerpc*-*-*spe*,
	default to with_cpu=8548 if --enable-e500-double, and to 8540
	otherwise.
	(set misc flags section): For powerpc*|rs6000*, remove inclusion
	of e500-double.h for --enable-e500-double.

 

[-- Attachment #2: e500-2.diff --]
[-- Type: application/octet-stream, Size: 25403 bytes --]

Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 187316)
+++ gcc/config.gcc	(working copy)
@@ -2828,6 +2828,13 @@
     mips*-*-vxworks)
       with_arch=mips2
       ;;
+    powerpc*-*-*spe*)
+      if test x$enable_e500_double = xyes; then
+         with_cpu=8548
+      else
+         with_cpu=8540
+      fi       
+      ;;
     sparc-leon*-*)
       with_cpu=v8;
       ;;
@@ -3509,11 +3516,6 @@
 		c_target_objs="${c_target_objs} rs6000-c.o"
 		cxx_target_objs="${cxx_target_objs} rs6000-c.o"
 		tmake_file="rs6000/t-rs6000 ${tmake_file}"
-
-                if test x$enable_e500_double = xyes
-                then
-                        tm_file="$tm_file rs6000/e500-double.h"
-                fi
 		;;
 
 	sh[123456ble]*-*-* | sh-*-*)
Index: gcc/config/rs6000/linuxspe.h
===================================================================
--- gcc/config/rs6000/linuxspe.h	(revision 187316)
+++ gcc/config/rs6000/linuxspe.h	(working copy)
@@ -22,20 +22,8 @@
 
 /* Override rs6000.h and sysv4.h definition.  */
 #undef	TARGET_DEFAULT
-#define	TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_STRICT_ALIGN)
+#define TARGET_DEFAULT \
+  (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_STRICT_ALIGN)
 
-#undef  SUBSUBTARGET_OVERRIDE_OPTIONS
-#define SUBSUBTARGET_OVERRIDE_OPTIONS \
-  if (!global_options_set.x_rs6000_cpu_index) \
-    rs6000_cpu = PROCESSOR_PPC8540; \
-  if (!global_options_set.x_rs6000_spe_abi) \
-    rs6000_spe_abi = 1; \
-  if (!global_options_set.x_rs6000_float_gprs) \
-    rs6000_float_gprs = 1; \
-  if (!global_options_set.x_rs6000_spe) \
-    rs6000_spe = 1; \
-  if (target_flags & MASK_64BIT) \
-    error ("-m64 not supported in this configuration")
-
 #undef  ASM_DEFAULT_SPEC
 #define	ASM_DEFAULT_SPEC "-mppc -mspe -me500"
Index: gcc/config/rs6000/8540.md
===================================================================
--- gcc/config/rs6000/8540.md	(revision 187316)
+++ gcc/config/rs6000/8540.md	(working copy)
@@ -87,18 +87,18 @@
   (and (eq_attr "type" "integer,insert_word,insert_dword,cmp,compare,\
                         delayed_compare,var_delayed_compare,fast_compare,\
                         shift,trap,var_shift_rotate,cntlz,exts,isel")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
 
 (define_insn_reservation "ppc8540_two" 1
   (and (eq_attr "type" "two")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire,\
    ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
 
 (define_insn_reservation "ppc8540_three" 1
   (and (eq_attr "type" "three")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire,\
    ppc8540_issue+ppc8540_su_stage0+ppc8540_retire,\
    ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
@@ -106,13 +106,13 @@
 ;; Branch.  Actually this latency time is not used by the scheduler.
 (define_insn_reservation "ppc8540_branch" 1
   (and (eq_attr "type" "jmpreg,branch,isync")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_bu,ppc8540_retire")
 
 ;; Multiply
 (define_insn_reservation "ppc8540_multiply" 4
   (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_mu_stage0,ppc8540_mu_stage1,\
    ppc8540_mu_stage2,ppc8540_mu_stage3+ppc8540_retire")
 
@@ -122,57 +122,57 @@
 ;; time.
 (define_insn_reservation "ppc8540_divide" 14
   (and (eq_attr "type" "idiv")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_mu_stage0+ppc8540_mu_div,\
    ppc8540_mu_div*13")
 
 ;; CR logical
 (define_insn_reservation "ppc8540_cr_logical" 1
   (and (eq_attr "type" "cr_logical,delayed_cr")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_bu,ppc8540_retire")
 
 ;; Mfcr
 (define_insn_reservation "ppc8540_mfcr" 1
   (and (eq_attr "type" "mfcr")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su1_stage0+ppc8540_retire")
 
 ;; Mtcrf
 (define_insn_reservation "ppc8540_mtcrf" 1
   (and (eq_attr "type" "mtcr")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su1_stage0+ppc8540_retire")
 
 ;; Mtjmpr
 (define_insn_reservation "ppc8540_mtjmpr" 1
   (and (eq_attr "type" "mtjmpr,mfjmpr")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
 
 ;; Loads
 (define_insn_reservation "ppc8540_load" 3
   (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
 			load_l,sync")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_lsu,nothing,ppc8540_retire")
 
 ;; Stores.
 (define_insn_reservation "ppc8540_store" 3
   (and (eq_attr "type" "store,store_ux,store_u,store_c")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_lsu,nothing,ppc8540_retire")
 
 ;; Simple FP
 (define_insn_reservation "ppc8540_simple_float" 1
   (and (eq_attr "type" "fpsimple")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
 
 ;; FP
 (define_insn_reservation "ppc8540_float" 4
   (and (eq_attr "type" "fp")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_mu_stage0,ppc8540_mu_stage1,\
    ppc8540_mu_stage2,ppc8540_mu_stage3+ppc8540_retire")
 
@@ -180,44 +180,44 @@
 ;; because of the result automata will be huge.
 (define_insn_reservation "ppc8540_float_vector_divide" 29
   (and (eq_attr "type" "vecfdiv")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_mu_stage0+ppc8540_mu_div,\
    ppc8540_mu_div*28")
 
 ;; Brinc
 (define_insn_reservation "ppc8540_brinc" 1
   (and (eq_attr "type" "brinc")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
 
 ;; Simple vector
 (define_insn_reservation "ppc8540_simple_vector" 1
   (and (eq_attr "type" "vecsimple")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su1_stage0+ppc8540_retire")
 
 ;; Simple vector compare
 (define_insn_reservation "ppc8540_simple_vector_compare" 1
   (and (eq_attr "type" "veccmpsimple")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
 
 ;; Vector compare
 (define_insn_reservation "ppc8540_vector_compare" 1
   (and (eq_attr "type" "veccmp")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su1_stage0+ppc8540_retire")
 
 ;; evsplatfi evsplati
 (define_insn_reservation "ppc8540_vector_perm" 1
   (and (eq_attr "type" "vecperm")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su1_stage0+ppc8540_retire")
 
 ;; Vector float
 (define_insn_reservation "ppc8540_float_vector" 4
   (and (eq_attr "type" "vecfloat")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_mu_stage0,ppc8540_mu_stage1,\
    ppc8540_mu_stage2,ppc8540_mu_stage3+ppc8540_retire")
 
@@ -226,25 +226,25 @@
 ;; of miu_stage3 here because we use the average latency time.
 (define_insn_reservation "ppc8540_vector_divide" 14
   (and (eq_attr "type" "vecdiv")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_mu_stage0+ppc8540_mu_div,\
    ppc8540_mu_div*13")
 
 ;; Complex vector.
 (define_insn_reservation "ppc8540_complex_vector" 4
   (and (eq_attr "type" "veccomplex")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_mu_stage0,ppc8540_mu_stage1,\
    ppc8540_mu_stage2,ppc8540_mu_stage3+ppc8540_retire")
 
 ;; Vector load
 (define_insn_reservation "ppc8540_vector_load" 3
   (and (eq_attr "type" "vecload")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_lsu,nothing,ppc8540_retire")
 
 ;; Vector store
 (define_insn_reservation "ppc8540_vector_store" 3
   (and (eq_attr "type" "vecstore")
-       (eq_attr "cpu" "ppc8540"))
+       (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_lsu,nothing,ppc8540_retire")
Index: gcc/config/rs6000/rtems.h
===================================================================
--- gcc/config/rs6000/rtems.h	(revision 187316)
+++ gcc/config/rs6000/rtems.h	(working copy)
@@ -55,17 +55,3 @@
 #undef  SUBSUBTARGET_EXTRA_SPECS
 #define SUBSUBTARGET_EXTRA_SPECS \
   { "cpp_os_rtems",		CPP_OS_RTEMS_SPEC }
-
-#undef SUBSUBTARGET_OVERRIDE_OPTIONS
-#define SUBSUBTARGET_OVERRIDE_OPTIONS                                     \
-  do {                                                                    \
-   if (TARGET_E500)                                                       \
-      {                                                                   \
-        if (TARGET_HARD_FLOAT && !global_options_set.x_rs6000_float_gprs) \
-          rs6000_float_gprs = 1;                                          \
-        if (rs6000_float_gprs != 0 && !global_options_set.x_rs6000_spe)   \
-          rs6000_spe = 1;                                                 \
-        if (rs6000_spe && !global_options_set.x_rs6000_spe_abi)           \
-          rs6000_spe_abi = 1;                                             \
-      }                                                                   \
-  } while(0)
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 187316)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -2592,7 +2592,10 @@
 {
   bool ret = true;
   bool have_cpu = false;
-  const char *default_cpu = OPTION_TARGET_CPU_DEFAULT;
+
+  /* The default cpu requested at configure time, if any.  */
+  const char *implicit_cpu = OPTION_TARGET_CPU_DEFAULT;
+
   int set_masks;
   int cpu_index;
   int tune_index;
@@ -2611,11 +2614,6 @@
     warning (0, "-malign-power is not supported for 64-bit Darwin;"
 	     " it is incompatible with the installed C and C++ libraries");
 
-  if (global_options_set.x_rs6000_spe_abi
-      && rs6000_spe_abi
-      && !TARGET_SPE_ABI)
-    error ("not configured for SPE ABI");
-
   /* Numerous experiment shows that IRA based loop pressure
      calculation works better for RTL loop invariant motion on targets
      with enough (>= 32) registers.  It is an expensive optimization.
@@ -2651,7 +2649,8 @@
   /* Process the -mcpu=<xxx> and -mtune=<xxx> argument.  If the user changed
      the cpu in a target attribute or pragma, but did not specify a tuning
      option, use the cpu for the tuning option rather than the option specified
-     with -mtune on the command line.  */
+     with -mtune on the command line.  Process a '--with-cpu' configuration
+     request as an implicit --cpu.  */
   if (rs6000_cpu_index >= 0)
     {
       cpu_index = rs6000_cpu_index;
@@ -2664,10 +2663,12 @@
     }
   else
     {
-      if (!default_cpu)
-	default_cpu = (TARGET_POWERPC64 ? "powerpc64" : "powerpc");
+      const char *default_cpu =
+        (implicit_cpu ? implicit_cpu
+         : (TARGET_POWERPC64 ? "powerpc64" : "powerpc"));
 
       rs6000_cpu_index = cpu_index = rs6000_cpu_name_lookup (default_cpu);
+      have_cpu = implicit_cpu != 0;
     }
 
   gcc_assert (cpu_index >= 0);
@@ -2698,6 +2699,42 @@
   gcc_assert (tune_index >= 0);
   rs6000_cpu = processor_target_table[tune_index].processor;
 
+  /* Pick defaults for SPE related control flags.  Do this early to make sure
+     that the TARGET_ macros are representative ASAP.  */
+  {
+    int spe_capable_cpu =
+      (rs6000_cpu == PROCESSOR_PPC8540
+       || rs6000_cpu == PROCESSOR_PPC8548);
+
+    if (!global_options_set.x_rs6000_spe_abi)
+      rs6000_spe_abi = spe_capable_cpu;
+
+    if (!global_options_set.x_rs6000_spe)
+      rs6000_spe = spe_capable_cpu;
+
+    if (!global_options_set.x_rs6000_float_gprs)
+      rs6000_float_gprs =
+        (rs6000_cpu == PROCESSOR_PPC8540 ? 1
+         : rs6000_cpu == PROCESSOR_PPC8548 ? 2
+         : 0);
+  }
+
+  if (global_options_set.x_rs6000_spe_abi
+      && rs6000_spe_abi
+      && !TARGET_SPE_ABI)
+    error ("not configured for SPE ABI");
+
+  if (global_options_set.x_rs6000_spe
+      && rs6000_spe
+      && !TARGET_SPE)
+    error ("not configured for SPE instruction set");
+
+  if (main_target_opt != NULL
+      && ((main_target_opt->x_rs6000_spe_abi != rs6000_spe_abi)
+          || (main_target_opt->x_rs6000_spe != rs6000_spe)
+          || (main_target_opt->x_rs6000_float_gprs != rs6000_float_gprs)))
+    error ("target attribute or pragma changes SPE ABI");
+
   if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
       || rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64)
     {
@@ -2933,35 +2970,44 @@
   SUB3TARGET_OVERRIDE_OPTIONS;
 #endif
 
-  if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC
-      || rs6000_cpu == PROCESSOR_PPCE500MC64)
+  /* For the E500 family of cores, reset the single/double FP flags to let us
+     check that they remain constant across attributes or pragmas.  Also,
+     clear a possible request for string instructions, not supported and which
+     we might have silently queried above for -Os. 
+
+     For other families, clear ISEL in case it was set implicitly.
+  */
+
+  switch (rs6000_cpu)
     {
-      /* The e500 and e500mc do not have string instructions, and we set
-	 MASK_STRING above when optimizing for size.  */
-      if ((target_flags & MASK_STRING) != 0)
-	target_flags = target_flags & ~MASK_STRING;
+    case PROCESSOR_PPC8540:
+    case PROCESSOR_PPC8548:
+    case PROCESSOR_PPCE500MC:
+    case PROCESSOR_PPCE500MC64:
+
+      rs6000_single_float = TARGET_E500_SINGLE || TARGET_E500_DOUBLE;
+      rs6000_double_float = TARGET_E500_DOUBLE;
+
+      target_flags &= ~MASK_STRING;
+
+      break;
+
+    default:
+
+      if (have_cpu && !(target_flags_explicit & MASK_ISEL))
+	target_flags &= ~MASK_ISEL;
+
+      break;
     }
-  else if (global_options_set.x_rs6000_cpu_index)
+
+  if (main_target_opt)
     {
-      /* For the powerpc-eabispe configuration, we set all these by
-	 default, so let's unset them if we manually set another
-	 CPU that is not the E500.  */
-      if (main_target_opt != NULL
-	  && ((main_target_opt->x_rs6000_spe_abi != rs6000_spe_abi)
-	      || (main_target_opt->x_rs6000_spe != rs6000_spe)
-	      || (main_target_opt->x_rs6000_float_gprs != rs6000_float_gprs)))
-	error ("target attribute or pragma changes SPE ABI");
-      else
-	{
-	  if (!global_options_set.x_rs6000_spe_abi)
-	    rs6000_spe_abi = 0;
-	  if (!global_options_set.x_rs6000_spe)
-	    rs6000_spe = 0;
-	  if (!global_options_set.x_rs6000_float_gprs)
-	    rs6000_float_gprs = 0;
-	}
-      if (!(target_flags_explicit & MASK_ISEL))
-	target_flags &= ~MASK_ISEL;
+      if (main_target_opt->x_rs6000_single_float != rs6000_single_float)
+	error ("target attribute or pragma changes single precision floating "
+	       "point");
+      if (main_target_opt->x_rs6000_double_float != rs6000_double_float)
+	error ("target attribute or pragma changes double precision floating "
+	       "point");
     }
 
   /* Detect invalid option combinations with E500.  */
@@ -3188,6 +3234,7 @@
 	break;
 
       case PROCESSOR_PPC8540:
+      case PROCESSOR_PPC8548:
 	rs6000_cost = &ppc8540_cost;
 	break;
 
@@ -3260,26 +3307,6 @@
       && rs6000_single_float == 0 && rs6000_double_float == 0)
     rs6000_single_float = rs6000_double_float = 1;
 
-  /* Reset single and double FP flags if target is E500. */
-  if (TARGET_E500) 
-  {
-    rs6000_single_float = rs6000_double_float = 0;
-    if (TARGET_E500_SINGLE)
-      rs6000_single_float = 1; 
-    if (TARGET_E500_DOUBLE)
-      rs6000_single_float = rs6000_double_float = 1;
-  }
-
-  if (main_target_opt)
-    {
-      if (main_target_opt->x_rs6000_single_float != rs6000_single_float)
-	error ("target attribute or pragma changes single precision floating "
-	       "point");
-      if (main_target_opt->x_rs6000_double_float != rs6000_double_float)
-	error ("target attribute or pragma changes double precision floating "
-	       "point");
-    }
-
   /* If not explicitly specified via option, decide whether to generate indexed
      load/store instructions.  */
   if (TARGET_AVOID_XFORM == -1)
@@ -23126,6 +23153,7 @@
   case CPU_PPC750:
   case CPU_PPC7400:
   case CPU_PPC8540:
+  case CPU_PPC8548:
   case CPU_CELL:
   case CPU_PPCE300C2:
   case CPU_PPCE300C3:
@@ -23156,11 +23184,18 @@
 static int
 rs6000_use_sched_lookahead (void)
 {
-  if (rs6000_cpu_attr == CPU_PPC8540)
-    return 4;
-  if (rs6000_cpu_attr == CPU_CELL)
-    return (reload_completed ? 8 : 0);
-  return 0;
+  switch (rs6000_cpu_attr)
+    {
+    case CPU_PPC8540:
+    case CPU_PPC8548:
+      return 4;
+
+    case CPU_CELL:
+      return (reload_completed ? 8 : 0);
+
+    default:
+      return 0;
+    }
 }
 
 /* We are choosing insn from the ready queue.  Return nonzero if INSN can be chosen.  */
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 187316)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -457,7 +457,6 @@
 
 #define TARGET_SPE_ABI 0
 #define TARGET_SPE 0
-#define TARGET_E500 0
 #define TARGET_ISEL64 (TARGET_ISEL && TARGET_POWERPC64)
 #define TARGET_FPRS 1
 #define TARGET_E500_SINGLE 0
@@ -500,11 +499,11 @@
 				      || TARGET_ALTIVEC			 \
 				      || TARGET_VSX)))
 
+/* E500 cores only support plain "sync", not lwsync.  */
+#define TARGET_NO_LWSYNC (rs6000_cpu == PROCESSOR_PPC8540 \
+			  || rs6000_cpu == PROCESSOR_PPC8548)
 
 
-/* E500 processors only support plain "sync", not lwsync.  */
-#define TARGET_NO_LWSYNC TARGET_E500
-
 /* Which machine supports the various reciprocal estimate instructions.  */
 #define TARGET_FRES	(TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT \
 			 && TARGET_FPRS && TARGET_SINGLE_FLOAT)
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 187316)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -165,7 +165,7 @@
 ;; Processor type -- this attribute must exactly match the processor_type
 ;; enumeration in rs6000.h.
 
-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,power4,power5,power6,power7,cell,ppca2,titan"
+(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppc8548,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,power4,power5,power6,power7,cell,ppca2,titan"
   (const (symbol_ref "rs6000_cpu_attr")))
 
 
Index: gcc/config/rs6000/eabispe.h
===================================================================
--- gcc/config/rs6000/eabispe.h	(revision 187316)
+++ gcc/config/rs6000/eabispe.h	(working copy)
@@ -21,21 +21,8 @@
    <http://www.gnu.org/licenses/>.  */
 
 #undef  TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_EABI	\
-  | MASK_STRICT_ALIGN)
+#define TARGET_DEFAULT \
+  (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_STRICT_ALIGN | MASK_EABI)
 
-#undef  SUBSUBTARGET_OVERRIDE_OPTIONS
-#define SUBSUBTARGET_OVERRIDE_OPTIONS \
-  if (!global_options_set.x_rs6000_cpu_index) \
-    rs6000_cpu = PROCESSOR_PPC8540; \
-  if (!global_options_set.x_rs6000_spe_abi) \
-    rs6000_spe_abi = 1; \
-  if (!global_options_set.x_rs6000_float_gprs) \
-    rs6000_float_gprs = 1; \
-  if (!global_options_set.x_rs6000_spe) \
-    rs6000_spe = 1; \
-  if (target_flags & MASK_64BIT) \
-    error ("-m64 not supported in this configuration")
-
 #undef  ASM_DEFAULT_SPEC
 #define	ASM_DEFAULT_SPEC "-mppc -mspe -me500"
Index: gcc/config/rs6000/rs6000-cpus.def
===================================================================
--- gcc/config/rs6000/rs6000-cpus.def	(revision 187316)
+++ gcc/config/rs6000/rs6000-cpus.def	(working copy)
@@ -76,8 +76,7 @@
 RS6000_CPU ("823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT)
 RS6000_CPU ("8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
 	    | MASK_ISEL)
-/* 8548 has a dummy entry for now.  */
-RS6000_CPU ("8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
+RS6000_CPU ("8548", PROCESSOR_PPC8548, POWERPC_BASE_MASK | MASK_STRICT_ALIGN
 	    | MASK_ISEL)
 RS6000_CPU ("a2", PROCESSOR_PPCA2,
 	    POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_POPCNTB
Index: gcc/config/rs6000/e500.h
===================================================================
--- gcc/config/rs6000/e500.h	(revision 187316)
+++ gcc/config/rs6000/e500.h	(working copy)
@@ -19,7 +19,6 @@
 
 #undef TARGET_SPE_ABI
 #undef TARGET_SPE
-#undef TARGET_E500
 #undef TARGET_FPRS
 #undef TARGET_E500_SINGLE
 #undef TARGET_E500_DOUBLE
@@ -27,21 +26,20 @@
 
 #define TARGET_SPE_ABI rs6000_spe_abi
 #define TARGET_SPE rs6000_spe
-#define TARGET_E500 (rs6000_cpu == PROCESSOR_PPC8540)
 #define TARGET_FPRS (rs6000_float_gprs == 0)
 #define TARGET_E500_SINGLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 1)
 #define TARGET_E500_DOUBLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 2)
 #define CHECK_E500_OPTIONS						\
   do {									\
-    if (TARGET_E500 || TARGET_SPE || TARGET_SPE_ABI			\
+    if (TARGET_SPE || TARGET_SPE_ABI					\
 	|| TARGET_E500_SINGLE || TARGET_E500_DOUBLE)			\
       {									\
 	if (TARGET_ALTIVEC)						\
-	  error ("AltiVec and E500 instructions cannot coexist");	\
+	  error ("AltiVec and SPE instructions cannot coexist");	\
 	if (TARGET_VSX)							\
-	  error ("VSX and E500 instructions cannot coexist");		\
+	  error ("VSX and SPE instructions cannot coexist");		\
 	if (TARGET_64BIT)						\
-	  error ("64-bit E500 not supported");				\
+	  error ("64-bit SPE not supported");				\
 	if (TARGET_HARD_FLOAT && TARGET_FPRS)				\
 	  error ("E500 and FPRs not supported");			\
       }									\
Index: gcc/config/rs6000/rs6000-opts.h
===================================================================
--- gcc/config/rs6000/rs6000-opts.h	(revision 187316)
+++ gcc/config/rs6000/rs6000-opts.h	(working copy)
@@ -49,6 +49,7 @@
    PROCESSOR_PPC7400,
    PROCESSOR_PPC7450,
    PROCESSOR_PPC8540,
+   PROCESSOR_PPC8548,
    PROCESSOR_PPCE300C2,
    PROCESSOR_PPCE300C3,
    PROCESSOR_PPCE500MC,
Index: gcc/config/rs6000/e500-double.h
===================================================================
--- gcc/config/rs6000/e500-double.h	(revision 187316)
+++ gcc/config/rs6000/e500-double.h	(working copy)
@@ -1,24 +0,0 @@
-/* Target definitions for E500 with double precision FP.
-   Copyright (C) 2004, 2006, 2007, 2011 Free Software Foundation, Inc.
-   Contributed by Aldy Hernandez (aldyh@redhat.com).
-
-   This file is part of GCC.
-
-   GCC is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published
-   by the Free Software Foundation; either version 3, or (at your
-   option) any later version.
-
-   GCC is distributed in the hope that it will be useful, but WITHOUT
-   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
-   License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING3.  If not see
-   <http://www.gnu.org/licenses/>.  */
-
-#undef  SUB3TARGET_OVERRIDE_OPTIONS
-#define SUB3TARGET_OVERRIDE_OPTIONS \
-  if (!global_options_set.x_rs6000_float_gprs) \
-    rs6000_float_gprs = 2;
Index: gcc/config/rs6000/vxworks.h
===================================================================
--- gcc/config/rs6000/vxworks.h	(revision 187316)
+++ gcc/config/rs6000/vxworks.h	(working copy)
@@ -122,19 +122,8 @@
 
 #undef  ABI_STACK_BOUNDARY
 
-/* Make -mcpu=8540 imply SPE.  ISEL is automatically enabled, the
-   others must be done by hand.  Handle -mrtp.  Disable -fPIC
-   for -mrtp - the VxWorks PIC model is not compatible with it.  */
 #undef SUBSUBTARGET_OVERRIDE_OPTIONS
 #define SUBSUBTARGET_OVERRIDE_OPTIONS		\
-  do {						\
-    if (TARGET_E500)				\
-      {						\
-	rs6000_spe = 1;				\
-	rs6000_spe_abi = 1;			\
-	rs6000_float_gprs = 1;			\
-      }						\
-						\
   if (!global_options_set.x_g_switch_value)	\
     g_switch_value = SDATA_DEFAULT_SIZE;	\
   VXWORKS_OVERRIDE_OPTIONS;			\

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-15 13:47     ` Olivier Hainque
@ 2012-05-16  1:11       ` David Edelsohn
  2012-05-16  9:26         ` Olivier Hainque
  0 siblings, 1 reply; 18+ messages in thread
From: David Edelsohn @ 2012-05-16  1:11 UTC (permalink / raw)
  To: Olivier Hainque; +Cc: GCC Patches

On Tue, May 15, 2012 at 9:47 AM, Olivier Hainque <hainque@adacore.com> wrote:

>        config/rs6000:
>
>        * rs6000-opts.h (enum processor_type): Add PROCESSOR_PPC8548.
>        * rs6000-cpus.def: Reference it for cpu="8548".
>        * rs6000.md (cpu attribute definition): Add ppc8548.
>        * 8540.md: indicate that the units/patterns apply to ppc8548 as well.
>
>        * rs6000.c (rs6000_option_override_internal): Rename default_cpu into
>        implicit_cpu, conveying what --with-cpu was passed at configure time.
>        Treat implicit_cpu as have_cpu. Pick defaults for SPE related flags,
>        check that what is queried is supported by the selected configuration.
>        Rework the single/double_float and MASK_STRING resets to hit for all
>        the E500 cores (854x + E500MC variants). Select the ppc8540 costs for
>        PROCESSOR_PPC8548 as well.
>        (rs6000_issue_rate): case CPU_PPC8548 together with CPU_PPC8540.
>        (rs6000_use_sched_lookahead): Likewise, rewriting function as a case
>        statement instead of a sequence of ifs.
>
>        * rs6000.h (TARGET_E500): Remove.
>        (TARGET_NO_LWSYNC): Adjust accordingly.
>        * e500.h (TARGET_E500): Remove.
>        (CHECK_E500_OPTIONS): Adjust accordingly.
>        * eabispe.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Remove.
>        (TARGET_DEFAULT): Reformat definition to match the one in linuxspe.h.
>        * linuxspe.h: Likewise.
>        * vxworks.h: Remove bogus TARGET_E500 overrides and superfluous comments.
>        * e500-double.h: Remove.
>
>        gcc:
>
>        * config.gcc (pick a default with_cpu): For powerpc*-*-*spe*,
>        default to with_cpu=8548 if --enable-e500-double, and to 8540
>        otherwise.
>        (set misc flags section): For powerpc*|rs6000*, remove inclusion
>        of e500-double.h for --enable-e500-double.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-16  1:11       ` David Edelsohn
@ 2012-05-16  9:26         ` Olivier Hainque
  0 siblings, 0 replies; 18+ messages in thread
From: Olivier Hainque @ 2012-05-16  9:26 UTC (permalink / raw)
  To: David Edelsohn; +Cc: Olivier Hainque, GCC Patches


On May 16, 2012, at 03:10 , David Edelsohn wrote:
> Okay.

 revision 187581. Thanks!

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: remove TARGET_E500 and factorize SPE defaults computation in powerpc ports
  2012-05-07 13:57 remove TARGET_E500 and factorize SPE defaults computation in powerpc ports Olivier Hainque
  2012-05-07 15:23 ` Olivier Hainque
  2012-05-07 16:11 ` remove TARGET_E500 and factorize SPE defaults computation in powerpc ports Joseph S. Myers
@ 2012-05-16 12:33 ` Sebastian Huber
  2 siblings, 0 replies; 18+ messages in thread
From: Sebastian Huber @ 2012-05-16 12:33 UTC (permalink / raw)
  To: gcc-patches

Hello,

since you touch the SPE area would you mind looking at this PR:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47856

-- 
Sebastian Huber, embedded brains GmbH

Address : Obere Lagerstr. 30, D-82178 Puchheim, Germany
Phone   : +49 89 18 90 80 79-6
Fax     : +49 89 18 90 80 79-9
E-Mail  : sebastian.huber@embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RS6000] save/restore reg tidy
  2012-05-08 10:33   ` [RS6000] Fix PR53271 " Alan Modra
  2012-05-08 14:16     ` David Edelsohn
@ 2012-05-21  2:48     ` Alan Modra
  2012-05-21  5:14       ` [RS6000] out-of-line save/restore conditions Alan Modra
  2012-05-21 15:33       ` [RS6000] save/restore reg tidy David Edelsohn
  1 sibling, 2 replies; 18+ messages in thread
From: Alan Modra @ 2012-05-21  2:48 UTC (permalink / raw)
  To: David Edelsohn, gcc-patches

On Tue, May 08, 2012 at 08:02:39PM +0930, Alan Modra wrote:
> I also make use of gen_frame_store and siblings that I invented for
> generating the eh info, elsewhere in rs6000.c where doing so is
> blindingly obvious.  We could probably use them in other places too,
> but I'll leave that for later.

Like so.  The part that isn't completely obvious is removing calls to
emit_move_insn, which can transform the rtl (rs6000_emit_move).
However, we're past reload, the insns emitted are always one set
involving a hard reg and mem, and we don't want any addressing mode
subsititions going on that avoid rs6000_emit_prologue tracking of r0,
r11 and r12 usage. 

This patch also fixes a couple of places that call df_regs_ever_live_p
without checking call_used_regs to test for global asm regs.  Not
serious bugs as they just result in larger stack frames.

Bootstrapped and regression tested powerpc-linux.  OK to apply?

	* config/rs6000/rs6000.c (save_reg_p): New function.
	(first_reg_to_save, first_fp_reg_to_save): Use it here.
	(first_altivec_reg_to_save, restore_saved_cr): Likewise.
	(emit_frame_save): Use gen_frame_store.
	(gen_frame_mem_offset): Correct SPE condition requiring reg+reg.
	(rs6000_emit_prologue): Use save_reg_p.  Use gen_frame_store for
	vrsave and toc.
	(rs6000_emit_epilogue): Use save_reg_p.  Use gen_frame_load for
	vrsave, toc, gp and fp restores.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 187699)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -17236,6 +17079,12 @@
 /* This page contains routines that are used to determine what the
    function prologue and epilogue code will do and write them out.  */
 
+static inline bool
+save_reg_p (int r)
+{
+  return !call_used_regs[r] && df_regs_ever_live_p (r);
+}
+
 /* Return the first fixed-point register that is required to be
    saved. 32 if none.  */
 
@@ -17246,14 +17095,16 @@
 
   /* Find lowest numbered live register.  */
   for (first_reg = 13; first_reg <= 31; first_reg++)
-    if (df_regs_ever_live_p (first_reg)
-	&& (! call_used_regs[first_reg]
-	    || (first_reg == RS6000_PIC_OFFSET_TABLE_REGNUM
-		&& ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
-		    || (DEFAULT_ABI == ABI_DARWIN && flag_pic)
-		    || (TARGET_TOC && TARGET_MINIMAL_TOC)))))
+    if (save_reg_p (first_reg))
       break;
 
+  if (first_reg > RS6000_PIC_OFFSET_TABLE_REGNUM
+      && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
+	  || (DEFAULT_ABI == ABI_DARWIN && flag_pic)
+	  || (TARGET_TOC && TARGET_MINIMAL_TOC))
+      && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM))
+    first_reg = RS6000_PIC_OFFSET_TABLE_REGNUM;
+
 #if TARGET_MACHO
   if (flag_pic
       && crtl->uses_pic_offset_table
@@ -17273,7 +17124,7 @@
 
   /* Find lowest numbered live register.  */
   for (first_reg = 14 + 32; first_reg <= 63; first_reg++)
-    if (df_regs_ever_live_p (first_reg))
+    if (save_reg_p (first_reg))
       break;
 
   return first_reg;
@@ -17299,7 +17150,7 @@
 
   /* Find lowest numbered live register.  */
   for (i = FIRST_ALTIVEC_REGNO + 20; i <= LAST_ALTIVEC_REGNO; ++i)
-    if (df_regs_ever_live_p (i))
+    if (save_reg_p (i))
       break;
 
   return i;
@@ -18995,7 +18904,7 @@
 emit_frame_save (rtx frame_reg, enum machine_mode mode,
 		 unsigned int regno, int offset, HOST_WIDE_INT frame_reg_to_sp)
 {
-  rtx reg, insn, mem, addr;
+  rtx reg, insn;
 
   /* Some cases that need register indexed addressing.  */
   gcc_checking_assert (!((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
@@ -19006,9 +18915,7 @@
 			     && !SPE_CONST_OFFSET_OK (offset))));
 
   reg = gen_rtx_REG (mode, regno);
-  addr = gen_rtx_PLUS (Pmode, frame_reg, GEN_INT (offset));
-  mem = gen_frame_mem (mode, addr);
-  insn = emit_move_insn (mem, reg);
+  insn = emit_insn (gen_frame_store (reg, frame_reg, offset));
   return rs6000_frame_related (insn, frame_reg, frame_reg_to_sp,
 			       NULL_RTX, NULL_RTX);
 }
@@ -19023,7 +18930,7 @@
 
   int_rtx = GEN_INT (offset);
 
-  if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
+  if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode) && !SPE_CONST_OFFSET_OK (offset))
       || (TARGET_E500_DOUBLE && mode == DFmode))
     {
       offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH);
@@ -19652,8 +19559,7 @@
     {
       int i;
       for (i = 0; i < 64 - info->first_fp_reg_save; i++)
-	if (df_regs_ever_live_p (info->first_fp_reg_save + i)
-	    && ! call_used_regs[info->first_fp_reg_save + i])
+	if (save_reg_p (info->first_fp_reg_save + i))
 	  emit_frame_save (frame_reg_rtx,
 			   (TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
 			    ? DFmode : SFmode),
@@ -20103,7 +20009,7 @@
       && TARGET_ALTIVEC_VRSAVE
       && info->vrsave_mask != 0)
     {
-      rtx reg, mem, vrsave;
+      rtx reg, vrsave;
       int offset;
       int save_regno;
 
@@ -20130,10 +20036,7 @@
 
       /* Save VRSAVE.  */
       offset = info->vrsave_save_offset + frame_off;
-      mem = gen_frame_mem (SImode,
-			   gen_rtx_PLUS (Pmode, frame_reg_rtx,
-					 GEN_INT (offset)));
-      insn = emit_move_insn (mem, reg);
+      insn = emit_insn (gen_frame_store (reg, frame_reg_rtx, offset));
 
       /* Include the registers in the mask.  */
       emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
@@ -20214,9 +20115,8 @@
      linux-unwind.h frob_update_context.  */
   if (rs6000_save_toc_in_prologue_p ())
     {
-      rtx addr = gen_rtx_PLUS (Pmode, sp_reg_rtx, GEN_INT (5 * reg_size));
-      rtx mem = gen_frame_mem (reg_mode, addr);
-      emit_move_insn (mem, gen_rtx_REG (reg_mode, TOC_REGNUM));
+      rtx reg = gen_rtx_REG (reg_mode, TOC_REGNUM);
+      emit_insn (gen_frame_store (reg, sp_reg_rtx, 5 * reg_size));
     }
 }
 
@@ -20314,7 +20233,7 @@
   if (using_mfcr_multiple)
     {
       for (i = 0; i < 8; i++)
-	if (df_regs_ever_live_p (CR0_REGNO+i) && ! call_used_regs[CR0_REGNO+i])
+	if (save_reg_p (CR0_REGNO + i))
 	  count++;
       gcc_assert (count);
     }
@@ -20328,13 +20247,13 @@
 
       ndx = 0;
       for (i = 0; i < 8; i++)
-	if (df_regs_ever_live_p (CR0_REGNO+i) && ! call_used_regs[CR0_REGNO+i])
+	if (save_reg_p (CR0_REGNO + i))
 	  {
 	    rtvec r = rtvec_alloc (2);
 	    RTVEC_ELT (r, 0) = reg;
 	    RTVEC_ELT (r, 1) = GEN_INT (1 << (7-i));
 	    RTVEC_ELT (p, ndx) =
-	      gen_rtx_SET (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO+i),
+	      gen_rtx_SET (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO + i),
 			   gen_rtx_UNSPEC (CCmode, r, UNSPEC_MOVESI_TO_CR));
 	    ndx++;
 	  }
@@ -20343,8 +20262,8 @@
     }
   else
     for (i = 0; i < 8; i++)
-      if (df_regs_ever_live_p (CR0_REGNO+i) && ! call_used_regs[CR0_REGNO+i])
-	emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode, CR0_REGNO+i),
+      if (save_reg_p (CR0_REGNO + i))
+	emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode, CR0_REGNO + i),
 					reg));
 
   if (!exit_func && (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap))
@@ -20677,7 +20596,7 @@
 	  || (DEFAULT_ABI != ABI_V4
 	      && offset_below_red_zone_p (info->vrsave_save_offset))))
     {
-      rtx addr, mem, reg;
+      rtx reg;
 
       if (frame_reg_rtx == sp_reg_rtx)
 	{
@@ -20692,11 +20611,9 @@
 	    frame_reg_rtx = hard_frame_pointer_rtx;
 	}
 
-      addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-			   GEN_INT (info->vrsave_save_offset + frame_off));
-      mem = gen_frame_mem (SImode, addr);
       reg = gen_rtx_REG (SImode, 12);
-      emit_move_insn (reg, mem);
+      emit_insn (gen_frame_load (reg, frame_reg_rtx,
+				 info->vrsave_save_offset + frame_off));
 
       emit_insn (generate_set_vrsave (reg, info, 1));
     }
@@ -20874,13 +20791,11 @@
       && (DEFAULT_ABI == ABI_V4
 	  || !offset_below_red_zone_p (info->vrsave_save_offset)))
     {
-      rtx addr, mem, reg;
+      rtx reg;
 
-      addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-			   GEN_INT (info->vrsave_save_offset + frame_off));
-      mem = gen_frame_mem (SImode, addr);
       reg = gen_rtx_REG (SImode, 12);
-      emit_move_insn (reg, mem);
+      emit_insn (gen_frame_load (reg, frame_reg_rtx,
+				 info->vrsave_save_offset + frame_off));
 
       emit_insn (generate_set_vrsave (reg, info, 1));
     }
@@ -20934,11 +20849,9 @@
 
       if (TARGET_AIX)
 	{
-	  rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				   GEN_INT (frame_off + 5 * reg_size));
-	  rtx mem = gen_frame_mem (reg_mode, addr);
-
-	  emit_move_insn (gen_rtx_REG (reg_mode, 2), mem);
+	  rtx reg = gen_rtx_REG (reg_mode, 2);
+	  emit_insn (gen_frame_load (reg, frame_reg_rtx,
+				     frame_off + 5 * reg_size));
 	}
 
       for (i = 0; ; ++i)
@@ -20949,6 +20862,7 @@
 	  if (regno == INVALID_REGNUM)
 	    break;
 
+	  /* Note: possible use of r0 here to address SPE regs.  */
 	  mem = gen_frame_mem_offset (reg_mode, frame_reg_rtx,
 				      info->ehrd_offset + frame_off
 				      + reg_size * (int) i);
@@ -21067,16 +20981,10 @@
     {
       for (i = 0; i < 32 - info->first_gp_reg_save; i++)
 	if (rs6000_reg_live_or_pic_offset_p (info->first_gp_reg_save + i))
-	  {
-	    rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-				     GEN_INT (info->gp_save_offset
-					      + frame_off
-					      + reg_size * i));
-	    rtx mem = gen_frame_mem (reg_mode, addr);
-	    rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
-
-	    emit_move_insn (reg, mem);
-	  }
+	  emit_insn (gen_frame_load
+		     (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
+		      frame_reg_rtx,
+		      info->gp_save_offset + frame_off + reg_size * i));
     }
 
   if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
@@ -21139,21 +21047,13 @@
   /* Restore fpr's if we need to do it without calling a function.  */
   if (restoring_FPRs_inline)
     for (i = 0; i < 64 - info->first_fp_reg_save; i++)
-      if ((df_regs_ever_live_p (info->first_fp_reg_save + i)
-	   && !call_used_regs[info->first_fp_reg_save + i]))
+      if (save_reg_p (info->first_fp_reg_save + i))
 	{
-	  rtx addr, mem, reg;
-	  addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
-			       GEN_INT (info->fp_save_offset
-					+ frame_off
-					+ 8 * i));
-	  mem = gen_frame_mem ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
-				? DFmode : SFmode), addr);
-	  reg = gen_rtx_REG ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
-			      ? DFmode : SFmode),
-			     info->first_fp_reg_save + i);
-
-	  emit_move_insn (reg, mem);
+	  rtx reg = gen_rtx_REG ((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
+				  ? DFmode : SFmode),
+				 info->first_fp_reg_save + i);
+	  emit_insn (gen_frame_load (reg, frame_reg_rtx,
+				     info->fp_save_offset + frame_off + 8 * i));
 	  if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
 	    cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
 	}

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RS6000] out-of-line save/restore conditions
  2012-05-21  2:48     ` [RS6000] save/restore reg tidy Alan Modra
@ 2012-05-21  5:14       ` Alan Modra
  2012-05-21 15:36         ` David Edelsohn
  2012-05-21 15:33       ` [RS6000] save/restore reg tidy David Edelsohn
  1 sibling, 1 reply; 18+ messages in thread
From: Alan Modra @ 2012-05-21  5:14 UTC (permalink / raw)
  To: David Edelsohn, gcc-patches

Currently, powerpc-linux gcc -Os -mno-multiple uses out-of-linux gpr
save and restore functions when saving/restoring just one gpr.  That's
quite silly since the function call requires more instructions and is
slower than an inline save/restore.  The only case where it might win
is when no fprs are restored and the restore function can tear down
the frame and exit (also loading up lr on ppc64).  I guess that's how
GP_SAVE_INLINE came to be like it is, ie. it's optimised for the
common case using ldm in the prologue and no fprs.  Still, it isn't
difficult to choose the best combination in all cases, but it does
mean different logic is needed for restores.  I could have implemented
GP_RESTORE_INLINE and FP_RESORE_INLINE macros but it seemed simpler to
just move everything into the one place the macros are invoked.  AIX
and Darwin register cutoff doesn't change with this patch.

This patch also enables out-of-line restores in cases that were
previously disabled due to using inline saves.

Bootstrapped and regression tested powerpc-linux.  OK to apply?

	* aix.h (FP_SAVE_INLINE, GP_SAVE_INLINE): Delete.
	* darwin.h (FP_SAVE_INLINE, GP_SAVE_INLINE): Delete.
	* sysv4.h (FP_SAVE_INLINE, GP_SAVE_INLINE, V_SAVE_INLINE): Delete.
	* config/rs6000/rs6000.c (V_SAVE_INLINE): Delete.
	(rs6000_savres_strategy): Reimplement GP/FP/V_SAVE_INLINE logic.
	For ELF targets, use out-of-line restores for -Os and any number
	of regs if the restore exits, and out-of-line gp save for two or
	more regs.  Use save_reg_p to test for holes in reg restore set.
	Replace "#if" with "if".

Index: gcc/config/rs6000/aix.h
===================================================================
--- gcc/config/rs6000/aix.h	(revision 187699)
+++ gcc/config/rs6000/aix.h	(working copy)
@@ -207,11 +207,6 @@
   { "link_syscalls",            LINK_SYSCALLS_SPEC },			\
   { "link_libg",                LINK_LIBG_SPEC }
 
-/* Define cutoff for using external functions to save floating point.  */
-#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63)
-/* And similarly for general purpose registers.  */
-#define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32)
-
 #define PROFILE_HOOK(LABEL)   output_profile_hook (LABEL)
 
 /* No version of AIX fully supports AltiVec or 64-bit instructions in
Index: gcc/config/rs6000/darwin.h
===================================================================
--- gcc/config/rs6000/darwin.h	(revision 187699)
+++ gcc/config/rs6000/darwin.h	(working copy)
@@ -173,16 +173,6 @@
   (RS6000_ALIGN (crtl->outgoing_args_size, 16)		\
    + (STACK_POINTER_OFFSET))
 
-/* Define cutoff for using out-of-line functions to save registers.
-   Currently on Darwin, we implement FP and GPR out-of-line-saves plus the
-   special routine for 'save everything'.  */
-
-#undef FP_SAVE_INLINE
-#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) > 60 && (FIRST_REG) < 64)
-
-#undef GP_SAVE_INLINE
-#define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) > 29 && (FIRST_REG) < 32)
-
 /* Darwin uses a function call if everything needs to be saved/restored.  */
 
 #undef WORLD_SAVE_P
Index: gcc/config/rs6000/sysv4.h
===================================================================
--- gcc/config/rs6000/sysv4.h	(revision 187699)
+++ gcc/config/rs6000/sysv4.h	(working copy)
@@ -243,19 +243,6 @@
 #define	BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN)
 #define	WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN)
 
-/* Define cutoff for using external functions to save floating point.
-   When optimizing for size, use external functions when profitable.  */
-#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62			\
-				   || (FIRST_REG) == 63			\
-				   || !optimize_size)
-
-/* And similarly for general purpose registers.  */
-#define GP_SAVE_INLINE(FIRST_REG) (!optimize_size)
-
-/* And vector registers.  */
-#define V_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == LAST_ALTIVEC_REGNO	\
-				  || !optimize_size)
-
 /* Put jump tables in read-only memory, rather than in .text.  */
 #define JUMP_TABLES_IN_TEXT_SECTION 0
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 187699)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -17443,10 +17294,6 @@
   REST_INLINE_VRS = 0x200
 };
 
-#ifndef V_SAVE_INLINE
-#define V_SAVE_INLINE(FIRST_REG) 1
-#endif
-
 static int
 rs6000_savres_strategy (rs6000_stack_t *info,
 			bool using_static_chain_p)
@@ -17468,7 +17315,6 @@
 		 | SAVE_INLINE_VRS | REST_INLINE_VRS);
 
   if (info->first_fp_reg_save == 64
-      || FP_SAVE_INLINE (info->first_fp_reg_save)
       /* The out-of-line FP routines use double-precision stores;
 	 we can't use those routines if we don't have such stores.  */
       || (TARGET_HARD_FLOAT && !TARGET_DOUBLE_FLOAT)
@@ -17476,26 +17322,80 @@
     strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
 
   if (info->first_gp_reg_save == 32
-      || GP_SAVE_INLINE (info->first_gp_reg_save)
       || (!(strategy & SAVRES_MULTIPLE)
 	  && global_regs_p (info->first_gp_reg_save, 32)))
     strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
 
   if (info->first_altivec_reg_save == LAST_ALTIVEC_REGNO + 1
-      || V_SAVE_INLINE (info->first_altivec_reg_save)
       || global_regs_p (info->first_altivec_reg_save, LAST_ALTIVEC_REGNO + 1))
     strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
 
+  /* Define cutoff for using out-of-line functions to save registers.  */
+  if (DEFAULT_ABI == ABI_V4 || TARGET_ELF)
+    {
+      if (!optimize_size)
+	{
+	  strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
+	  strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+	  strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
+	}
+      else
+	{
+	  /* Prefer out-of-line restore if it will exit.  */
+	  if (info->first_fp_reg_save > 61)
+	    strategy |= SAVE_INLINE_FPRS;
+	  if (info->first_gp_reg_save > 29)
+	    {
+	      if (info->first_fp_reg_save == 64)
+		strategy |= SAVE_INLINE_GPRS;
+	      else
+		strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+	    }
+	  if (info->first_altivec_reg_save == LAST_ALTIVEC_REGNO)
+	    strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
+	}
+    }
+  else if (DEFAULT_ABI == ABI_DARWIN)
+    {
+      if (info->first_fp_reg_save > 60)
+	strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
+      if (info->first_gp_reg_save > 29)
+	strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+      strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
+    }
+  else
+    {
+      gcc_checking_assert (DEFAULT_ABI == ABI_AIX);
+      if (info->first_fp_reg_save > 61)
+	strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
+      strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+      strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
+    }
+
   /* Don't bother to try to save things out-of-line if r11 is occupied
      by the static chain.  It would require too much fiddling and the
      static chain is rarely used anyway.  FPRs are saved w.r.t the stack
      pointer on Darwin, and AIX uses r1 or r12.  */
   if (using_static_chain_p && DEFAULT_ABI != ABI_AIX)
-    strategy |= ((DEFAULT_ABI == ABI_DARWIN
-		  ? 0 : SAVE_INLINE_FPRS | REST_INLINE_FPRS)
+    strategy |= ((DEFAULT_ABI == ABI_DARWIN ? 0 : SAVE_INLINE_FPRS)
 		 | SAVE_INLINE_GPRS
 		 | SAVE_INLINE_VRS | REST_INLINE_VRS);
 
+  /* We can only use the out-of-line routines to restore if we've
+     saved all the registers from first_fp_reg_save in the prologue.
+     Otherwise, we risk loading garbage.  */
+  if ((strategy & (SAVE_INLINE_FPRS | REST_INLINE_FPRS)) == SAVE_INLINE_FPRS)
+    {
+      int i;
+
+      for (i = info->first_fp_reg_save; i < 64; i++)
+	if (!save_reg_p (i))
+	  {
+	    strategy |= REST_INLINE_FPRS;
+	    break;
+	  }
+    }
+
   /* If we are going to use store multiple, then don't even bother
      with the out-of-line routines, since the store-multiple
      instruction will always be smaller.  */
@@ -17525,13 +17426,6 @@
 	  || info->first_fp_reg_save != 64))
     strategy |= REST_INLINE_GPRS;
 
-  /* We can only use load multiple or the out-of-line routines to
-     restore if we've used store multiple or out-of-line routines
-     in the prologue, i.e. if we've saved all the registers from
-     first_gp_reg_save.  Otherwise, we risk loading garbage.  */
-  if ((strategy & (SAVE_INLINE_GPRS | SAVRES_MULTIPLE)) == SAVE_INLINE_GPRS)
-    strategy |= REST_INLINE_GPRS;
-
   /* Saving CR interferes with the exit routines used on the SPE, so
      just punt here.  */
   if (TARGET_SPE_ABI
@@ -17539,19 +17433,34 @@
       && info->cr_save_p)
     strategy |= REST_INLINE_GPRS;
 
-#if defined (POWERPC_LINUX) || defined (POWERPC_FREEBSD)
-  if (TARGET_64BIT)
+  /* We can only use load multiple or the out-of-line routines to
+     restore if we've used store multiple or out-of-line routines
+     in the prologue, i.e. if we've saved all the registers from
+     first_gp_reg_save.  Otherwise, we risk loading garbage.  */
+  if ((strategy & (SAVE_INLINE_GPRS | REST_INLINE_GPRS | SAVRES_MULTIPLE))
+      == SAVE_INLINE_GPRS)
     {
+      int i;
+
+      for (i = info->first_gp_reg_save; i < 32; i++)
+	if (!save_reg_p (i))
+	  {
+	    strategy |= REST_INLINE_GPRS;
+	    break;
+	  }
+    }
+
+  if (TARGET_ELF && TARGET_64BIT)
+    {
       if (!(strategy & SAVE_INLINE_FPRS))
 	strategy |= SAVE_NOINLINE_FPRS_SAVES_LR;
       else if (!(strategy & SAVE_INLINE_GPRS)
 	       && info->first_fp_reg_save == 64)
 	strategy |= SAVE_NOINLINE_GPRS_SAVES_LR;
     }
-#else
-  if (TARGET_AIX && !(strategy & REST_INLINE_FPRS))
+  else if (TARGET_AIX && !(strategy & REST_INLINE_FPRS))
     strategy |= REST_NOINLINE_FPRS_DOESNT_RESTORE_LR;
-#endif
+
   if (TARGET_MACHO && !(strategy & SAVE_INLINE_FPRS))
     strategy |= SAVE_NOINLINE_FPRS_SAVES_LR;
 

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RS6000] save/restore reg tidy
  2012-05-21  2:48     ` [RS6000] save/restore reg tidy Alan Modra
  2012-05-21  5:14       ` [RS6000] out-of-line save/restore conditions Alan Modra
@ 2012-05-21 15:33       ` David Edelsohn
  1 sibling, 0 replies; 18+ messages in thread
From: David Edelsohn @ 2012-05-21 15:33 UTC (permalink / raw)
  To: Alan Modra; +Cc: GCC Patches

On Sun, May 20, 2012 at 10:48 PM, Alan Modra <amodra@gmail.com> wrote:
> On Tue, May 08, 2012 at 08:02:39PM +0930, Alan Modra wrote:
>> I also make use of gen_frame_store and siblings that I invented for
>> generating the eh info, elsewhere in rs6000.c where doing so is
>> blindingly obvious.  We could probably use them in other places too,
>> but I'll leave that for later.
>
> Like so.  The part that isn't completely obvious is removing calls to
> emit_move_insn, which can transform the rtl (rs6000_emit_move).
> However, we're past reload, the insns emitted are always one set
> involving a hard reg and mem, and we don't want any addressing mode
> subsititions going on that avoid rs6000_emit_prologue tracking of r0,
> r11 and r12 usage.
>
> This patch also fixes a couple of places that call df_regs_ever_live_p
> without checking call_used_regs to test for global asm regs.  Not
> serious bugs as they just result in larger stack frames.
>
> Bootstrapped and regression tested powerpc-linux.  OK to apply?
>
>        * config/rs6000/rs6000.c (save_reg_p): New function.
>        (first_reg_to_save, first_fp_reg_to_save): Use it here.
>        (first_altivec_reg_to_save, restore_saved_cr): Likewise.
>        (emit_frame_save): Use gen_frame_store.
>        (gen_frame_mem_offset): Correct SPE condition requiring reg+reg.
>        (rs6000_emit_prologue): Use save_reg_p.  Use gen_frame_store for
>        vrsave and toc.
>        (rs6000_emit_epilogue): Use save_reg_p.  Use gen_frame_load for
>        vrsave, toc, gp and fp restores.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RS6000] out-of-line save/restore conditions
  2012-05-21  5:14       ` [RS6000] out-of-line save/restore conditions Alan Modra
@ 2012-05-21 15:36         ` David Edelsohn
  0 siblings, 0 replies; 18+ messages in thread
From: David Edelsohn @ 2012-05-21 15:36 UTC (permalink / raw)
  To: Alan Modra; +Cc: GCC Patches

On Mon, May 21, 2012 at 1:14 AM, Alan Modra <amodra@gmail.com> wrote:
> Currently, powerpc-linux gcc -Os -mno-multiple uses out-of-line gpr
> save and restore functions when saving/restoring just one gpr.  That's
> quite silly since the function call requires more instructions and is
> slower than an inline save/restore.  The only case where it might win
> is when no fprs are restored and the restore function can tear down
> the frame and exit (also loading up lr on ppc64).  I guess that's how
> GP_SAVE_INLINE came to be like it is, ie. it's optimised for the
> common case using ldm in the prologue and no fprs.  Still, it isn't
> difficult to choose the best combination in all cases, but it does
> mean different logic is needed for restores.  I could have implemented
> GP_RESTORE_INLINE and FP_RESORE_INLINE macros but it seemed simpler to
> just move everything into the one place the macros are invoked.  AIX
> and Darwin register cutoff doesn't change with this patch.
>
> This patch also enables out-of-line restores in cases that were
> previously disabled due to using inline saves.
>
> Bootstrapped and regression tested powerpc-linux.  OK to apply?
>
>        * aix.h (FP_SAVE_INLINE, GP_SAVE_INLINE): Delete.
>        * darwin.h (FP_SAVE_INLINE, GP_SAVE_INLINE): Delete.
>        * sysv4.h (FP_SAVE_INLINE, GP_SAVE_INLINE, V_SAVE_INLINE): Delete.
>        * config/rs6000/rs6000.c (V_SAVE_INLINE): Delete.
>        (rs6000_savres_strategy): Reimplement GP/FP/V_SAVE_INLINE logic.
>        For ELF targets, use out-of-line restores for -Os and any number
>        of regs if the restore exits, and out-of-line gp save for two or
>        more regs.  Use save_reg_p to test for holes in reg restore set.
>        Replace "#if" with "if".

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2012-05-21 15:36 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-07 13:57 remove TARGET_E500 and factorize SPE defaults computation in powerpc ports Olivier Hainque
2012-05-07 15:23 ` Olivier Hainque
2012-05-08 10:33   ` [RS6000] Fix PR53271 " Alan Modra
2012-05-08 14:16     ` David Edelsohn
2012-05-21  2:48     ` [RS6000] save/restore reg tidy Alan Modra
2012-05-21  5:14       ` [RS6000] out-of-line save/restore conditions Alan Modra
2012-05-21 15:36         ` David Edelsohn
2012-05-21 15:33       ` [RS6000] save/restore reg tidy David Edelsohn
2012-05-07 16:11 ` remove TARGET_E500 and factorize SPE defaults computation in powerpc ports Joseph S. Myers
2012-05-07 17:00   ` David Edelsohn
2012-05-07 17:24     ` Olivier Hainque
2012-05-07 18:31       ` David Edelsohn
2012-05-07 19:27         ` Olivier Hainque
2012-05-07 20:54           ` Olivier Hainque
2012-05-15 13:47     ` Olivier Hainque
2012-05-16  1:11       ` David Edelsohn
2012-05-16  9:26         ` Olivier Hainque
2012-05-16 12:33 ` Sebastian Huber

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).