OSDN Git Service

* config/sparc/sparc.md (movdi_insn_sp64_novis): New pattern.
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 4 Apr 2000 10:13:26 +0000 (10:13 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 4 Apr 2000 10:13:26 +0000 (10:13 +0000)
(movdi_insn_sp64_vis): Renamed from movdi_insn_sp64.
(movsf): Don't force any constant to memory if target is integer
hard register.
Move fp_zero_operand check below the const0_rtx check.
(movtf): Likewise. Also allow fp_zero_operand for stores into
memory.
(movdf): Likewise. Also allow fp_zero_operand for stores into
memory and into integer hard registers.
(clear_df, clear_dfp, movdf_const_intreg_sp32,
movdf_const_intreg_sp64): Remove.
(movdf_insn_sp32, movdf_no_e_insn_sp32): Redo constraints and
conditions.
(movdf_no_e_insn_v9_sp32): New pattern.
(movdf_insn_v9only): Remove.
(movdf_insn_v9only_novis, movdf_insn_v9only_vis): New patterns.
(movdf_insn_sp64): Remove.
(movdf_insn_sp64_novis, movdf_insn_sp64_vis): New patterns.
(movdf_no_e_insn_sp64): Allow storing 0.0 into memory.
(following splits): Rewrite conditions. Add two new splits
for storing 0.0 into memory and registers.
(clear_tf, clear_tf+1, clear_tfp, clear_tfp+1): Remove.
(movtf_insn_sp32): Redo constraints and conditions.
(movtf_insn_vis_sp32): New pattern.
(movtf_no_e_insn_sp32): Redo constraints and conditions.
(movtf_insn_hq_sp64): Likewise.
(movtf_insn_hq_vis_sp64): New pattern.
(movtf_insn_sp64): Redo constraints and conditions.
(movtf_insn_vis_sp64): New pattern.
(movtf_no_e_insn_sp64): Redo constraints and conditions.
(movtf_no_e_insn_sp64+1): New split for storing 0.0L into registers
or memory.
* config/sparc/sparc.c (sparc_override_options): Assume v9 if either
-mvis or -m64 to take down the number of various reload patterns.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@32901 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.md

index 7b1f324..4bdff45 100644 (file)
@@ -6,6 +6,41 @@
        non-optimizing TARGET_ARCH32 in DF or DI modes because it is not
        offsetable.
 
+       * config/sparc/sparc.md (movdi_insn_sp64_novis): New pattern.
+       (movdi_insn_sp64_vis): Renamed from movdi_insn_sp64.
+       (movsf): Don't force any constant to memory if target is integer
+       hard register.
+       Move fp_zero_operand check below the const0_rtx check.
+       (movtf): Likewise. Also allow fp_zero_operand for stores into
+       memory.
+       (movdf): Likewise. Also allow fp_zero_operand for stores into
+       memory and into integer hard registers.
+       (clear_df, clear_dfp, movdf_const_intreg_sp32,
+       movdf_const_intreg_sp64): Remove.
+       (movdf_insn_sp32, movdf_no_e_insn_sp32): Redo constraints and
+       conditions.
+       (movdf_no_e_insn_v9_sp32): New pattern.
+       (movdf_insn_v9only): Remove.
+       (movdf_insn_v9only_novis, movdf_insn_v9only_vis): New patterns.
+       (movdf_insn_sp64): Remove.
+       (movdf_insn_sp64_novis, movdf_insn_sp64_vis): New patterns.
+       (movdf_no_e_insn_sp64): Allow storing 0.0 into memory.
+       (following splits): Rewrite conditions. Add two new splits
+       for storing 0.0 into memory and registers.
+       (clear_tf, clear_tf+1, clear_tfp, clear_tfp+1): Remove.
+       (movtf_insn_sp32): Redo constraints and conditions.
+       (movtf_insn_vis_sp32): New pattern.
+       (movtf_no_e_insn_sp32): Redo constraints and conditions.
+       (movtf_insn_hq_sp64): Likewise.
+       (movtf_insn_hq_vis_sp64): New pattern.
+       (movtf_insn_sp64): Redo constraints and conditions.
+       (movtf_insn_vis_sp64): New pattern.
+       (movtf_no_e_insn_sp64): Redo constraints and conditions.
+       (movtf_no_e_insn_sp64+1): New split for storing 0.0L into registers
+       or memory.
+       * config/sparc/sparc.c (sparc_override_options): Assume v9 if either
+       -mvis or -m64 to take down the number of various reload patterns.
+
 Tue Apr  4 00:41:53 2000  Jeffrey A Law  (law@cygnus.com)
 
        * pa/pa-64.h: New file.
index 2ee24c1..5570796 100644 (file)
@@ -342,6 +342,16 @@ sparc_override_options ()
       target_flags &= ~MASK_FPU_SET;
     }
 
