other/7114: ICE building strcoll.op from glibc-2.2.5

Alan Modra amodra@bigpond.net.au
Wed Jul 17 02:04:00 GMT 2002


On Wed, Jul 17, 2002 at 12:07:11AM -0700, Geoff Keating wrote:
> So, why don't we go back to the push/pop implementation, but this time
> do it properly?  We'd only need to push/pop in the (rare)
> nested-function case.

I wasn't aware that powerpc used that scheme previously, and therefore
was worried that some mcount implementation might peek at the stack.

Here we go.

	* config/rs6000/r6000.c (first_reg_to_save): Remove bogus
	adjustments to first_reg for profiling case.
	(output_function_profiler): Correct lr save slot for ABI_AIX_NODESC.
	Disable profiling for 64 bit code on both ABI_V4 and ABI_AIX_NODESC.
	Save static chain reg to sp + 12 on ABI_AIX_NODESC.
	* config/rs6000/sysv4.h (ASM_OUTPUT_REG_PUSH): Define.
	(ASM_OUTPUT_REG_POP): Define.
	* config/rs6000/linux64.h (ASM_OUTPUT_REG_PUSH): Undef.
	(ASM_OUTPUT_REG_POP): Undef.

Rationale:

	* config/rs6000/r6000.c (first_reg_to_save): Remove bogus
	adjustments to first_reg for profiling case.
first_reg_to_save doesn't need to do anything special for any of these
registers as profiling is done via PROFILE_HOOK when ABI_AIX or
ABI_DARWIN.  The normal register allocation code will set up
regs_ever_live for us.  We're also not trying to use a reg when ABI_V4.

	(output_function_profiler): Correct lr save slot for ABI_AIX_NODESC.
ABI_AIX_NODESC saves lr to sp + 8.  This change is perhaps a little
contentious as existing mcount implementations may take into account
the current ABI breakage.

	Disable profiling for 64 bit code on both ABI_V4 and ABI_AIX_NODESC.
The instructions emitted here are 32 bit ones.  Fix this with a later
patch.

	Save static chain reg to sp + 12 on ABI_AIX_NODESC.
We need to save it somewhere.  This seems a likely spot.

	* config/rs6000/sysv4.h (ASM_OUTPUT_REG_PUSH): Define.
	(ASM_OUTPUT_REG_POP): Define.
Code resurrected from prior to Mon Mar 15 22:45:25 1999 delta, but
with DEFAULT_ABI == ABI_V4 test added.


powerpc-linux bootstrap on mainline seems to be broken at the moment.

internal compiler error: Internal compiler error
 in tree_low_cst, at tree.c:3312

so I'm in the process of bootstrapping this one on the 3.1 branch.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

Index: gcc/config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.344
diff -u -p -r1.344 rs6000.c
--- gcc/config/rs6000/rs6000.c	16 Jul 2002 20:59:03 -0000	1.344
+++ gcc/config/rs6000/rs6000.c	17 Jul 2002 08:19:35 -0000
@@ -7356,53 +7356,6 @@ first_reg_to_save ()
 		    || (DEFAULT_ABI == ABI_DARWIN && flag_pic)))))
       break;
 
-  if (current_function_profile)
-    {
-      /* AIX must save/restore every register that contains a parameter
-	 before/after the .__mcount call plus an additional register
-	 for the static chain, if needed; use registers from 30 down to 22
-	 to do this.  */
-      if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
-	{
-	  int last_parm_reg, profile_first_reg;
-
-	  /* Figure out last used parameter register.  The proper thing
-	     to do is to walk incoming args of the function.  A function
-	     might have live parameter registers even if it has no
-	     incoming args.  */
-	  for (last_parm_reg = 10;
-	       last_parm_reg > 2 && ! regs_ever_live [last_parm_reg];
-	       last_parm_reg--)
-	    ;
-
-	  /* Calculate first reg for saving parameter registers
-	     and static chain.
-	     Skip reg 31 which may contain the frame pointer.  */
-	  profile_first_reg = (33 - last_parm_reg
-			       - (current_function_needs_context ? 1 : 0));
-#if TARGET_MACHO
-          /* Need to skip another reg to account for R31 being PICBASE
-             (when flag_pic is set) or R30 being used as the frame
-             pointer (when flag_pic is not set).  */
-          --profile_first_reg;
-#endif
-	  /* Do not save frame pointer if no parameters needs to be saved.  */
-	  if (profile_first_reg == 31)
-	    profile_first_reg = 32;
-
-	  if (first_reg > profile_first_reg)
-	    first_reg = profile_first_reg;
-	}
-
-      /* SVR4 may need one register to preserve the static chain.  */
-      else if (current_function_needs_context)
-	{
-	  /* Skip reg 31 which may contain the frame pointer.  */
-	  if (first_reg > 30)
-	    first_reg = 30;
-	}
-    }
-
 #if TARGET_MACHO
   if (flag_pic && current_function_uses_pic_offset_table &&
       (first_reg > RS6000_PIC_OFFSET_TABLE_REGNUM))
