reload fix

Jan Hubicka jh@suse.cz
Tue May 14 03:13:00 GMT 2002


Hi
the following testcase:

extern double cos (double __x) ; extern double __cos (double __x) ;

extern double sin (double __x) ; extern double __sin (double __x) ;

void
axis_to_quat(float a[3], float phi, float q[4])
{
    vcopy(a,q);
    vscale(q,sin(phi/2.0));
    q[3] = cos(phi/2.0);
}

Crashes on x86_64 (and probably i386 with SSE2/ssemath) as well by producing
zero extend from st(0) to xmm1 in reload.  This happends in emit_inoyt_reload_insns
that attempts to optimize and replace source originally properly reloaded by
xmm1, since it veirfies the transformation of constraint_accepts_reg_p that
implicitly assumes each alternative is matching.

I am not quite sure if the attached patch is the proper fix.  I think idea of
constraint_accepts_reg_p is simply broken, so I replace it by extract_insn
and constrain operands.  This can have two problems, eigther that the insns
are not completely reload or that otehr instruction must be extracted, but
I am not able to reproduce any of such scenarios.

Honza

Tue May 14 11:51:21 CEST 2002  Jan Hubicka  <jh@suse.cz>
	* reload1.c (emit_input_reload_insns): Use constrain_operands
	instead of constraint_accepts_reg_p to verify optimization.
	(constraint_accepts_reg_p): Kill
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.335
diff -c -3 -p -r1.335 reload1.c
*** reload1.c	9 May 2002 01:42:26 -0000	1.335
--- reload1.c	14 May 2002 09:51:17 -0000
*************** static void delete_output_reload	PARAMS 
*** 440,446 ****
  static void delete_address_reloads	PARAMS ((rtx, rtx));
  static void delete_address_reloads_1	PARAMS ((rtx, rtx, rtx));
  static rtx inc_for_reload		PARAMS ((rtx, rtx, rtx, int));
- static int constraint_accepts_reg_p	PARAMS ((const char *, rtx));
  static void reload_cse_regs_1		PARAMS ((rtx));
  static int reload_cse_noop_set_p	PARAMS ((rtx));
  static int reload_cse_simplify_set	PARAMS ((rtx, rtx));
--- 440,445 ----
*************** emit_input_reload_insns (chain, rl, old,
*** 6384,6421 ****
  	  && SET_DEST (PATTERN (temp)) == old
  	  /* Make sure we can access insn_operand_constraint.  */
  	  && asm_noperands (PATTERN (temp)) < 0
- 	  /* This is unsafe if prev insn rejects our reload reg.  */
- 	  && constraint_accepts_reg_p (insn_data[recog_memoized (temp)].operand[0].constraint,
- 				       reloadreg)
  	  /* This is unsafe if operand occurs more than once in current
  	     insn.  Perhaps some occurrences aren't reloaded.  */
! 	  && count_occurrences (PATTERN (insn), old, 0) == 1
! 	  /* Don't risk splitting a matching pair of operands.  */
! 	  && ! reg_mentioned_p (old, SET_SRC (PATTERN (temp))))
  	{
  	  /* Store into the reload register instead of the pseudo.  */
  	  SET_DEST (PATTERN (temp)) = reloadreg;
  
! 	  /* If the previous insn is an output reload, the source is
! 	     a reload register, and its spill_reg_store entry will
! 	     contain the previous destination.  This is now
! 	     invalid.  */
! 	  if (GET_CODE (SET_SRC (PATTERN (temp))) == REG
! 	      && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
! 	    {
! 	      spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
! 	      spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
! 	    }
! 
! 	  /* If these are the only uses of the pseudo reg,
! 	     pretend for GDB it lives in the reload reg we used.  */
! 	  if (REG_N_DEATHS (REGNO (old)) == 1
! 	      && REG_N_SETS (REGNO (old)) == 1)
  	    {
! 	      reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
! 	      alter_reg (REGNO (old), -1);
  	    }
- 	  special = 1;
  	}
      }
  
--- 6383,6425 ----
  	  && SET_DEST (PATTERN (temp)) == old
  	  /* Make sure we can access insn_operand_constraint.  */
  	  && asm_noperands (PATTERN (temp)) < 0
  	  /* This is unsafe if operand occurs more than once in current
  	     insn.  Perhaps some occurrences aren't reloaded.  */
! 	  && count_occurrences (PATTERN (insn), old, 0) == 1)
  	{
+ 	  rtx old = SET_DEST (PATTERN (temp));
  	  /* Store into the reload register instead of the pseudo.  */
  	  SET_DEST (PATTERN (temp)) = reloadreg;
  
! 	  /* Verify that resulting insn is valid.  */
! 	  extract_insn (temp);
! 	  if (constrain_operands (1))
  	    {
! 	      /* If the previous insn is an output reload, the source is
! 		 a reload register, and its spill_reg_store entry will
! 		 contain the previous destination.  This is now
! 		 invalid.  */
! 	      if (GET_CODE (SET_SRC (PATTERN (temp))) == REG
! 		  && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
! 		{
! 		  spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
! 		  spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
! 		}
! 
! 	      /* If these are the only uses of the pseudo reg,
! 		 pretend for GDB it lives in the reload reg we used.  */
! 	      if (REG_N_DEATHS (REGNO (old)) == 1
! 		  && REG_N_SETS (REGNO (old)) == 1)
! 		{
! 		  reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
! 		  alter_reg (REGNO (old), -1);
! 		}
! 	      special = 1;
! 	    }
! 	  else
! 	    {
! 	      SET_DEST (PATTERN (temp)) = old;
  	    }
  	}
      }
  
*************** inc_for_reload (reloadreg, in, value, in
*** 7978,8028 ****
      }
  
    return store;
- }
- 
- /* Return 1 if we are certain that the constraint-string STRING allows
-    the hard register REG.  Return 0 if we can't be sure of this.  */
- 
- static int
- constraint_accepts_reg_p (string, reg)
-      const char *string;
-      rtx reg;
- {
-   int value = 0;
-   int regno = true_regnum (reg);
-   int c;
- 
-   /* Initialize for first alternative.  */
-   value = 0;
-   /* Check that each alternative contains `g' or `r'.  */
-   while (1)
-     switch (c = *string++)
-       {
-       case 0:
- 	/* If an alternative lacks `g' or `r', we lose.  */
- 	return value;
-       case ',':
- 	/* If an alternative lacks `g' or `r', we lose.  */
- 	if (value == 0)
- 	  return 0;
- 	/* Initialize for next alternative.  */
- 	value = 0;
- 	break;
-       case 'g':
-       case 'r':
- 	/* Any general reg wins for this alternative.  */
- 	if (TEST_HARD_REG_BIT (reg_class_contents[(int) GENERAL_REGS], regno))
- 	  value = 1;
- 	break;
-       default:
- 	/* Any reg in specified class wins for this alternative.  */
- 	{
- 	  enum reg_class class = REG_CLASS_FROM_LETTER (c);
- 
- 	  if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno))
- 	    value = 1;
- 	}
-       }
  }
  
  /* INSN is a no-op; delete it.
--- 7982,7987 ----



More information about the Gcc-patches mailing list