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 to fix MIPS IV reload failures


Two related MIPS IV bug-fixes here.  The simple one is to
make TFmode valid for float registers, since reload_incc
needs a TFmode scratch.  (It was a change of mine that
broke things, sorry.)

The main part of the patch is to fix the long-standing
compile/920501-4.c -O1 ICE, in which an existing movcc
instruction isn't properly reloaded.

On this target, all moves into a condition-code register
require a floating-point scratch.  Thus movcc's destination
constraints don't include condition-code registers.

In the test case, we have a movcc whose destination is 
allocated to a condition-code register, and we need to
reload out of a float or integer register.  reload_outcc
doesn't handle this situation: it assumes we'll only ever
reload out of a condition-code register.

What's more, the current reload_outcc seems to be redundant,
since the "scratch" register is really just an intermediary.
The pattern generates: scratch <- src, dest <- scratch.

The patch below makes reload_outcc handle moves into
condition-code registers in the same way that reload_incc
does.  The patterns are now identical, which seems a little
odd.  But moves into condition-code registers are the "only"
CCmode ones that need a special reload pattern.  Other
combinations (such as FCC -> FPR) just need two moves.
Is this the right fix?

Patch tested on mips64-elf, pattern {-EB,-EL}{,-mips4,-msoft-float}.
Fixes several test cases.  OK for trunk?

Richard


	* config/mips/mips-protos.h (mips_emit_fcc_reload): Declare.
	* config/mips/mips.h (PREDICATE_CODES): Add fcc_register_operand.
	* config/mips/mips.c (fcc_register_operand): New function.
	(mips_emit_fcc_reload): New function, extracted from reload_incc.
	(override_options): Allow TFmode values in float registers
	if ISA_HAS_8CC.
	* cnfig/mips/mips.md (reload_incc): Change destination prediate
	to fcc_register_operand.  Remove misleading source constraint.
	Use mips_emit_fcc_reload.
	(reload_outcc): Duplicate reload_incc.

Index: config/mips/mips-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips-protos.h,v
retrieving revision 1.28
diff -c -d -p -r1.28 mips-protos.h
*** config/mips/mips-protos.h	2 Aug 2002 14:55:08 -0000	1.28
--- config/mips/mips-protos.h	25 Sep 2002 10:28:30 -0000
*************** extern void		init_cumulative_args PARAMS
*** 87,92 ****
--- 87,93 ----
  						      tree, rtx));
  extern void		gen_conditional_move PARAMS ((rtx *));
  extern void		mips_gen_conditional_trap PARAMS ((rtx *));
+ extern void		mips_emit_fcc_reload PARAMS ((rtx, rtx, rtx));
  extern void		mips_set_return_address PARAMS ((rtx, rtx));
  extern void		machine_dependent_reorg PARAMS ((rtx));
  extern int		mips_address_cost PARAMS ((rtx));
Index: config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.219
diff -c -d -p -r1.219 mips.h
*** config/mips/mips.h	20 Sep 2002 23:46:56 -0000	1.219
--- config/mips/mips.h	25 Sep 2002 10:28:31 -0000
*************** typedef struct mips_args {
*** 3824,3829 ****
--- 3824,3830 ----
  				  REG, SIGN_EXTEND }},			\
    {"consttable_operand",	{ LABEL_REF, SYMBOL_REF, CONST_INT,	\
  				  CONST_DOUBLE, CONST }},		\
+   {"fcc_register_operand",	{ REG, SUBREG }},			\
    {"extend_operator",           { SIGN_EXTEND, ZERO_EXTEND }},          \
    {"highpart_shift_operator",   { ASHIFTRT, LSHIFTRT, ROTATERT, ROTATE }},
  
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.229
diff -c -d -p -r1.229 mips.c
*** config/mips/mips.c	20 Sep 2002 23:46:56 -0000	1.229
--- config/mips/mips.c	25 Sep 2002 10:28:31 -0000
*************** mips_gen_conditional_trap (operands)
*** 3522,3527 ****
--- 3553,3603 ----
  			      operands[1]));
  }
  