@@ -10429,6 +10382,7 @@ output_function_profiler (file, labelno)
   int labelno;
 {
   char buf[100];
+  int save_lr = 8;
 
   ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
   switch (DEFAULT_ABI)
@@ -10437,13 +10391,21 @@ output_function_profiler (file, labelno)
       abort ();
 
     case ABI_V4:
+      save_lr = 4;
+      /* Fall through.  */
+
     case ABI_AIX_NODESC:
+      if (!TARGET_32BIT)
+	{
+	  warning ("no profiling of 64-bit code for this ABI");
+	  return;
+	}
       fprintf (file, "\tmflr %s\n", reg_names[0]);
       if (flag_pic == 1)
 	{
 	  fputs ("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n", file);
-	  asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
-		       reg_names[0], reg_names[1]);
+	  asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
+		       reg_names[0], save_lr, reg_names[1]);
 	  asm_fprintf (file, "\tmflr %s\n", reg_names[12]);
 	  asm_fprintf (file, "\t{l|lwz} %s,", reg_names[0]);
 	  assemble_name (file, buf);
@@ -10451,8 +10413,8 @@ output_function_profiler (file, labelno)
 	}
       else if (flag_pic > 1)
 	{
-	  asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
-		       reg_names[0], reg_names[1]);
+	  asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
+		       reg_names[0], save_lr, reg_names[1]);
 	  /* Now, we need to get the address of the label.  */
 	  fputs ("\tbl 1f\n\t.long ", file);
 	  assemble_name (file, buf);
@@ -10468,27 +10430,32 @@ output_function_profiler (file, labelno)
 	  asm_fprintf (file, "\t{liu|lis} %s,", reg_names[12]);
 	  assemble_name (file, buf);
 	  fputs ("@ha\n", file);
-	  asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
-		       reg_names[0], reg_names[1]);
+	  asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
+		       reg_names[0], save_lr, reg_names[1]);
 	  asm_fprintf (file, "\t{cal|la} %s,", reg_names[0]);
 	  assemble_name (file, buf);
 	  asm_fprintf (file, "@l(%s)\n", reg_names[12]);
 	}
 
-      if (current_function_needs_context)
-	asm_fprintf (file, "\tmr %s,%s\n",
-		     reg_names[30], reg_names[STATIC_CHAIN_REGNUM]);
-      fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
-      if (current_function_needs_context)
-	asm_fprintf (file, "\tmr %s,%s\n",
-		     reg_names[STATIC_CHAIN_REGNUM], reg_names[30]);
+      if (current_function_needs_context && DEFAULT_ABI == ABI_AIX_NODESC)
+	{
+	  asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
+		       reg_names[STATIC_CHAIN_REGNUM],
+		       12, reg_names[1]);
+	  fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
+	  asm_fprintf (file, "\t{l|lwz} %s,%d(%s)\n",
+		       reg_names[STATIC_CHAIN_REGNUM],
+		       12, reg_names[1]);
+	}
+      else
+	/* ABI_V4 saves the static chain reg with ASM_OUTPUT_REG_PUSH.  */
+	fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
       break;
 
     case ABI_AIX:
     case ABI_DARWIN:
       /* Don't do anything, done in output_profile_hook ().  */
       break;
-
     }
 }
 
Index: gcc/config/rs6000/sysv4.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/sysv4.h,v
retrieving revision 1.98
diff -u -p -r1.98 sysv4.h
--- gcc/config/rs6000/sysv4.h	10 Jul 2002 00:33:51 -0000	1.98
+++ gcc/config/rs6000/sysv4.h	17 Jul 2002 08:19:36 -0000
@@ -736,6 +736,38 @@ do {									\
   ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN);			\
 } while (0)
 
+/* This is how to output code to push a register on the stack.
+   It need not be very fast code.
+
+   On the rs6000, we must keep the backchain up to date.  In order
+   to simplify things, always allocate 16 bytes for a push (System V
+   wants to keep stack aligned to a 16 byte boundary).  */
+
+#define	ASM_OUTPUT_REG_PUSH(FILE, REGNO)				\
+do {									\
+  if (DEFAULT_ABI == ABI_V4)						\
+    asm_fprintf (FILE,							\
+		 (TARGET_32BIT						\
+		  ? "\t{stu|stwu} %s,-16(%s)\n\t{st|stw} %s,12(%s)\n"	\
+		  : "\tstdu %s,-32(%s)\n\tstd %s,24(%s)\n"),		\
+		 reg_names[1], reg_names[1], reg_names[REGNO],		\
+		 reg_names[1]);						\
+} while (0)
+
+/* This is how to output an insn to pop a register from the stack.
+   It need not be very fast code.  */
+
+#define	ASM_OUTPUT_REG_POP(FILE, REGNO)					\
+do {									\
+  if (DEFAULT_ABI == ABI_V4)						\
+    asm_fprintf (FILE,							\
+		 (TARGET_32BIT						\
+		  ? "\t{l|lwz} %s,12(%s)\n\t{ai|addic} %s,%s,16\n"	\
+		  : "\tld %s,24(%s)\n\t{ai|addic} %s,%s,32\n"),		\
+		 reg_names[REGNO], reg_names[1], reg_names[1],		\
+		 reg_names[1]);						\
+} while (0)
+
 /* Switch  Recognition by gcc.c.  Add -G xx support.  */
 
 /* Override svr4.h definition.  */
Index: gcc/config/rs6000/linux64.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/linux64.h,v
retrieving revision 1.21
diff -u -p -r1.21 linux64.h
--- gcc/config/rs6000/linux64.h	11 Jul 2002 00:23:16 -0000	1.21
+++ gcc/config/rs6000/linux64.h	17 Jul 2002 08:19:25 -0000
@@ -329,3 +329,7 @@ do									\
     sym_lineno += 1;							\
   }									\
 while (0)
+
+/* Override sysv4.h as these are ABI_V4 only.  */
+#undef	ASM_OUTPUT_REG_PUSH
+#undef	ASM_OUTPUT_REG_POP



More information about the Gcc-patches mailing list