[PATCH] Fix PR target/6512

Jakub Jelinek jakub@redhat.com
Tue Apr 30 05:26:00 GMT 2002


Hi!

PR target/6512 at least for me ICEs on
nucleic.c:21747: insn does not satisfy its constraints:
(insn 25599 25597 25601 (set (reg:SF 72 %f40 [127])
        (mem:SF (plus:SI (reg/v:SI 18 %l2 [116])
                (const_int 19 [0x13])) [0 S4 A64])) 85 {*movsf_insn_novis} (nil)
    (nil))

This insn was created by splitting:

(insn 4968 4967 4969 (set (reg/v:DF 72 %f40 [127])
        (mem:DF (plus:SI (reg/v:SI 18 %l2 [116])
                (const_int 19 [0x13])) [0 S8 A64])) 93 {*movdf_insn_v9only_novis} (nil)
    (nil))

for which we cannot prove %l2 + 0x13 to be at least 64 bit aligned.
We obviously cannot split into SF regs for DF registers %f32 and above,
as such hardware registers don't exist, but IMHO it makes no sense to
split when we are not guaranteed any alignment whatsoever (it is likely
to be 64-bit aligned for any well-behaved program and even if we split
it into 2 SF mode loads, we'd still risk unaligned 32-bit loads).

I've tried patch P3 (changing e -> f constraints for e <- o and o <- e
alternatives), but it did work at all, for the above insn
reload just tried (set %f40 (mem ())); (set %f40 %f40).

On the other side, UltraSPARC has fast unaligned ldd/std traps, so IMHO
we don't have to try too hard to avoid them if the expected case
is aligned load (this is in the first patch P4). What do you think?

	Jakub
-------------- next part --------------
2002-04-30  Jakub Jelinek  <jakub@redhat.com>

	PR target/6512
	* config/sparc/sparc.c (int_register_operand): New predicate.
	(fp_v9_register_operand): Likewise.
	* config/sparc/sparc.h (PREDICATE_CODES): Add int_register_operand
	and fp_v9_register_operand.
	* config/sparc/sparc.md (movdf_ldd, movdf_std): New insns.
	(movdf reg<-reg and reg<-0.0 splitters): Use int_register_operand.
	(movdf reg<-mem and mem<-reg splitters): Use movdf_{ldd,std} if
	float register is >= %f32 or if memory is not even 4 byte aligned.

--- gcc/config/sparc/sparc.c.jj	Sun Apr 28 23:27:35 2002
+++ gcc/config/sparc/sparc.c	Tue Apr 30 13:02:38 2002
@@ -498,6 +498,35 @@ fp_register_operand (op, mode)
   return GET_CODE (op) == REG && SPARC_FP_REG_P (REGNO (op));
 }
 
+/* Nonzero if OP is a register operand in floating point register.  */
+
+int
+int_register_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (! register_operand (op, mode))
+    return 0;
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+  return GET_CODE (op) == REG && REGNO (op) < 32;
+}
+
+/* Nonzero if OP is a register operand in floating point v9 register.  */
+
+int
+fp_v9_register_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (! register_operand (op, mode))
+    return 0;
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+  return GET_CODE (op) == REG && SPARC_FP_REG_P (REGNO (op))
+	 && REGNO (op) >= SPARC_FIRST_V9_FP_REG;
+}
+
 /* Nonzero if OP is a floating point constant which can
    be loaded into an integer register using a single
    sethi instruction.  */
--- gcc/config/sparc/sparc.h.jj	Mon Apr 29 16:22:43 2002
+++ gcc/config/sparc/sparc.h	Tue Apr 30 13:02:38 2002
@@ -3001,6 +3001,8 @@ do {									\
 {"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},		\
 {"fp_zero_operand", {CONST_DOUBLE}},					\
 {"fp_register_operand", {SUBREG, REG}},					\
+{"fp_v9_register_operand", {SUBREG, REG}},				\
+{"int_register_operand", {SUBREG, REG}},				\
 {"intreg_operand", {SUBREG, REG}},					\
 {"fcc_reg_operand", {REG}},						\
 {"fcc0_reg_operand", {REG}},						\
--- gcc/config/sparc/sparc.md.jj	Mon Apr 29 16:22:43 2002
+++ gcc/config/sparc/sparc.md	Tue Apr 30 13:55:30 2002
@@ -44,6 +44,7 @@
 ;;			16	embmedany_textlo
 ;;			18	sethm
 ;;			19	setlo
+;;			20	movdf_ldd/std
 ;;
 ;; UNSPEC_VOLATILE:	0	blockage
 ;;			1	flush_register_windows
@@ -3459,6 +3460,36 @@
   stx\\t%r1, %0"
   [(set_attr "type" "*,load,store")])
 
+;; The UNSPEC is here so that it is only matched if generated
+;; from movdf splitters
+(define_insn "movdf_ldd"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=e")
+        (match_operand:DF 1 "input_operand" "m"))
+   (unspec:DF [(const_int 0)] 20)]
+  "TARGET_FPU
+   && reload_completed
+   && ! TARGET_ARCH64
+   && fp_register_operand (operands[0], DFmode)
+   && ((! TARGET_UNALIGNED_DOUBLES
+	&& ! mem_min_alignment (operands[1], 4))
+       || fp_v9_register_operand (operands[0], DFmode))"
+  "ldd\\t%1, %0"
+  [(set_attr "type" "load")])
+
+(define_insn "movdf_std"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=m")
+        (match_operand:DF 1 "input_operand" "e"))
+   (unspec:DF [(const_int 0)] 20)]
+  "TARGET_FPU
+   && reload_completed
+   && ! TARGET_ARCH64
+   && fp_register_operand (operands[1], DFmode)
+   && ((! TARGET_UNALIGNED_DOUBLES
+	&& ! mem_min_alignment (operands[0], 4))
+       || fp_v9_register_operand (operands[1], DFmode))"
+  "std\\t%1, %0"
+  [(set_attr "type" "store")])
+
 (define_split
   [(set (match_operand:DF 0 "register_operand" "")
         (match_operand:DF 1 "const_double_operand" ""))]
@@ -3523,11 +3554,7 @@
         (match_operand:DF 1 "register_operand" ""))]
   "(! TARGET_V9
     || (! TARGET_ARCH64
-        && ((GET_CODE (operands[0]) == REG
-             && REGNO (operands[0]) < 32)
-            || (GET_CODE (operands[0]) == SUBREG
-                && GET_CODE (SUBREG_REG (operands[0])) == REG
-                && REGNO (SUBREG_REG (operands[0])) < 32))))
+        && int_register_operand (operands[0], DFmode)))
    && reload_completed"
   [(clobber (const_int 0))]
   "
