This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR optimization/8300 and target/9763 (Sparc)


Hi,

These are regressions from gcc 2.95.3 present on all active branches.

The compiler ICEs in emit-rtl.c:gen_reg_rtx() on both testcases for exactly 
the same reason: it tries to create a new pseudo-reg when it is not allowed 
to do so any longer.

We have these lines in toplev.c:

  no_new_pseudos = 1;

  if (warn_uninitialized || extra_warnings)
    {
      uninitialized_vars_warning (DECL_INITIAL (decl));
      if (extra_warnings)
	setjmp_args_warning ();
    }

  if (optimize)
    {
      if (initialize_uninitialized_subregs ())
	{
	  /* Insns were inserted, so things might look a bit different.  */
	  insns = get_insns ();
	  life_analysis (insns, rtl_dump_file, 
			 (PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES));
	}
    }

The problem is the call to initialize_uninitialized_subregs(): this function 
is intended to initialize some pseudo-regs with 0. Now, on generic Sparc 
CPUs, FP regs can't be zeroed directly so we end up forcing 0.0 into memory 
in order to load it into the FP regs. But, given that we use indexed 
addressing, we need a new pseudo to do so, hence we abort in gen_reg_rtx().

The proposed fix is to zero the FP regs with a 'fsub' in this case. 
Bootstrapped/regtested on sparc-sun-solaris2.8 (c,c++,objc,f77 3.2 branch) 
and sparc-sun-solaris2.9 (c,c++,objc,f77 3.3 branch).

-- 
Eric Botcazou


2003-03-23  Eric Botcazou  <ebotcazou at libertysurf dot fr>

        PR optimization/8300 and target/9763
	* config/sparc/sparc.md (movsf expander): Use 'fsub'
	to zero the FP regs when no new pseudos are allowed.
	(movdf expander): Likewise.


2003-03-23  Eric Botcazou  <ebotcazou at libertysurf dot fr>

	* gcc.dg/20030323-1.c: New test.
	* gcc.dg/20030323-2.c: New test.
Index: config/sparc/sparc.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.md,v
retrieving revision 1.148.2.15.4.1
diff -u -r1.148.2.15.4.1 sparc.md
--- config/sparc/sparc.md	2 Oct 2002 03:47:05 -0000	1.148.2.15.4.1
+++ config/sparc/sparc.md	20 Mar 2003 09:55:25 -0000
@@ -3177,7 +3177,7 @@
   ""
   "
 {
-  /* Force SFmode constants into memory.  */
+  /* Force SFmode constants into memory if necessary.  */
   if (GET_CODE (operands[0]) == REG
       && CONSTANT_P (operands[1]))
     {
@@ -3187,6 +3187,7 @@
       if (operands [1] == const0_rtx)
         operands[1] = CONST0_RTX (SFmode);
 
+      /* The Visual Instruction Set extensions have 'fzero'.  */
       if (TARGET_VIS && fp_zero_operand (operands[1], SFmode))
 	goto movsf_is_ok;
 
@@ -3195,6 +3196,26 @@
       if (REGNO (operands[0]) < 32)
 	goto movsf_is_ok;
 
+      /* We might be requested to clear some SF regs after the ban on
+	 new pseudo regs creation.  In that case, we can't force into
+	 memory because we would need a new pseudo to load back from
+	 memory.  */
+      if (no_new_pseudos && fp_zero_operand (operands[1], SFmode))
+	{
+	  /* Careful, subsf3 is a FP-only insn.  */
+	  if (TARGET_FPU)
+	    {
+	      /* Substract the register from itself.  */
+	      rtx insn = emit_insn (gen_subsf3 (operands[0], operands[0], operands[0]));
+	      set_unique_reg_note (insn, REG_EQUAL, operands[1]);
+	      DONE;
+	    }
+
+	  /* Nothing to be done for integer registers.  */
+	  else
+	    goto movsf_is_ok;
+	}
+
       operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
                                                    operands[1]));
     }
@@ -3240,7 +3261,7 @@
   ""
   "
 {
-  /* Force DFmode constants into memory.  */
+  /* Force DFmode constants into memory if necessary.  */
   if (GET_CODE (operands[0]) == REG
       && CONSTANT_P (operands[1]))
     {
@@ -3250,6 +3271,7 @@
       if (operands [1] == const0_rtx)
         operands[1] = CONST0_RTX (DFmode);
 
+      /* The Visual Instruction Set extensions have 'fzero'.  */
       if ((TARGET_VIS || REGNO (operands[0]) < 32)
 	  && fp_zero_operand (operands[1], DFmode))
 	goto movdf_is_ok;
@@ -3258,6 +3280,26 @@
       if (REGNO (operands[0]) < 32
 	  && (reload_completed || reload_in_progress))
 	goto movdf_is_ok;
+
+      /* We might be requested to clear some DF regs after the ban on
+	 new pseudo regs creation.  In that case, we can't force into
+	 memory because we would need a new pseudo to load back from
+	 memory.  */
+      if (no_new_pseudos && fp_zero_operand (operands[1], DFmode))
+	{
+	  /* Careful, subdf3 is a FP-only insn.  */
+	  if (TARGET_FPU)
+	    {
+	      /* Substract the register from itself.  */
+	      rtx insn = emit_insn (gen_subdf3 (operands[0], operands[0], operands[0]));
+	      set_unique_reg_note (insn, REG_EQUAL, operands[1]);
+	      DONE;
+	    }
+
+	  /* Nothing to be done for integer registers.  */
+	  else
+	    goto movdf_is_ok;
+	}
 
       operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
                                                    operands[1]));
/* PR optimization/8300 */
/* Originator: Robert Schiele <rschiele at uni-mannheim dot de> */
/* { dg-do compile } */
/* { dg-options "-O" } */

/* This testcase violates the ISO C aliasing rules
   but it used to expose a real problem on Sparc.  */

void a()
{
  double b;
  int c[2];
  *((int*)&b) && (c[1] = 0);
}
/* PR target/9763 */
/* Contributed by Christian Ehrhardt <ehrhardt at mathematik dot uni-ulm dot de> */
/* { dg-do compile } */
/* { dg-options "-O" } */

/* This testcase violates the ISO C aliasing rules
   but it used to expose a real problem on Sparc.  */

static int phys_get_long(int addr)
{
  if (addr)
    return 0; 
  addr = 0xff000000;
}

struct ieee {
  int negative:1 ;
};

double make_single(int value)
{
  float result;
  struct ieee * srp = (struct ieee *) ( &result );
  srp->negative = (value >> 31) & 1;
  return result;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]