+  /* Don't allow -mvis if FPU is disabled.  */
+  if (! TARGET_FPU)
+    target_flags &= ~MASK_VIS;
+
+  /* -mvis assumes UltraSPARC+, so we are sure v9 instructions
+     are available.
+     -m64 also implies v9.  */
+  if (TARGET_VIS || TARGET_ARCH64)
+    target_flags |= MASK_V9;
+
   /* Use the deprecated v8 insns for sparc64 in 32 bit mode.  */
   if (TARGET_V9 && TARGET_ARCH32)
     target_flags |= MASK_DEPRECATED_V8_INSNS;
@@ -354,10 +364,6 @@ sparc_override_options ()
   if (TARGET_ARCH32)
     target_flags &= ~MASK_STACK_BIAS;
     
-  /* Don't allow -mvis if FPU is disabled.  */
-  if (! TARGET_FPU)
-    target_flags &= ~MASK_VIS;
-
   /* Supply a default value for align_functions.  */
   if (align_functions == 0 && sparc_cpu == PROCESSOR_ULTRASPARC)
     align_functions = 32;
index b98a380..477e45d 100644 (file)
@@ -2298,7 +2298,7 @@ LFLGRET"ID":\n\
 #define REG_OK_FOR_BASE_P(X) \
   (((unsigned) REGNO (X)) - 32 >= (FIRST_PSEUDO_REGISTER - 32))
 
-/* 'T', 'U' are for aligned memory loads which aren't needed for v9.  */
+/* 'T', 'U' are for aligned memory loads which aren't needed for arch64.  */
 
 #define EXTRA_CONSTRAINT(OP, C)                                \
    (EXTRA_CONSTRAINT_BASE(OP, C)                        \
index 3b62a5e..f72f8a8 100644 (file)
   [(set_attr "type" "move")
    (set_attr "length" "1")])
 
-(define_insn "*movdi_insn_sp64"
+(define_insn "*movdi_insn_sp64_novis"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?m")
+        (match_operand:DI 1 "input_operand"   "rI,K,J,m,rJ,e,m,e"))]
+  "TARGET_ARCH64 && ! TARGET_VIS &&
+   (register_operand (operands[0], DImode)
+    || reg_or_0_operand (operands[1], DImode))"
+  "@
+   mov\\t%1, %0
+   sethi\\t%%hi(%a1), %0
+   clr\\t%0
+   ldx\\t%1, %0
+   stx\\t%r1, %0
+   fmovd\\t%1, %0
+   ldd\\t%1, %0
+   std\\t%1, %0"
+  [(set_attr "type" "move,move,move,load,store,fpmove,fpload,fpstore")
+   (set_attr "length" "1")])
+
+(define_insn "*movdi_insn_sp64_vis"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?m,b")
         (match_operand:DI 1 "input_operand"   "rI,K,J,m,rJ,e,m,e,J"))]
-  "TARGET_ARCH64 &&
+  "TARGET_ARCH64 && TARGET_VIS &&
    (register_operand (operands[0], DImode)
     || reg_or_0_operand (operands[1], DImode))"
   "@
   if (GET_CODE (operands[0]) == REG
       && CONSTANT_P (operands[1]))
     {
-      if (TARGET_VIS && fp_zero_operand (operands[1], SFmode))
-       goto movsf_is_ok;
-
       /* emit_group_store will send such bogosity to us when it is
          not storing directly into memory.  So fix this up to avoid
          crashes in output_constant_pool.  */
       if (operands [1] == const0_rtx)
         operands[1] = CONST0_RTX (SFmode);
+
+      if (TARGET_VIS && fp_zero_operand (operands[1], SFmode))
+       goto movsf_is_ok;
+
+      /* We are able to build any SF constant in integer registers
+        with at most 2 instructions.  */
+      if (REGNO (operands[0]) < 32)
+       goto movsf_is_ok;
+
       operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
                                                    operands[1]));
     }
   ;
 }")
 
