fix mips epilogue edge case

Richard Henderson rth@redhat.com
Thu Nov 8 11:14:00 GMT 2001


Fixes compile/920501-12.c, execute/921208-2.c, execute/930106-1.c.

The stack frame for these functions is larger than 32k, which means that
we needed a temporary in order to restore the registers.  But there is
only one register saved in the stack frame, the gp, and that register is
handled specially in the caller so we don't restore it.

Which leaves us with the unused temporary, which leads to the abort in
flow.c regarding dead epilogue insns.

Fix tested mipsel-linux; applied 3.0 and mainline.


r~



        * config/mips/mips.c (save_restore_insns): Remove GP from the
        restore registers mask early instead of special casing it inside
        the loop.

Index: mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.160
diff -c -p -d -r1.160 mips.c
*** mips.c	2001/11/02 02:18:36	1.160
--- mips.c	2001/11/08 19:05:49
*************** save_restore_insns (store_p, large_reg, 
*** 6659,6664 ****
--- 6659,6665 ----
  {
    long mask = current_frame_info.mask;
    long fmask = current_frame_info.fmask;
+   long real_mask = mask;
    int regno;
    rtx base_reg_rtx;
    HOST_WIDE_INT base_offset;
*************** save_restore_insns (store_p, large_reg, 
*** 6671,6676 ****
--- 6672,6683 ----
        && ! BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST))
      abort ();
  
+   /* Do not restore GP under certain conditions.  */
+   if (! store_p
+       && TARGET_ABICALLS
+       && (mips_abi == ABI_32 || mips_abi == ABI_O64))
+     mask &= ~(1 << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST));
+ 
    if (mask == 0 && fmask == 0)
      return;
  
*************** save_restore_insns (store_p, large_reg, 
*** 6785,6793 ****
  
  		if (store_p)
  		  mips_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset);
! 		else if (!TARGET_ABICALLS
! 			 || (mips_abi != ABI_32 && mips_abi != ABI_O64)
! 			 || regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
  		  {
  		    emit_move_insn (reg_rtx, mem_rtx);
  		    if (TARGET_MIPS16
--- 6792,6798 ----
  
  		if (store_p)
  		  mips_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset);
! 		else
  		  {
  		    emit_move_insn (reg_rtx, mem_rtx);
  		    if (TARGET_MIPS16
*************** save_restore_insns (store_p, large_reg, 
*** 6799,6846 ****
  	      }
  	    else
  	      {
! 		if (store_p || !TARGET_ABICALLS
! 		    || (mips_abi != ABI_32 && mips_abi != ABI_O64)
! 		    || regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
! 		  {
! 		    int r = regno;
  
! 		    /* The mips16 does not have an instruction to
!                        load $31, so we load $7 instead, and work
!                        things out in the caller.  */
! 		    if (TARGET_MIPS16 && ! store_p && r == GP_REG_FIRST + 31)
! 		      r = GP_REG_FIRST + 7;
! 		      /* The mips16 sometimes needs to save $18.  */
! 		    if (TARGET_MIPS16
! 			&& regno != GP_REG_FIRST + 31
! 			&& ! M16_REG_P (regno))
  		      {
! 			if (! store_p)
! 			  r = GP_REG_FIRST + 6;
! 			else
! 			  {
! 			    r = GP_REG_FIRST + 3;
! 			    fprintf (file, "\tmove\t%s,%s\n",
! 				     reg_names[r], reg_names[regno]);
! 			  }
  		      }
- 		    fprintf (file, "\t%s\t%s,",
- 			     (TARGET_64BIT
- 			      ? (store_p) ? "sd" : "ld"
- 			      : (store_p) ? "sw" : "lw"),
- 			     reg_names[r]);
- 		    fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- 			     gp_offset - base_offset);
- 		    fprintf (file, "(%s)\n", reg_names[REGNO(base_reg_rtx)]);
- 		    if (! store_p
- 			&& TARGET_MIPS16
- 			&& regno != GP_REG_FIRST + 31
- 			&& ! M16_REG_P (regno))
- 		      fprintf (file, "\tmove\t%s,%s\n",
- 			       reg_names[regno], reg_names[r]);
  		  }
! 
  	      }
  	    gp_offset -= GET_MODE_SIZE (gpr_mode);
  	  }
      }
--- 6804,6851 ----
  	      }
  	    else
  	      {
! 		int r = regno;
  
! 		/* The mips16 does not have an instruction to
! 		   load $31, so we load $7 instead, and work
! 		   things out in the caller.  */
! 		if (TARGET_MIPS16 && ! store_p && r == GP_REG_FIRST + 31)
! 		  r = GP_REG_FIRST + 7;
! 		/* The mips16 sometimes needs to save $18.  */
! 		if (TARGET_MIPS16
! 		    && regno != GP_REG_FIRST + 31
! 		    && ! M16_REG_P (regno))
! 		  {
! 		    if (! store_p)
! 		      r = GP_REG_FIRST + 6;
! 		    else
  		      {
! 			r = GP_REG_FIRST + 3;
! 			fprintf (file, "\tmove\t%s,%s\n",
! 				 reg_names[r], reg_names[regno]);
  		      }
  		  }
! 		fprintf (file, "\t%s\t%s,",
! 			 (TARGET_64BIT
! 			  ? (store_p) ? "sd" : "ld"
! 			  : (store_p) ? "sw" : "lw"),
! 			 reg_names[r]);
! 		fprintf (file, HOST_WIDE_INT_PRINT_DEC,
! 			 gp_offset - base_offset);
! 		fprintf (file, "(%s)\n", reg_names[REGNO(base_reg_rtx)]);
! 		if (! store_p
! 		    && TARGET_MIPS16
! 		    && regno != GP_REG_FIRST + 31
! 		    && ! M16_REG_P (regno))
! 		  fprintf (file, "\tmove\t%s,%s\n",
! 			   reg_names[regno], reg_names[r]);
  	      }
+ 	    gp_offset -= GET_MODE_SIZE (gpr_mode);
+ 	  }
+         /* If the restore is being supressed, still take into account
+ 	   the offset at which it is stored.  */
+  	else if (BITSET_P (real_mask, regno - GP_REG_FIRST))
+  	  {
  	    gp_offset -= GET_MODE_SIZE (gpr_mode);
  	  }
      }



More information about the Gcc-patches mailing list