This is the mail archive of the gcc@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]

Trouble with powerpc64 mfpgpr patch


I extracted the MFPGPR hunks from Peter Bergner's "[PATCH] Add POWER6 machine description", posted on 2006-11-01 and dropped them into gcc-4.0.3, but the result fails with "error: insn does not satisfy its constraints":

.../src/gcc-4.0.3/gcc/config/rs6000/darwin-ldouble.c: In function '__gcc_qadd':
.../src/gcc-4.0.3/gcc/config/rs6000/darwin-ldouble.c:127: error: insn does not satisfy its constraints:
(insn 193 64 152 4 .../src/gcc-4.0.3/gcc/config/rs6000/darwin-ldouble.c:110 (set (reg:DF 10 10)
(plus:DF (reg:DF 34 2 [orig:124 D.1365 ] [124])
(reg:DF 32 0 [146]))) 177 {*adddf3_fpr} (nil)
(expr_list:REG_DEAD (reg:DF 34 2 [orig:124 D.1365 ] [124])
(expr_list:REG_DEAD (reg:DF 32 0 [146])
(nil))))
.../src/gcc-4.0.3/gcc/config/rs6000/darwin-ldouble.c:127: internal compiler error: in copyprop_hardreg_forward_1, at regrename.c:1583
Please submit a full bug report,
with preprocessed source if appropriate.


The complaint is about operand[0], which is an integer register with DFmode. FYI, I did my own work to put mftgpr/mffgpr into GCC-4.0.x last year, and ran into this same problem. I solved it by changing the operand predicates everywhere I found an "f" constraint so that the predicate only allowed FP regs rather than the permissive gpc_reg_operand. Alhough this worked, I didn't like it because the change was very invasive, so when I saw that Peter's patch didn't muck with the FP operand predicates, I wanted to use it instead. Alas, I have the same problem with integer registers matching gpc_reg_operand, but not satisfying the "f" constraint. What am I missing? Is there something inhospitable about GCC-4.0 vs. the trunk for Peter's changes? The patch I used is attached.

Thanks, Greg

2006-11-01  Pete Steinmetz  <steinmtz@us.ibm.com>
	    Peter Bergner  <bergner@vnet.ibm.com>

	* config/rs6000/rs6000.md (define_attr "type"): Add mffgpr
	and mftgpr attributes.
	(floatsidf2,fix_truncdfsi2): use TARGET_MFPGPR.
	(fix_truncdfsi2_mfpgpr): New.
	(floatsidf_ppc64_mfpgpr): New.
	(floatsidf_ppc64): Added !TARGET_MFPGPR condition.
	(movdf_hardfloat64_mfpgpr,movdi_mfpgpr): New.
	(movdf_hardfloat64): Added !TARGET_MFPGPR condition.
	(movdi_internal64): Added !TARGET_MFPGPR and related conditions.
	* config/rs6000/rs6000.h (TARGET_MFPGPR): New.
	(SECONDARY_MEMORY_NEEDED): Use TARGET_MFPGPR.
	(SECONDARY_MEMORY_NEEDED): Added mode!=DFmode and mode!=DImode
	conditions.

Index: gcc-4.0.3/gcc/config/rs6000/rs6000.h
===================================================================
--- gcc-4.0.3.orig/gcc/config/rs6000/rs6000.h
+++ gcc-4.0.3/gcc/config/rs6000/rs6000.h
@@ -201,6 +201,9 @@ extern int target_flags;
 /* Use single field mfcr instruction.  */
 #define MASK_MFCRF		0x00080000
 
+/* Use FP <-> GP register moves.  */
+#define MASK_MFPGPR		0x00200000
+
 /* The only remaining free bits are 0x00600000.  linux64.h uses
    0x00100000, and sysv4.h uses 0x00800000 -> 0x40000000.
    0x80000000 is not available because target_flags is signed.  */
@@ -223,6 +226,7 @@ extern int target_flags;
 #define TARGET_SCHED_PROLOG	(target_flags & MASK_SCHED_PROLOG)
 #define TARGET_ALTIVEC		(target_flags & MASK_ALTIVEC)
 #define TARGET_AIX_STRUCT_RET	(target_flags & MASK_AIX_STRUCT_RET)