-(define_insn "*clear_df"
-  [(set (match_operand:DF 0 "register_operand" "=e")
-        (match_operand:DF 1 "fp_zero_operand" ""))]
-  "TARGET_VIS"
-  "fzero\\t%0"
-  [(set_attr "type" "fpmove")
-   (set_attr "length" "1")])
-
-(define_insn "*clear_dfp"
-  [(set (match_operand:DF 0 "memory_operand" "=m")
-        (match_operand:DF 1 "fp_zero_operand" ""))]
-  "TARGET_V9"
-  "stx\\t%%g0, %0"
-  [(set_attr "type" "store")
-   (set_attr "length" "1")])
-
-(define_insn "*movdf_const_intreg_sp32"
-  [(set (match_operand:DF 0 "register_operand" "=e,e,?r")
-        (match_operand:DF 1 "const_double_operand" "T#F,o#F,F"))]
-  "TARGET_FPU && ! TARGET_ARCH64"
-  "@
-   ldd\\t%1, %0
-   #
-   #"
-  [(set_attr "type" "move")
-   (set_attr "length" "1,2,2")])
-
-;; Now that we redo life analysis with a clean slate after
-;; instruction splitting for sched2 this can work.
-(define_insn "*movdf_const_intreg_sp64"
-  [(set (match_operand:DF 0 "register_operand" "=e,?r")
-        (match_operand:DF 1 "const_double_operand" "m#F,F"))]
-  "TARGET_FPU && TARGET_ARCH64"
-  "@
-   ldd\\t%1, %0
-   #"
-  [(set_attr "type" "move")
-   (set_attr "length" "1,2")])
-
-(define_split
-  [(set (match_operand:DF 0 "register_operand" "")
-        (match_operand:DF 1 "const_double_operand" ""))]
-  "TARGET_FPU
-   && (GET_CODE (operands[0]) == REG
-       && REGNO (operands[0]) < 32)
-   && reload_completed"
-  [(clobber (const_int 0))]
-  "
-{
-  REAL_VALUE_TYPE r;
-  long l[2];
-
-  REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
-  REAL_VALUE_TO_TARGET_DOUBLE (r, l);
-  if (GET_CODE (operands[0]) == SUBREG)
-    operands[0] = alter_subreg (operands[0]);
-  operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
-
-  if (TARGET_ARCH64)
-    {
-#if HOST_BITS_PER_WIDE_INT == 64
-      HOST_WIDE_INT val;
-
-      val = ((HOST_WIDE_INT)(unsigned long)l[1] |
-             ((HOST_WIDE_INT)(unsigned long)l[0] << 32));
-      emit_insn (gen_movdi (operands[0], GEN_INT (val)));
-#else
-      emit_insn (gen_movdi (operands[0],
-                            gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx,
-                                                  l[1], l[0])));
-#endif
-    }
-  else
-    {
-      emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
-                           GEN_INT (l[0])));
-
-      /* Slick... but this trick loses if this subreg constant part
-         can be done in one insn.  */
-      if (l[1] == l[0]
-          && !(SPARC_SETHI_P (l[0])
-              || SPARC_SIMM13_P (l[0])))
-        {
-          emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
-                               gen_highpart (SImode, operands[0])));
-        }
-      else
-        {
-          emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
-                               GEN_INT (l[1])));
-        }
-    }
-  DONE;
-}")
-
 (define_expand "movdf"
   [(set (match_operand:DF 0 "general_operand" "")
        (match_operand:DF 1 "general_operand" ""))]
   if (GET_CODE (operands[0]) == REG
       && CONSTANT_P (operands[1]))
     {
-      if (TARGET_VIS && fp_zero_operand (operands[1], DFmode))
-       goto movdf_is_ok;
-
       /* emit_group_store will send such bogosity to us when it is
          not storing directly into memory.  So fix this up to avoid
          crashes in output_constant_pool.  */
       if (operands [1] == const0_rtx)
         operands[1] = CONST0_RTX (DFmode);
+
+      if ((TARGET_VIS || REGNO (operands[0]) < 32)
+         && fp_zero_operand (operands[1], DFmode))
+       goto movdf_is_ok;
+
       operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
                                                    operands[1]));
     }
   /* Handle MEM cases first.  */
   if (GET_CODE (operands[0]) == MEM)
     {
-      if (register_operand (operands[1], DFmode))
+      if (register_operand (operands[1], DFmode)
+         || fp_zero_operand (operands[1], DFmode))
        goto movdf_is_ok;
 
       if (! reload_in_progress)
 
 ;; Be careful, fmovd does not exist when !v9.
 (define_insn "*movdf_insn_sp32"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,T,U,T,e,r,r,o,e,o")
-       (match_operand:DF 1 "input_operand"    "T,e,T,U,e,r,o,r,o,e"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,T,U,T,o,e,*r,o,e,o")
+       (match_operand:DF 1 "input_operand"    "T#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
   "TARGET_FPU
    && ! TARGET_V9
    && (register_operand (operands[0], DFmode)
-       || register_operand (operands[1], DFmode))"
+       || register_operand (operands[1], DFmode)
+       || fp_zero_operand (operands[1], DFmode))"
   "@
   ldd\\t%1, %0
   std\\t%1, %0
   (set_attr "length" "1,1,1,1,2,2,2,2,2,2")])
 
 (define_insn "*movdf_no_e_insn_sp32"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,r,r,o")
-       (match_operand:DF 1 "input_operand"    "T,U,r,o,r"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,o,r,o")
+       (match_operand:DF 1 "input_operand"    "T,U,G,ro,r"))]
   "! TARGET_FPU
+   && ! TARGET_V9
    && ! TARGET_ARCH64
    && (register_operand (operands[0], DFmode)
-       || register_operand (operands[1], DFmode))"
+       || register_operand (operands[1], DFmode)
+       || fp_zero_operand (operands[1], DFmode))"
   "@
   ldd\\t%1, %0
   std\\t%1, %0
   [(set_attr "type" "load,store,*,*,*")
    (set_attr "length" "1,1,2,2,2")])
 