+ /* Return true if operand OP is a condition code register.
+    Only for use during or after reload.  */
+ 
+ int
+ fcc_register_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+ {
+   return ((mode == VOIDmode || mode == GET_MODE (op))
+ 	  && (reload_in_progress || reload_completed)
+ 	  && (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ 	  && ST_REG_P (true_regnum (op)));
+ }
+ 
+ /* Emit code to move general operand SRC into condition-code
+    register DEST.  SCRATCH is a scratch TFmode float register.
+    The sequence is:
+ 
+ 	FP1 = SRC
+ 	FP2 = 0.0f
+ 	DEST = FP2 < FP1
+ 
+    where FP1 and FP2 are single-precision float registers
+    taken from SCRATCH.  */
+ 
+ void
+ mips_emit_fcc_reload (dest, src, scratch)
+      rtx dest, src, scratch;
+ {
+   rtx fp1, fp2;
+ 
+   /* Change the source to SFmode.  */
+   if (GET_CODE (src) == MEM)
+     src = adjust_address (src, SFmode, 0);
+   else if (GET_CODE (src) == REG || GET_CODE (src) == SUBREG)
+     src = gen_rtx_REG (SFmode, true_regnum (src));
+ 
+   fp1 = gen_rtx_REG (SFmode, REGNO (scratch));
+   fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + FP_INC);
+ 
+   emit_move_insn (copy_rtx (fp1), src);
+   emit_move_insn (copy_rtx (fp2), CONST0_RTX (SFmode));
+   emit_insn (gen_slt_sf (dest, fp2, fp1));
+ }
+ 
  /* Emit code to change the current function's return address to
     ADDRESS.  SCRATCH is available as a scratch register, if needed.
     ADDRESS and SCRATCH are both word-mode GPRs.  */
*************** override_options ()
*** 5362,5368 ****
  			/* Allow integer modes that fit into a single
  			   register.  We need to put integers into FPRs
  			   when using instructions like cvt and trunc.  */
! 			|| (class == MODE_INT && size <= UNITS_PER_FPREG)));
  
  	  else if (MD_REG_P (regno))
  	    temp = (class == MODE_INT
--- 5438,5446 ----
  			/* Allow integer modes that fit into a single
  			   register.  We need to put integers into FPRs
  			   when using instructions like cvt and trunc.  */
! 			|| (class == MODE_INT && size <= UNITS_PER_FPREG)
! 			/* Allow TFmode for CCmode reloads.  */
! 			|| (ISA_HAS_8CC && mode == TFmode)));
  
  	  else if (MD_REG_P (regno))
  	    temp = (class == MODE_INT
Index: config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v
retrieving revision 1.143
diff -c -d -p -r1.143 mips.md
*** config/mips/mips.md	20 Sep 2002 20:11:25 -0000	1.143
--- config/mips/mips.md	25 Sep 2002 10:28:32 -0000
*************** move\\t%0,%z4\\n\\
*** 6025,6101 ****
     (set_attr "mode"	"SI")
     (set_attr "length"	"8,4,4,8,4,8,4,4,4,4,8,4,8")])
  
