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]

frv floating-point condition codes reload problem


I had expected Aldy to contribute this one along with his recent TLS
patch, but his tree wasn't sufficiently up-to-date.  So I got an
opportunity to expand on the problem.

GCC failed to bring a FP CC pseudo that ended up assigned to a stack
slot at (plus (reg fp) (const_int -8200)) back to a hardware condition
code.

The problem was that the reload_incc_fp pattern required a
memory_operand, but the big const_int that didn't fit in 12 bits
caused the address to be regarded as non-legitimate.  Failing to match
the predicate for the pattern input operand, reload attempted a
secondary reload using only the register class returned by
SECONDARY_INPUT_RELOAD_CLASS, and that fails because movcc_fp_internal
doesn't have an alternative to copy from a gpr to a fcr.

The patch actually contains two significant changes:

first, make sure movcc_fp_internal doesn't match if the output operand
is invalid, and actually avoid even attempting to emit such a pattern
using movcc_fp.  I'm not entirely sure this has any effect other than
changing the ICE from `unmatched constraints' to `unrecognizable
insn', but it felt like progress to me.

second, get reload_incc_fp to accept a limited class of illegitimate
addresses, and legitimize them using one of the available scratch
registers.  This actually fixes the bug, getting correct code to be
generated.

What I'm not entirely sure is whether it's worth keeping the
constraint as "m" or changing it to "d".  I actually chose a predicate
that accepted gprs because the code actually works if we get the
CC_FPmode value in a gpr, so I figured I wouldn't limit it in the
predicate, but I have no idea whether the constraint would actually
force the gpr contents into memory just to have it loaded back.  I
can't quite figure out what effects this constraint has in this case.
It appears to be intended to affect the choices of temporaries used to
satisfy the required reload, but I can't quite see effects in this
case.

Anyhow, I'm checking this in.  Tested on i686-pc-linux-gnu and
x86_64-linux-gnu hosts, cross-building frv-linux-gnu, frv-uclinux and
frv-elf.

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* config/frv/frv.c (movcc_fp_destination_operand): New.
	(gpr_or_memory_operand): Fix typo in comment.
	(gpr_or_memory_operand_with_scratch): New.
	* config/frv/frv.h (PREDICATE_CODES): Add the two new predicates.
	* config/frv/frv.md (movcc_fp, movcc_fp_internal): Use
	movcc_fp_destination_operand.
	(reload_incc_fp): Use gpr_or_memory_operand_with_scratch.
	Legitimize memory addresses using a scratch register.

Index: gcc/config/frv/frv.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv.c,v
retrieving revision 1.80
diff -u -p -r1.80 frv.c
--- gcc/config/frv/frv.c 27 Jan 2005 08:37:19 -0000 1.80
+++ gcc/config/frv/frv.c 27 Jan 2005 08:48:52 -0000
@@ -4569,6 +4569,19 @@ move_destination_operand (rtx op, enum m
   return FALSE;
 }
 
+/* Return true if we the operand is a valid destination for a movcc_fp
+   instruction.  This means rejecting fcc_operands, since we need
+   scratch registers to write to them.  */
+
+int
+movcc_fp_destination_operand (rtx op, enum machine_mode mode)
+{
+  if (fcc_operand (op, mode))
+    return FALSE;
+
+  return move_destination_operand (op, mode);
+}
+
 /* Look for a SYMBOL_REF of a function in an rtx.  We always want to
    process these separately from any offsets, such that we add any
    offsets to the function descriptor (the actual pointer), not to the
@@ -4832,7 +4845,8 @@ const_unspec_operand (rtx op, enum machi
 
   return frv_const_unspec_p (op, &unspec);
 }
-/* Return true if operand is a gpr register or a valid memory operation.  */
+
+/* Return true if operand is a gpr register or a valid memory operand.  */
 
 int
 gpr_or_memory_operand (rtx op, enum machine_mode mode)
@@ -4841,6 +4855,38 @@ gpr_or_memory_operand (rtx op, enum mach
 	  || frv_legitimate_memory_operand (op, mode, FALSE));
 }
 
+/* Return true if operand is a gpr register, a valid memory operand,
+   or a memory operand that can be made valid using an additional gpr
+   register.  */
+
+int
+gpr_or_memory_operand_with_scratch (rtx op, enum machine_mode mode)
+{
+  rtx addr;
+
+  if (gpr_or_memory_operand (op, mode))
+    return TRUE;
+
+  if (GET_CODE (op) != MEM)
+    return FALSE;
+
+  if (GET_MODE (op) != mode)
+    return FALSE;
+
+  addr = XEXP (op, 0);
+
+  if (GET_CODE (addr) != PLUS)
+    return FALSE;
+      
+  if (!integer_register_operand (XEXP (addr, 0), Pmode))
+    return FALSE;
+
+  if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
+    return FALSE;
+
+  return TRUE;
+}
+
 /* Return true if operand is a fpr register or a valid memory operation.  */
 
 int