+(define_insn "*movdf_no_e_insn_v9_sp32"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
+       (match_operand:DF 1 "input_operand"    "T,U,G,ro,rG"))]
+  "! TARGET_FPU
+   && TARGET_V9
+   && ! TARGET_ARCH64
+   && (register_operand (operands[0], DFmode)
+       || register_operand (operands[1], DFmode)
+       || fp_zero_operand (operands[1], DFmode))"
+  "@
+  ldd\\t%1, %0
+  std\\t%1, %0
+  stx\\t%r1, %0
+  #
+  #"
+  [(set_attr "type" "load,store,store,*,*")
+   (set_attr "length" "1,1,1,2,2")])
+
 ;; We have available v9 double floats but not 64-bit
-;; integer registers.
-(define_insn "*movdf_insn_v9only"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,m,U,T,r,r,o")
-        (match_operand:DF 1 "input_operand"    "e,m,e,T,U,r,o,r"))]
+;; integer registers and no VIS.
+(define_insn "*movdf_insn_v9only_novis"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,T,U,T,e,*r,o")
+        (match_operand:DF 1 "input_operand"    "e,T#F,G,e,T,U,o#F,*roF,*rGe"))]
   "TARGET_FPU
    && TARGET_V9
+   && ! TARGET_VIS
+   && ! TARGET_ARCH64
+   && (register_operand (operands[0], DFmode)
+       || register_operand (operands[1], DFmode)
+       || fp_zero_operand (operands[1], DFmode))"
+  "@
+  fmovd\\t%1, %0
+  ldd\\t%1, %0
+  stx\\t%r1, %0
+  std\\t%1, %0
+  ldd\\t%1, %0
+  std\\t%1, %0
+  #
+  #
+  #"
+  [(set_attr "type" "fpmove,load,store,store,load,store,*,*,*")
+   (set_attr "length" "1,1,1,1,1,1,2,2,2")])
+
+;; 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,T,U,T,e,*r,o")
+        (match_operand:DF 1 "input_operand" "G,e,T#F,G,e,T,U,o#F,*roGF,*rGe"))]
+  "TARGET_FPU
+   && TARGET_VIS
    && ! TARGET_ARCH64
    && (register_operand (operands[0], DFmode)
-       || register_operand (operands[1], DFmode))"
+       || register_operand (operands[1], DFmode)
+       || fp_zero_operand (operands[1], DFmode))"
   "@
+  fzero\\t%1, %0
   fmovd\\t%1, %0
   ldd\\t%1, %0
+  stx\\t%r1, %0
   std\\t%1, %0
   ldd\\t%1, %0
   std\\t%1, %0
   #
   #
   #"