+#define TARGET_MFPGPR		(target_flags & MASK_MFPGPR)
 
 /* Define TARGET_MFCRF if the target assembler supports the optional
    field operand for mfcr and the target processor supports the
@@ -234,7 +238,6 @@ extern int target_flags;
 #define TARGET_MFCRF 0
 #endif
 
-
 #define TARGET_32BIT		(! TARGET_64BIT)
 #define TARGET_HARD_FLOAT	(! TARGET_SOFT_FLOAT)
 #define TARGET_UPDATE		(! TARGET_NO_UPDATE)
@@ -365,6 +368,10 @@ extern int target_flags;
 			N_("Generate single field mfcr instruction")},	\
   {"no-mfcrf",		- MASK_MFCRF,					\
 			N_("Do not generate single field mfcr instruction")},\
+  {"mfpgpr",		MASK_MFPGPR,					\
+			N_("Generate moves between floating and general registers")},	\
+  {"no-mfpgpr",		- MASK_MFPGPR,					\
+			N_("Do not generate moves between floating and general registers")},\
   SUBTARGET_SWITCHES							\
   {"",			TARGET_DEFAULT | MASK_SCHED_PROLOG,		\
 			""}}
@@ -1413,12 +1420,18 @@ enum reg_class
   secondary_reload_class (CLASS, MODE, IN)
 
 /* If we are copying between FP or AltiVec registers and anything
-   else, we need a memory location.  */
-
-#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) 		\
- ((CLASS1) != (CLASS2) && ((CLASS1) == FLOAT_REGS		\
-			   || (CLASS2) == FLOAT_REGS		\
-			   || (CLASS1) == ALTIVEC_REGS		\
+   else, we need a memory location.  The exception is when we are
+   targeting ppc64 and the move to/from fpr to gpr instructions
+   are available.*/
+
+#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE)			\
+ ((CLASS1) != (CLASS2) && (((CLASS1) == FLOAT_REGS			\
+                            && (!TARGET_MFPGPR || !TARGET_POWERPC64	\
+				|| ((MODE != DFmode) && (MODE != DImode)))) \
+			   || ((CLASS2) == FLOAT_REGS			\
+                               && (!TARGET_MFPGPR || !TARGET_POWERPC64	\
+				|| ((MODE != DFmode) && (MODE != DImode)))) \
+			   || (CLASS1) == ALTIVEC_REGS			\
 			   || (CLASS2) == ALTIVEC_REGS))
 
 /* Return the maximum number of consecutive registers
Index: gcc-4.0.3/gcc/config/rs6000/rs6000.md
===================================================================
--- gcc-4.0.3.orig/gcc/config/rs6000/rs6000.md
+++ gcc-4.0.3/gcc/config/rs6000/rs6000.md
@@ -5120,6 +5120,12 @@
       emit_insn (gen_spe_floatsidf2 (operands[0], operands[1]));
       DONE;
     }
+  if (TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS)
+    {
+      rtx t1 = gen_reg_rtx (DImode);
+      emit_insn (gen_floatsidf_ppc64_mfpgpr (operands[0], operands[1], t1));
+      DONE;
+    }
   if (TARGET_POWERPC64)
     {
       rtx mem = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
@@ -5283,6 +5289,14 @@
      DONE;
     }
   operands[2] = gen_reg_rtx (DImode);
+  if (TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+      && gpc_reg_operand(operands[0], GET_MODE (operands[0])))
+    {
+      operands[3] = gen_reg_rtx (DImode);
+      emit_insn (gen_fix_truncdfsi2_mfpgpr (operands[0], operands[1],
+					     operands[2], operands[3]));
+      DONE;
+    }
   operands[3] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
 }")
 
@@ -5320,6 +5334,20 @@
   DONE;
 }")
 
+(define_insn_and_split "fix_truncdfsi2_mfpgpr"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+	(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
+   (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))
+   (clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))]
+  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "#"
+  "&& 1"
+  [(set (match_dup 2) (unspec:DI [(fix:SI (match_dup 1))] UNSPEC_FCTIWZ))
+   (set (match_dup 3) (match_dup 2))
+   (set (match_dup 0) (subreg:SI (match_dup 3) 4))]
+  ""
+  [(set_attr "length" "12")])
+
 ; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ))
 ; rather than (set (subreg:SI (reg)) (fix:SI ...))
 ; because the first makes it clear that operand 0 is not live
@@ -5345,13 +5373,24 @@
   "fcfid %0,%1"
   [(set_attr "type" "fp")])
 
+(define_insn_and_split "floatsidf_ppc64_mfpgpr"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+	(float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
+   (clobber (match_operand:DI 2 "gpc_reg_operand" "=r"))]
+  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "#"
+  "&& 1"
+  [(set (match_dup 2) (sign_extend:DI (match_dup 1)))
+   (set (match_dup 0) (float:DF (match_dup 2)))]
+  "")
+
 (define_insn_and_split "floatsidf_ppc64"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
 	(float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
    (clobber (match_operand:DI 2 "memory_operand" "=o"))
    (clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))
    (clobber (match_operand:DI 4 "gpc_reg_operand" "=f"))]
-  "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
+  "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS"
   "#"
   "&& 1"
   [(set (match_dup 3) (sign_extend:DI (match_dup 1)))
@@ -8223,10 +8262,36 @@
 
 ; ld/std require word-aligned displacements -> 'Y' constraint.
 ; List Y->r and r->Y before r->r for reload.
+(define_insn "*movdf_hardfloat64_mfpgpr"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r,r,f")
+	(match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F,f,r"))]
+  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+   && (gpc_reg_operand (operands[0], DFmode)
+       || gpc_reg_operand (operands[1], DFmode))"
+  "@
+   std%U0%X0 %1,%0
+   ld%U1%X1 %0,%1
+   mr %0,%1
+   fmr %0,%1
+   lfd%U1%X1 %0,%1
+   stfd%U0%X0 %1,%0
+   mt%0 %1
+   mf%1 %0
+   {cror 0,0,0|nop}
+   #
+   #
+   #
+   mftgpr %0,%1
+   mffgpr %0,%1"
+  [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*,*,*")
+   (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16,4,4")])
+
+; ld/std require word-aligned displacements -> 'Y' constraint.
+; List Y->r and r->Y before r->r for reload.
 (define_insn "*movdf_hardfloat64"
   [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,!cl,!r,!h,!r,!r,!r")
 	(match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
-  "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
+  "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
    && (gpc_reg_operand (operands[0], DFmode)
        || gpc_reg_operand (operands[1], DFmode))"
   "@
@@ -8574,10 +8639,35 @@
   [(pc)]
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
 
+(define_insn "*movdi_mfpgpr"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*f,*f,m,r,*h,*h,r,*f")
+	(match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0,*f,r"))]
+  "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
+   && (gpc_reg_operand (operands[0], DImode)
+       || gpc_reg_operand (operands[1], DImode))"
+  "@
+   mr %0,%1
+   ld%U1%X1 %0,%1
+   std%U0%X0 %1,%0
+   li %0,%1
+   lis %0,%v1
+   #
+   {cal|la} %0,%a1
+   fmr %0,%1
+   lfd%U1%X1 %0,%1
+   stfd%U0%X0 %1,%0
+   mf%1 %0
+   mt%0 %1
+   {cror 0,0,0|nop}
+   mftgpr %0,%1
+   mffgpr %0,%1"
+  [(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,*,*")
+   (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4")])
+
 (define_insn "*movdi_internal64"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*f,*f,m,r,*h,*h")
 	(match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0"))]
-  "TARGET_POWERPC64
+  "TARGET_POWERPC64 && (!TARGET_MFPGPR || !TARGET_HARD_FLOAT || !TARGET_FPRS)
    && (gpc_reg_operand (operands[0], DImode)
        || gpc_reg_operand (operands[1], DImode))"
   "@

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