Index: gcc/config/frv/frv.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv.h,v
retrieving revision 1.58
diff -u -p -r1.58 frv.h
--- gcc/config/frv/frv.h 26 Jan 2005 00:07:08 -0000 1.58
+++ gcc/config/frv/frv.h 27 Jan 2005 08:48:56 -0000
@@ -3023,12 +3023,14 @@ do {                                    
 					  CONST_DOUBLE, CONST,		\
 					  SYMBOL_REF, LABEL_REF }},	\
   { "move_destination_operand",		{ REG, SUBREG, MEM }},		\
+  { "movcc_fp_destination_operand",	{ REG, SUBREG, MEM }},		\
   { "condexec_source_operand",		{ REG, SUBREG, CONST_INT, MEM,	\
 					  CONST_DOUBLE }},		\
   { "condexec_dest_operand",		{ REG, SUBREG, MEM }},		\
   { "reg_or_0_operand",			{ REG, SUBREG, CONST_INT }},	\
   { "lr_operand",			{ REG }},			\
   { "gpr_or_memory_operand",		{ REG, SUBREG, MEM }},		\
+  { "gpr_or_memory_operand_with_scratch", { REG, SUBREG, MEM }},	\
   { "fpr_or_memory_operand",		{ REG, SUBREG, MEM }},		\
   { "int12_operand",			{ CONST_INT }},			\
   { "int_2word_operand",		{ CONST_INT, CONST_DOUBLE,	\
Index: gcc/config/frv/frv.md
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv.md,v
retrieving revision 1.29
diff -u -p -r1.29 frv.md
--- gcc/config/frv/frv.md 26 Jan 2005 18:57:03 -0000 1.29
+++ gcc/config/frv/frv.md 27 Jan 2005 08:48:59 -0000
@@ -2426,7 +2426,7 @@
 ;; to make it conditional on reload.
 
 (define_expand "movcc_fp"
-  [(set (match_operand:CC_FP 0 "move_destination_operand" "")
+  [(set (match_operand:CC_FP 0 "movcc_fp_destination_operand" "")
 	(match_operand:CC_FP 1 "move_source_operand" ""))]
   "TARGET_HAS_FPRS"
   "
@@ -2436,7 +2436,7 @@
 }")
 
 (define_insn "*movcc_fp_internal"
-  [(set (match_operand:CC_FP 0 "move_destination_operand" "=d,d,d,m")
+  [(set (match_operand:CC_FP 0 "movcc_fp_destination_operand" "=d,d,d,m")
 	(match_operand:CC_FP 1 "move_source_operand" "u,d,m,d"))]
   "TARGET_HAS_FPRS && (reload_in_progress || reload_completed)"
   "@
@@ -2450,7 +2450,7 @@
 
 (define_expand "reload_incc_fp"
   [(match_operand:CC_FP 0 "fcc_operand" "=u")
-   (match_operand:CC_FP 1 "memory_operand" "m")
+   (match_operand:CC_FP 1 "gpr_or_memory_operand_with_scratch" "m")
    (match_operand:TI 2 "integer_register_operand" "=&d")]
   "TARGET_HAS_FPRS"
   "
@@ -2462,6 +2462,27 @@
   int shift = CC_SHIFT_RIGHT (REGNO (operands[0]));
   HOST_WIDE_INT mask;
 
+  if (!gpr_or_memory_operand (operands[1], CC_FPmode))
+    {
+      rtx addr;
+      rtx temp3 = simplify_gen_subreg (SImode, operands[2], TImode, 12);
+
+      if (GET_CODE (operands[1]) != MEM)
+        abort ();
+
+      addr = XEXP (operands[1], 0);
+
+      if (GET_CODE (addr) != PLUS)
+        abort ();
+
+      emit_move_insn (temp3, XEXP (addr, 1));
+
+      operands[1] = replace_equiv_address (operands[1],
+					   gen_rtx_PLUS (GET_MODE (addr),
+							 XEXP (addr, 0),
+							 temp3));
+    }
+
   emit_insn (gen_movcc_fp (cc_op2, operands[1]));
   if (shift)
     emit_insn (gen_ashlsi3 (int_op2, int_op2, GEN_INT (shift)));
-- 
Alexandre Oliva             http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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