-  [(set_attr "type" "fpmove,load,store,load,store,*,*,*")
-   (set_attr "length" "1,1,1,1,1,2,2,2")])
+  [(set_attr "type" "fpmove,fpmove,load,store,store,load,store,*,*,*")
+   (set_attr "length" "1,1,1,1,1,1,1,2,2,2")])
 
 ;; We have available both v9 double floats and 64-bit
-;; integer registers.
-(define_insn "*movdf_insn_sp64"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,m,r,r,m")
-        (match_operand:DF 1 "input_operand"    "e,m,e,r,m,r"))]
+;; integer registers. No VIS though.
+(define_insn "*movdf_insn_sp64_novis"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,m,*r,*r,m,*r")
+        (match_operand:DF 1 "input_operand"    "e,m#F,e,*rG,m,*rG,F"))]
   "TARGET_FPU
-   && TARGET_V9
+   && ! TARGET_VIS
    && TARGET_ARCH64
    && (register_operand (operands[0], DFmode)
-       || register_operand (operands[1], DFmode))"
+       || register_operand (operands[1], DFmode)
+       || fp_zero_operand (operands[1], DFmode))"
   "@
   fmovd\\t%1, %0
   ldd\\t%1, %0
   std\\t%1, %0
-  mov\\t%1, %0
+  mov\\t%r1, %0
   ldx\\t%1, %0
-  stx\\t%1, %0"
-  [(set_attr "type" "fpmove,load,store,move,load,store")
-   (set_attr "length" "1")])
+  stx\\t%r1, %0
+  #"
+  [(set_attr "type" "fpmove,load,store,move,load,store,*")
+   (set_attr "length" "1,1,1,1,1,1,2")])
+
+;; We have available both v9 double floats and 64-bit
+;; integer registers. And we have VIS.
+(define_insn "*movdf_insn_sp64_vis"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,m,*r,*r,m,*r")
+        (match_operand:DF 1 "input_operand"    "G,e,m#F,e,*rG,m,*rG,F"))]
+  "TARGET_FPU
+   && TARGET_VIS
+   && TARGET_ARCH64
+   && (register_operand (operands[0], DFmode)
+       || register_operand (operands[1], DFmode)
+       || fp_zero_operand (operands[1], DFmode))"
+  "@
+  fzero\\t%0
+  fmovd\\t%1, %0
+  ldd\\t%1, %0
+  std\\t%1, %0
+  mov\\t%r1, %0
+  ldx\\t%1, %0
+  stx\\t%r1, %0
+  #"
+  [(set_attr "type" "fpmove,fpmove,load,store,move,load,store,*")
+   (set_attr "length" "1,1,1,1,1,1,1,2")])
 
 (define_insn "*movdf_no_e_insn_sp64"
   [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
-        (match_operand:DF 1 "input_operand"    "r,m,r"))]
+        (match_operand:DF 1 "input_operand"    "r,m,rG"))]
   "! TARGET_FPU
    && TARGET_ARCH64
    && (register_operand (operands[0], DFmode)
-       || register_operand (operands[1], DFmode))"
+       || register_operand (operands[1], DFmode)
+       || fp_zero_operand (operands[1], DFmode))"
   "@
   mov\\t%1, %0
   ldx\\t%1, %0
-  stx\\t%1, %0"
+  stx\\t%r1, %0"
   [(set_attr "type" "move,load,store")
    (set_attr "length" "1")])
 