! ;; Reload condition code registers.  These need scratch registers.
! 
  (define_expand "reload_incc"
!   [(set (match_operand:CC 0 "register_operand" "=z")
! 	(match_operand:CC 1 "general_operand" "z"))
     (clobber (match_operand:TF 2 "register_operand" "=&f"))]
    "ISA_HAS_8CC && TARGET_HARD_FLOAT"
    "
  {
!   rtx source;
!   rtx fp1, fp2;
!   int regno;
! 
!   /* This is called when are copying some value into a condition code
!      register.  Operand 0 is the condition code register.  Operand 1
!      is the source.  Operand 2 is a scratch register; we use TFmode
!      because we actually need two floating point registers.  */
!   if (! ST_REG_P (true_regnum (operands[0]))
!       || ! FP_REG_P (true_regnum (operands[2])))
!     abort ();
! 
!   /* We need to get the source in SFmode so that the insn is
!      recognized.  */
!   if (GET_CODE (operands[1]) == MEM)
!     source = adjust_address (operands[1], SFmode, 0);
!   else if (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG)
!     source = gen_rtx_REG (SFmode, true_regnum (operands[1]));
!   else
!     source = operands[1];
! 
!   /* FP1 and FP2 are the two halves of the TFmode scratch operand.  They
!      will be single registers in 64-bit mode and register pairs in 32-bit
!      mode.  SOURCE is loaded into FP1 and zero is loaded into FP2.  */
!   regno = REGNO (operands[2]);
!   fp1 = gen_rtx_REG (SFmode, regno);
!   fp2 = gen_rtx_REG (SFmode, regno + HARD_REGNO_NREGS (regno, DFmode));
! 
!   emit_insn (gen_move_insn (fp1, source));
!   emit_insn (gen_move_insn (fp2, gen_rtx_REG (SFmode, 0)));
!   emit_insn (gen_rtx_SET (VOIDmode, operands[0],
! 			  gen_rtx_LT (CCmode, fp2, fp1)));
! 
    DONE;
  }")
  
  (define_expand "reload_outcc"
!   [(set (match_operand:CC 0 "general_operand" "=z")
! 	(match_operand:CC 1 "register_operand" "z"))
!    (clobber (match_operand:CC 2 "register_operand" "=&d"))]
    "ISA_HAS_8CC && TARGET_HARD_FLOAT"
    "
  {
!   /* This is called when we are copying a condition code register out
!      to save it somewhere.  Operand 0 should be the location we are
!      going to save it to.  Operand 1 should be the condition code
!      register.  Operand 2 should be a scratch general purpose register
!      created for us by reload.  The mips_secondary_reload_class
!      function should have told reload that we don't need a scratch
!      register if the destination is a general purpose register anyhow.  */
!   if (ST_REG_P (true_regnum (operands[0]))
!       || GP_REG_P (true_regnum (operands[0]))
!       || ! ST_REG_P (true_regnum (operands[1]))
!       || ! GP_REG_P (true_regnum (operands[2])))
!     abort ();
! 
!   /* All we have to do is copy the value from the condition code to
!      the data register, which movcc can handle, and then store the
!      value into the real final destination.  */
!   emit_insn (gen_move_insn (operands[2], operands[1]));
!   emit_insn (gen_move_insn (operands[0], operands[2]));
! 
    DONE;
  }")
  
--- 6025,6063 ----
     (set_attr "mode"	"SI")
     (set_attr "length"	"8,4,4,8,4,8,4,4,4,4,8,4,8")])
  
! ;; Reload condition code registers.  reload_incc and reload_outcc
! ;; both handle moves from arbitrary operands into condition code
! ;; registers.  reload_incc handles the more common case in which
! ;; a source operand is constrained to be in a condition-code
! ;; register, but has not been allocated to one.
! ;;
! ;; Sometimes, such as in movcc, we have a CCmode destination whose
! ;; constraints do not include 'z'.  reload_outcc handles the case
! ;; when such an operand is allocated to a condition-code register.
! ;;
! ;; Note that reloads from a condition code register to some
! ;; other location can be done using ordinary moves.  Moving
! ;; into a GPR takes a single movcc, moving elsewhere takes
! ;; two.  We can leave these cases to the generic reload code.
  (define_expand "reload_incc"
!   [(set (match_operand:CC 0 "fcc_register_operand" "=z")
! 	(match_operand:CC 1 "general_operand" ""))
     (clobber (match_operand:TF 2 "register_operand" "=&f"))]
    "ISA_HAS_8CC && TARGET_HARD_FLOAT"
    "
  {
!   mips_emit_fcc_reload (operands[0], operands[1], operands[2]);
    DONE;
  }")
  
  (define_expand "reload_outcc"
!   [(set (match_operand:CC 0 "fcc_register_operand" "=z")
! 	(match_operand:CC 1 "register_operand" ""))
!    (clobber (match_operand:TF 2 "register_operand" "=&f"))]
    "ISA_HAS_8CC && TARGET_HARD_FLOAT"
    "
  {
!   mips_emit_fcc_reload (operands[0], operands[1], operands[2]);
    DONE;
  }")
  


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