@@ -3568,8 +3595,25 @@
   [(clobber (const_int 0))]
   "
 {
-  rtx word0 = adjust_address (operands[1], SFmode, 0);
-  rtx word1 = adjust_address (operands[1], SFmode, 4);
+  rtx word0, word1;
+
+  /* If DEST is %f32 or higher, we really cannot split
+     as there are no SFmode registers >= %f32.
+     If DEST is any floating register and the memory
+     address is not known to be aligned to at least 32 bits,
+     assume it is aligned to 64 bits and let the kernel
+     handle the unaligned case.  */
+  if (fp_register_operand (operands[0], DFmode)
+      && ((! TARGET_UNALIGNED_DOUBLES
+	   && ! mem_min_alignment (operands[1], 4))
+	  || fp_v9_register_operand (operands[0], DFmode)))
+    {
+      emit_insn (gen_movdf_ldd (operands[0], operands[1]));
+      DONE;
+    }
+
+  word0 = adjust_address (operands[1], SFmode, 0);
+  word1 = adjust_address (operands[1], SFmode, 4);
 
   if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1))
     {
@@ -3599,8 +3643,25 @@
   [(clobber (const_int 0))]
   "
 {
-  rtx word0 = adjust_address (operands[0], SFmode, 0);
-  rtx word1 = adjust_address (operands[0], SFmode, 4);
+  rtx word0, word1;
+
+  /* If SRC is %f32 or higher, we really cannot split
+     as there are no SFmode registers >= %f32.
+     If SRC is any floating register and the memory
+     address is not known to be aligned to at least 32 bits,
+     assume it is aligned to 64 bits and let the kernel
+     handle the unaligned case.  */
+  if (fp_register_operand (operands[1], DFmode)
+      && ((! TARGET_UNALIGNED_DOUBLES
+	   && ! mem_min_alignment (operands[0], 4))
+	  || fp_v9_register_operand (operands[1], DFmode)))
+    {
+      emit_insn (gen_movdf_std (operands[0], operands[1]));
+      DONE;
+    }
+
+  word0 = adjust_address (operands[0], SFmode, 0);
+  word1 = adjust_address (operands[0], SFmode, 4);
 
   emit_insn (gen_movsf (word0,
 			gen_highpart (SFmode, operands[1])));
@@ -3635,11 +3696,7 @@
         (match_operand:DF 1 "fp_zero_operand" ""))]
   "reload_completed
    && ! TARGET_ARCH64
-   && ((GET_CODE (operands[0]) == REG
-	&& REGNO (operands[0]) < 32)
-       || (GET_CODE (operands[0]) == SUBREG
-	   && GET_CODE (SUBREG_REG (operands[0])) == REG
-	   && REGNO (SUBREG_REG (operands[0])) < 32))"
+   && int_register_operand (operands[0], DFmode)"
   [(clobber (const_int 0))]
   "
 {
-------------- next part --------------
--- gcc/config/sparc/sparc.md.jj	Mon Apr 29 16:22:43 2002
+++ gcc/config/sparc/sparc.md	Tue Apr 30 12:44:52 2002
@@ -3349,8 +3349,8 @@
 ;; We have available v9 double floats but not 64-bit
 ;; integer registers and no VIS.
 (define_insn "*movdf_insn_v9only_novis"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,W,U,T,e,*r,o")
-        (match_operand:DF 1 "input_operand"    "e,W#F,G,e,T,U,o#F,*roF,*rGe"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,W,U,T,f,*r,o")
+        (match_operand:DF 1 "input_operand"    "e,W#F,G,e,T,U,o#F,*roF,*rGf"))]
   "TARGET_FPU
    && TARGET_V9
    && ! TARGET_VIS
@@ -3375,8 +3375,8 @@
 ;; We have available v9 double floats but not 64-bit
 ;; integer registers but we have VIS.
 (define_insn "*movdf_insn_v9only_vis"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,W,U,T,e,*r,o")
-        (match_operand:DF 1 "input_operand" "G,e,W#F,G,e,T,U,o#F,*roGF,*rGe"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,W,U,T,f,*r,o")
+        (match_operand:DF 1 "input_operand" "G,e,W#F,G,e,T,U,o#F,*roGF,*rGf"))]
   "TARGET_FPU
    && TARGET_VIS
    && ! TARGET_ARCH64


More information about the Gcc-patches mailing list