+(define_split
+  [(set (match_operand:DF 0 "register_operand" "")
+        (match_operand:DF 1 "const_double_operand" ""))]
+  "TARGET_FPU
+   && (GET_CODE (operands[0]) == REG
+       && REGNO (operands[0]) < 32)
+   && ! fp_zero_operand(operands[1], DFmode)
+   && reload_completed"
+  [(clobber (const_int 0))]
+  "
+{
+  REAL_VALUE_TYPE r;
+  long l[2];
+
+  REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+  REAL_VALUE_TO_TARGET_DOUBLE (r, l);
+  if (GET_CODE (operands[0]) == SUBREG)
+    operands[0] = alter_subreg (operands[0]);
+  operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
+
+  if (TARGET_ARCH64)
+    {
+#if HOST_BITS_PER_WIDE_INT == 64
+      HOST_WIDE_INT val;
+
+      val = ((HOST_WIDE_INT)(unsigned long)l[1] |
+             ((HOST_WIDE_INT)(unsigned long)l[0] << 32));
+      emit_insn (gen_movdi (operands[0], GEN_INT (val)));
+#else
+      emit_insn (gen_movdi (operands[0],
+                            gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx,
+                                                  l[1], l[0])));
+#endif
+    }
+  else
+    {
+      emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
+                           GEN_INT (l[0])));
+
+      /* Slick... but this trick loses if this subreg constant part
+         can be done in one insn.  */
+      if (l[1] == l[0]
+          && !(SPARC_SETHI_P (l[0])
+              || SPARC_SIMM13_P (l[0])))
+        {
+          emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+                               gen_highpart (SImode, operands[0])));
+        }
+      else
+        {
+          emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+                               GEN_INT (l[1])));
+        }
+    }
+  DONE;
+}")
+
 ;; Ok, now the splits to handle all the multi insn and
 ;; mis-aligned memory address cases.
 ;; In these splits please take note that we must be
 (define_split
   [(set (match_operand:DF 0 "register_operand" "")
        (match_operand:DF 1 "memory_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))))
-    && (reload_completed
-        && (((REGNO (operands[0])) % 2) != 0
-             || ! mem_min_alignment (operands[1], 8))
-        && offsettable_memref_p (operands[1])))"
+  "reload_completed
+   && ! TARGET_ARCH64
+   && (((REGNO (operands[0]) % 2) != 0)
+       || ! mem_min_alignment (operands[1], 8))
+   && offsettable_memref_p (operands[1])"
   [(clobber (const_int 0))]
   "
 {
 (define_split
   [(set (match_operand:DF 0 "memory_operand" "")
        (match_operand:DF 1 "register_operand" ""))]
-  "((! TARGET_V9
-     || (! TARGET_ARCH64
-         && ((GET_CODE (operands[1]) == REG
-              && REGNO (operands[1]) < 32)
-             || (GET_CODE (operands[1]) == SUBREG
-                 && GET_CODE (SUBREG_REG (operands[1])) == REG
-                 && REGNO (SUBREG_REG (operands[1])) < 32))))
-    && (reload_completed
-        && (((REGNO (operands[1])) % 2) != 0
-             || ! mem_min_alignment (operands[0], 8))
-        && offsettable_memref_p (operands[0])))"
+  "reload_completed
+   && ! TARGET_ARCH64
+   && (((REGNO (operands[1]) % 2) != 0)
+       || ! mem_min_alignment (operands[0], 8))
+   && offsettable_memref_p (operands[0])"
   [(clobber (const_int 0))]
   "
 {
   DONE;
 }")
 
-(define_insn "*clear_tf"
-  [(set (match_operand:TF 0 "register_operand" "=e")
-        (match_operand:TF 1 "fp_zero_operand" ""))]
-  "TARGET_VIS"
-  "#"
-  [(set_attr "type" "fpmove")
-   (set_attr "length" "2")])
-
 (define_split
-  [(set (match_operand:TF 0 "register_operand" "")
-        (match_operand:TF 1 "fp_zero_operand" ""))]
-  "TARGET_VIS && reload_completed"
-  [(set (subreg:DF (match_dup 0) 0) (match_dup 1))
-   (set (subreg:DF (match_dup 0) 8) (match_dup 1))]
+  [(set (match_operand:DF 0 "memory_operand" "")
+        (match_operand:DF 1 "fp_zero_operand" ""))]
+  "reload_completed
+   && (! TARGET_V9
+       || (! TARGET_ARCH64
+          && ! mem_min_alignment (operands[0], 8)))
+   && offsettable_memref_p (operands[0])"
+  [(clobber (const_int 0))]
   "
 {
-  operands[1] = CONST0_RTX (DFmode);
-}
-")
+  rtx dest1, dest2;
 
-(define_insn "*clear_tfp"
-  [(set (match_operand:TF 0 "memory_operand" "=m")
-        (match_operand:TF 1 "fp_zero_operand" ""))]
-  "TARGET_V9"
-  "#"
-  [(set_attr "type" "fpmove")
-   (set_attr "length" "2")])
+  dest1 = change_address (operands[0], SFmode, NULL_RTX);
+  dest2 = change_address (operands[0], SFmode,
+                         plus_constant_for_output (XEXP (dest1, 0), 4));
+  emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
+  emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
+  DONE;
+}")
 
 (define_split
-  [(set (match_operand:TF 0 "memory_operand" "=m")
-        (match_operand:TF 1 "fp_zero_operand" ""))]
-  "TARGET_V9 && reload_completed"
-  [(set (subreg:DF (match_dup 0) 0) (match_dup 1))
-   (set (subreg:DF (match_dup 0) 8) (match_dup 1))]
+  [(set (match_operand:DF 0 "register_operand" "")
+        (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))"
+  [(clobber (const_int 0))]
   "
 {
-  operands[1] = CONST0_RTX (DFmode);
-}
-")
+  rtx set_dest = operands[0];
+  rtx dest1, dest2;
+
+  if (GET_CODE (set_dest) == SUBREG)
+    set_dest = alter_subreg (set_dest);
+  dest1 = gen_highpart (SFmode, set_dest);
+  dest2 = gen_lowpart (SFmode, set_dest);
+  emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
+  emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
+  DONE;
+}")
 
 (define_expand "movtf"
   [(set (match_operand:TF 0 "general_operand" "")
   if (GET_CODE (operands[0]) == REG
       && CONSTANT_P (operands[1]))
     {
-      if (TARGET_VIS && fp_zero_operand (operands[1], TFmode))
-       goto movtf_is_ok;
-
       /* emit_group_store will send such bogosity to us when it is
          not storing directly into memory.  So fix this up to avoid
          crashes in output_constant_pool.  */
       if (operands [1] == const0_rtx)
         operands[1] = CONST0_RTX (TFmode);
+
+      if (TARGET_VIS && fp_zero_operand (operands[1], TFmode))
+       goto movtf_is_ok;
+
       operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
                                                    operands[1]));
     }
      full 16-byte alignment for quads. */
   if (GET_CODE (operands[0]) == MEM)
     {
-      if (register_operand (operands[1], TFmode))
-        goto movtf_is_ok;
+      if (register_operand (operands[1], TFmode)
+         || fp_zero_operand (operands[1], TFmode))
+       goto movtf_is_ok;
 
       if (! reload_in_progress)
        {
 ;; Be careful, fmovq and {st,ld}{x,q} do not exist when !arch64 so
 ;; we must split them all.  :-(
 (define_insn "*movtf_insn_sp32"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,o,e,r,r,o")
-       (match_operand:TF 1 "input_operand"    "o,e,o,U,e,r,o,r"))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,o,r,o")
+       (match_operand:TF 1 "input_operand"    "oe,Ge,o,U,ro,r"))]
   "TARGET_FPU
+   && ! TARGET_VIS
    && ! TARGET_ARCH64
    && (register_operand (operands[0], TFmode)
-       || register_operand (operands[1], TFmode))"
+       || register_operand (operands[1], TFmode)
+       || fp_zero_operand (operands[1], TFmode))"
+  "#"
+  [(set_attr "length" "4")])
+
+(define_insn "*movtf_insn_vis_sp32"
+  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,o,r,o")
+       (match_operand:TF 1 "input_operand"    "Goe,Ge,o,U,ro,r"))]
+  "TARGET_FPU
+   && TARGET_VIS
+   && ! TARGET_ARCH64
+   && (register_operand (operands[0], TFmode)
+       || register_operand (operands[1], TFmode)
+       || fp_zero_operand (operands[1], TFmode))"
   "#"
   [(set_attr "length" "4")])
 
 ;; when -mno-fpu.
 
 (define_insn "*movtf_no_e_insn_sp32"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "=U,o,r,r,o")
-       (match_operand:TF 1 "input_operand"    "o,U,r,o,r"))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o,r,o")
+       (match_operand:TF 1 "input_operand"    "G,o,U,ro,r"))]
   "! TARGET_FPU
    && ! TARGET_ARCH64
    && (register_operand (operands[0], TFmode)
-       || register_operand (operands[1], TFmode))"
+       || register_operand (operands[1], TFmode)
+       || fp_zero_operand (operands[1], TFmode))"
   "#"
   [(set_attr "length" "4")])
 
 ;; Now handle the float reg cases directly when arch64,
 ;; hard_quad, and proper reg number alignment are all true.
 (define_insn "*movtf_insn_hq_sp64"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,r,r,o")
-        (match_operand:TF 1 "input_operand"    "e,m,e,r,o,r"))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,o,r,o")
+        (match_operand:TF 1 "input_operand"    "e,m,e,G,ro,r"))]
   "TARGET_FPU
+   && ! TARGET_VIS
    && TARGET_ARCH64
-   && TARGET_V9
    && TARGET_HARD_QUAD
    && (register_operand (operands[0], TFmode)
-       || register_operand (operands[1], TFmode))"
+       || register_operand (operands[1], TFmode)
+       || fp_zero_operand (operands[1], TFmode))"
+  "@
+  fmovq\\t%1, %0
+  ldq\\t%1, %0
+  stq\\t%1, %0
+  #
+  #
+  #"
+  [(set_attr "type" "fpmove,fpload,fpstore,*,*,*")
+   (set_attr "length" "1,1,1,2,2,2")])
+
+(define_insn "*movtf_insn_hq_vis_sp64"
+  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,eo,r,o")
+        (match_operand:TF 1 "input_operand"    "e,m,e,G,ro,r"))]
+  "TARGET_FPU
+   && TARGET_VIS
+   && TARGET_ARCH64
+   && TARGET_HARD_QUAD
+   && (register_operand (operands[0], TFmode)
+       || register_operand (operands[1], TFmode)
+       || fp_zero_operand (operands[1], TFmode))"
   "@
   fmovq\\t%1, %0
   ldq\\t%1, %0
 ;; Now we allow the integer register cases even when
 ;; only arch64 is true.
 (define_insn "*movtf_insn_sp64"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r,o,e,r")
-        (match_operand:TF 1 "input_operand"    "o,e,o,r,e,r"))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "=o,e,r")
+        (match_operand:TF 1 "input_operand"    "Ge,oe,or"))]
+  "TARGET_FPU
+   && ! TARGET_VIS
+   && TARGET_ARCH64
+   && ! TARGET_HARD_QUAD
+   && (register_operand (operands[0], TFmode)
+       || register_operand (operands[1], TFmode)
+       || fp_zero_operand (operands[1], TFmode))"
+  "#"
+  [(set_attr "length" "2")])
+
+(define_insn "*movtf_insn_vis_sp64"
+  [(set (match_operand:TF 0 "nonimmediate_operand" "=eo,e,r")
+        (match_operand:TF 1 "input_operand"    "Ge,o,or"))]
   "TARGET_FPU
+   && TARGET_VIS
    && TARGET_ARCH64
    && ! TARGET_HARD_QUAD
    && (register_operand (operands[0], TFmode)
-       || register_operand (operands[1], TFmode))"
+       || register_operand (operands[1], TFmode)
+       || fp_zero_operand (operands[1], TFmode))"
   "#"
   [(set_attr "length" "2")])
 
 (define_insn "*movtf_no_e_insn_sp64"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,r")
-        (match_operand:TF 1 "input_operand"    "o,r,r"))]
+  [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
+        (match_operand:TF 1 "input_operand"    "or,rG"))]
   "! TARGET_FPU
    && TARGET_ARCH64
    && (register_operand (operands[0], TFmode)
-       || register_operand (operands[1], TFmode))"
+       || register_operand (operands[1], TFmode)
+       || fp_zero_operand (operands[1], TFmode))"
   "#"
   [(set_attr "length" "2")])
 
 }")
 
 (define_split
+  [(set (match_operand:TF 0 "nonimmediate_operand" "")
+        (match_operand:TF 1 "fp_zero_operand" ""))]
+  "reload_completed"
+  [(clobber (const_int 0))]
+  "
+{
+  rtx set_dest = operands[0];
+  rtx dest1, dest2;
+
+  switch (GET_CODE (set_dest))
+    {
+    case SUBREG:
+      set_dest = alter_subreg (set_dest);
+      /* FALLTHROUGH */
+    case REG:
+      dest1 = gen_df_reg (set_dest, 0);
+      dest2 = gen_df_reg (set_dest, 1);
+      break;
+    case MEM:
+      dest1 = change_address (set_dest, DFmode, NULL_RTX);
+      dest2 = change_address (set_dest, DFmode,
+                             plus_constant_for_output (XEXP (dest1, 0), 8));
+      break;
+    default:
+      abort ();      
+    }
+
+  emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode)));
+  emit_insn (gen_movdf (dest2, CONST0_RTX (DFmode)));
+  DONE;
+}")
+
+(define_split
   [(set (match_operand:TF 0 "register_operand" "")
         (match_operand:TF 1 "memory_operand" ""))]
   "(reload_completed