diff mbox

Canonicalize sparc movcc patterns such that operand 0 always appears in operand 4.

Message ID 20111026.172055.1361157389798399406.davem@davemloft.net
State New
Headers show

Commit Message

David Miller Oct. 26, 2011, 9:20 p.m. UTC
The background is that I was putting together some test cases for
gcc.target/sparc that make sure the most optimal setcc sequences
are being generated.

When v9, and thus conditional moves, are enabled we sometimes fall
back to conditional moves even when the addx/subx sequence is more
efficient.  For example, we can do "a = x < y" in 2 instructions when
x and y are both unsigned:

	cmp	y, x
	subx	%g0, -1, a

but with v9 enabled we get:

	cmp	x, y
	mov	0, a
	movleu	%icc, 1, a

The reason is because of the permissive way in which we define the RTL
for conditional moves.

For the integer moves we mark both operands 3 and 4 using predicate
"arith*_operand" which accepts constants as well as registers.  The
constraints do in fact express how one of the two operands must be
equal the operand 0. However combine doesn't look at constraints to
determine if a combined instruction is recognized.

So combine thinks that insns of the form:

	(set op0 (if_then_else (CMP X Y)
                               (const_int 0)
                               (const_int 1)))

are ok.  Reload later fixes things up by reloading one of the two
constants into operand 0, and that's how we end up with the above 3
instruction sequence.

Initially I tried to fix up the conditional move patterns by using a
"match_dup 0" for operand 4 to show the combiner, in the RTL, that
operand 4 must be equal to operand 0.

But I learned that this is not legal RTL.  You can only use match_dup
in instructions after the first instruction of an expansion that
initially makes use of the operand.  Surprisingly this worked most of
the time. The failures I got were in a regrename def/use chain
assertion check when loop unrolling was enabled.

Anyways, instead what I do here is normalize all expansions of
conditional moves to be of the form:

	(set op0 (if_then_else (cmp X Y)
			       op3
                               op0))

and in the instruction patterns I use "register_operand" and
constraint "0" for operand 4.

This is enough to keep the combiner from recognizing sequences
like the above.

Committed to trunk.

gcc/

	* config/sparc/sparc-protos.h (sparc_expand_conditional_move): Declare.
	* config/sparc/sparc.md (mov<I:mode>cc, mov<F:mode>cc): Call it.
	(*mov<I:mode>_cc_v9): Normalize to expect operand 0 always in operand 4.
	(*mov<I:mode>_cc_reg_sp64): Likewise.
	(*movsf_cc_v9): Likewise.
	(*movsf_cc_reg_sp64): Likewise.
	(*movdf_cc_v9): Likewise.
	(*movdf_cc_reg_sp64): Likewise.
	(*movtf_cc_hq_v9): Likewise.
	(*movtf_cc_reg_hq_sp64): Likewise.
	(*movtf_cc_v9): Likewise.
	(*movtf_cc_reg_sp64): Likewise.
	* config/sparc/sparc.c (sparc_expand_conditional_move): New function.
	(sparc_print_operand): Delete 'c' and 'd' handling, no longer used.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180542 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                   |   17 ++++
 gcc/config/sparc/sparc-protos.h |    1 +
 gcc/config/sparc/sparc.c        |   80 ++++++++++++----
 gcc/config/sparc/sparc.md       |  197 +++++++++++++--------------------------
 4 files changed, 144 insertions(+), 151 deletions(-)

Comments

Eric Botcazou Nov. 2, 2011, 12:29 p.m. UTC | #1
> Anyways, instead what I do here is normalize all expansions of
> conditional moves to be of the form:
>
> 	(set op0 (if_then_else (cmp X Y)
> 			       op3
>                                op0))
>
> and in the instruction patterns I use "register_operand" and
> constraint "0" for operand 4.
>
> This is enough to keep the combiner from recognizing sequences
> like the above.
>
> Committed to trunk.
>
> gcc/
>
> 	* config/sparc/sparc-protos.h (sparc_expand_conditional_move): Declare.
> 	* config/sparc/sparc.md (mov<I:mode>cc, mov<F:mode>cc): Call it.
> 	(*mov<I:mode>_cc_v9): Normalize to expect operand 0 always in operand 4.
> 	(*mov<I:mode>_cc_reg_sp64): Likewise.
> 	(*movsf_cc_v9): Likewise.
> 	(*movsf_cc_reg_sp64): Likewise.
> 	(*movdf_cc_v9): Likewise.
> 	(*movdf_cc_reg_sp64): Likewise.
> 	(*movtf_cc_hq_v9): Likewise.
> 	(*movtf_cc_reg_hq_sp64): Likewise.
> 	(*movtf_cc_v9): Likewise.
> 	(*movtf_cc_reg_sp64): Likewise.
> 	* config/sparc/sparc.c (sparc_expand_conditional_move): New function.
> 	(sparc_print_operand): Delete 'c' and 'd' handling, no longer used.

This has reintroduced PR target/49965.

> @@ -11377,4 +11361,58 @@ sparc_secondary_reload (bool in_p, rtx x,
> reg_class_t rclass_i, return NO_REGS;
>  }
>
> +bool
> +sparc_expand_conditional_move (enum machine_mode mode, rtx *operands)
> +{
> +  enum rtx_code rc = GET_CODE (operands[1]);
> +  enum machine_mode cmp_mode;
> +  rtx cc_reg, dst, cmp;
> +
> +  cmp = operands[1];
> +  cmp_mode = GET_MODE (XEXP (cmp, 0));
> +  if (cmp_mode == DImode && !TARGET_ARCH64)
> +    return false;
> +
> +  dst = operands[0];
> +
> +  if (! rtx_equal_p (operands[2], dst)
> +      && ! rtx_equal_p (operands[3], dst))
> +    {
> +      if (reg_overlap_mentioned_p (dst, cmp))
> +	dst = gen_reg_rtx (mode);
> +
> +      emit_move_insn (dst, operands[3]);
> +    }
> +  else if (operands[2] == dst)
> +    {
> +      operands[2] = operands[3];
> +
> +      if (GET_MODE_CLASS (cmp_mode) == MODE_FLOAT)
> +        rc = reverse_condition_maybe_unordered (rc);
> +      else
> +        rc = reverse_condition (rc);
> +    }
> +
> +  if (cmp_mode == TFmode && !TARGET_HARD_QUAD)
> +    cmp = sparc_emit_float_lib_cmp (XEXP (cmp, 0), XEXP (cmp, 1), rc);

You cannot cache anything from operands[1] as sparc_emit_float_lib_cmp will 
modify it, including RC.

> +  if (XEXP (cmp, 1) == const0_rtx
> +      && GET_CODE (XEXP (cmp, 0)) == REG
> +      && cmp_mode == DImode
> +      && v9_regcmp_p (rc))
> +    cc_reg = XEXP (cmp, 0);
> +  else
> +    cc_reg = gen_compare_reg_1 (rc, XEXP (cmp, 0), XEXP (cmp, 1));
> +
> +  cmp = gen_rtx_fmt_ee (rc, GET_MODE (cc_reg), cc_reg, const0_rtx);

RC is wrong here if we went through sparc_emit_float_lib_cmp above.
David Miller Nov. 2, 2011, 8:17 p.m. UTC | #2
From: Eric Botcazou <ebotcazou@adacore.com>
Date: Wed, 2 Nov 2011 13:29:45 +0100

> This has reintroduced PR target/49965.

I am working on fixing this right now, thanks for reporting Eric.
diff mbox

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cd1a236..d6d1382 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@ 
+2011-10-26  David S. Miller  <davem@davemloft.net>
+
+	* config/sparc/sparc-protos.h (sparc_expand_conditional_move): Declare.
+	* config/sparc/sparc.md (mov<I:mode>cc, mov<F:mode>cc): Call it.
+	(*mov<I:mode>_cc_v9): Normalize to expect operand 0 always in operand 4.
+	(*mov<I:mode>_cc_reg_sp64): Likewise.
+	(*movsf_cc_v9): Likewise.
+	(*movsf_cc_reg_sp64): Likewise.
+	(*movdf_cc_v9): Likewise.
+	(*movdf_cc_reg_sp64): Likewise.
+	(*movtf_cc_hq_v9): Likewise.
+	(*movtf_cc_reg_hq_sp64): Likewise.
+	(*movtf_cc_v9): Likewise.
+	(*movtf_cc_reg_sp64): Likewise.
+	* config/sparc/sparc.c (sparc_expand_conditional_move): New function.
+	(sparc_print_operand): Delete 'c' and 'd' handling, no longer used.
+
 2011-10-26  Eric Botcazou  <ebotcazou@adacore.com>
 
 	* reload.c (reload_inner_reg_of_subreg): Change type of return value
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index bb6fb07..108e105 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -107,6 +107,7 @@  extern void sparc_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
 extern const char *output_v8plus_mult (rtx, rtx *, const char *);
 extern void sparc_expand_vector_init (rtx, rtx);
 extern void sparc_expand_vec_perm_bmask(enum machine_mode, rtx);
+extern bool sparc_expand_conditional_move (enum machine_mode, rtx *);
 #endif /* RTX_CODE */
 
 #endif /* __SPARC_PROTOS_H__ */
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index f806c6c..964bcaf 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -8162,20 +8162,11 @@  sparc_print_operand (FILE *file, rtx x, int code)
 	}
       return;
 
-      /* These are used by the conditional move instructions.  */
-    case 'c' :
+      /* This is used by the conditional move instructions.  */
     case 'C':
       {
 	enum rtx_code rc = GET_CODE (x);
 	
-	if (code == 'c')
-	  {
-	    enum machine_mode mode = GET_MODE (XEXP (x, 0));
-	    if (mode == CCFPmode || mode == CCFPEmode)
-	      rc = reverse_condition_maybe_unordered (GET_CODE (x));
-	    else
-	      rc = reverse_condition (GET_CODE (x));
-	  }
 	switch (rc)
 	  {
 	  case NE: fputs ("ne", file); break;
@@ -8196,20 +8187,15 @@  sparc_print_operand (FILE *file, rtx x, int code)
 	  case UNGT: fputs ("ug", file); break;
 	  case UNGE: fputs ("uge", file); break;
 	  case UNEQ: fputs ("ue", file); break;
-	  default: output_operand_lossage (code == 'c'
-					   ? "invalid %%c operand"
-					   : "invalid %%C operand");
+	  default: output_operand_lossage ("invalid %%C operand");
 	  }
 	return;
       }
 
-      /* These are used by the movr instruction pattern.  */
-    case 'd':
+      /* This are used by the movr instruction pattern.  */
     case 'D':
       {
-	enum rtx_code rc = (code == 'd'
-			    ? reverse_condition (GET_CODE (x))
-			    : GET_CODE (x));
+	enum rtx_code rc = GET_CODE (x);
 	switch (rc)
 	  {
 	  case NE: fputs ("ne", file); break;
@@ -8218,9 +8204,7 @@  sparc_print_operand (FILE *file, rtx x, int code)
 	  case LT: fputs ("lz", file); break;
 	  case LE: fputs ("lez", file); break;
 	  case GT: fputs ("gz", file); break;
-	  default: output_operand_lossage (code == 'd'
-					   ? "invalid %%d operand"
-					   : "invalid %%D operand");
+	  default: output_operand_lossage ("invalid %%D operand");
 	  }
 	return;
       }
@@ -11377,4 +11361,58 @@  sparc_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
   return NO_REGS;
 }
 
+bool
+sparc_expand_conditional_move (enum machine_mode mode, rtx *operands)
+{
+  enum rtx_code rc = GET_CODE (operands[1]);
+  enum machine_mode cmp_mode;
+  rtx cc_reg, dst, cmp;
+
+  cmp = operands[1];
+  cmp_mode = GET_MODE (XEXP (cmp, 0));
+  if (cmp_mode == DImode && !TARGET_ARCH64)
+    return false;
+
+  dst = operands[0];
+
+  if (! rtx_equal_p (operands[2], dst)
+      && ! rtx_equal_p (operands[3], dst))
+    {
+      if (reg_overlap_mentioned_p (dst, cmp))
+	dst = gen_reg_rtx (mode);
+
+      emit_move_insn (dst, operands[3]);
+    }
+  else if (operands[2] == dst)
+    {
+      operands[2] = operands[3];
+
+      if (GET_MODE_CLASS (cmp_mode) == MODE_FLOAT)
+        rc = reverse_condition_maybe_unordered (rc);
+      else
+        rc = reverse_condition (rc);
+    }
+
+  if (cmp_mode == TFmode && !TARGET_HARD_QUAD)
+    cmp = sparc_emit_float_lib_cmp (XEXP (cmp, 0), XEXP (cmp, 1), rc);
+
+  if (XEXP (cmp, 1) == const0_rtx
+      && GET_CODE (XEXP (cmp, 0)) == REG
+      && cmp_mode == DImode
+      && v9_regcmp_p (rc))
+    cc_reg = XEXP (cmp, 0);
+  else
+    cc_reg = gen_compare_reg_1 (rc, XEXP (cmp, 0), XEXP (cmp, 1));
+
+  cmp = gen_rtx_fmt_ee (rc, GET_MODE (cc_reg), cc_reg, const0_rtx);
+
+  emit_insn (gen_rtx_SET (VOIDmode, dst,
+			  gen_rtx_IF_THEN_ELSE (mode, cmp, operands[2], dst)));
+
+  if (dst != operands[0])
+    emit_move_insn (operands[0], dst);
+
+  return true;
+}
+
 #include "gt-sparc.h"
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index d1ebb24..2bae28e 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -2456,6 +2456,9 @@ 
 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
 ;; 3 contains the constant if one is present, but we handle either for
 ;; generality (sparc.c puts a constant in operand 2).
+;;
+;; Our instruction patterns, on the other hand, canonicalize such that
+;; operand 3 must be the set destination.
 
 (define_expand "mov<I:mode>cc"
   [(set (match_operand:I 0 "register_operand" "")
@@ -2464,27 +2467,9 @@ 
 			(match_operand:I 3 "arith10_operand" "")))]
   "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
 {
-  rtx cc_reg;
-
-  if (GET_MODE (XEXP (operands[1], 0)) == DImode && !TARGET_ARCH64)
+  if (! sparc_expand_conditional_move (<I:MODE>mode, operands))
     FAIL;
-
-  if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
-    operands[1]
-      = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
-				  GET_CODE (operands[1]));
-
-  if (XEXP (operands[1], 1) == const0_rtx
-      && GET_CODE (XEXP (operands[1], 0)) == REG
-      && GET_MODE (XEXP (operands[1], 0)) == DImode
-      && v9_regcmp_p (GET_CODE (operands[1])))
-    cc_reg = XEXP (operands[1], 0);
-  else
-    cc_reg = gen_compare_reg (operands[1]);
-
-  operands[1]
-    = gen_rtx_fmt_ee (GET_CODE (operands[1]), GET_MODE (cc_reg), cc_reg,
-		      const0_rtx);
+  DONE;
 })
 
 (define_expand "mov<F:mode>cc"
@@ -2494,146 +2479,112 @@ 
 			(match_operand:F 3 "register_operand" "")))]
   "TARGET_V9 && TARGET_FPU"
 {
-  rtx cc_reg;
-
-  if (GET_MODE (XEXP (operands[1], 0)) == DImode && !TARGET_ARCH64)
+  if (! sparc_expand_conditional_move (<F:MODE>mode, operands))
     FAIL;
-
-  if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
-    operands[1]
-      = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
-				  GET_CODE (operands[1]));
-
-  if (XEXP (operands[1], 1) == const0_rtx
-      && GET_CODE (XEXP (operands[1], 0)) == REG
-      && GET_MODE (XEXP (operands[1], 0)) == DImode
-      && v9_regcmp_p (GET_CODE (operands[1])))
-    cc_reg = XEXP (operands[1], 0);
-  else
-    cc_reg = gen_compare_reg (operands[1]);
-
-  operands[1]
-    = gen_rtx_fmt_ee (GET_CODE (operands[1]), GET_MODE (cc_reg), cc_reg,
-		      const0_rtx);
+  DONE;
 })
 
 ;; Conditional move define_insns
 
 (define_insn "*mov<I:mode>_cc_v9"
-  [(set (match_operand:I 0 "register_operand" "=r,r")
+  [(set (match_operand:I 0 "register_operand" "=r")
 	(if_then_else:I (match_operator 1 "comparison_operator"
-			       [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+			       [(match_operand 2 "icc_or_fcc_register_operand" "X")
 				(const_int 0)])
-			(match_operand:I 3 "arith11_operand" "rL,0")
-			(match_operand:I 4 "arith11_operand" "0,rL")))]
+			(match_operand:I 3 "arith11_operand" "rL")
+			(match_operand:I 4 "register_operand" "0")))]
   "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
-  "@
-   mov%C1\t%x2, %3, %0
-   mov%c1\t%x2, %4, %0"
+  "mov%C1\t%x2, %3, %0"
   [(set_attr "type" "cmove")])
 
 (define_insn "*mov<I:mode>_cc_reg_sp64"
-  [(set (match_operand:I 0 "register_operand" "=r,r")
+  [(set (match_operand:I 0 "register_operand" "=r")
 	(if_then_else:I (match_operator 1 "v9_register_compare_operator"
-				[(match_operand:DI 2 "register_operand" "r,r")
+				[(match_operand:DI 2 "register_operand" "r")
 				 (const_int 0)])
-			(match_operand:I 3 "arith10_operand" "rM,0")
-			(match_operand:I 4 "arith10_operand" "0,rM")))]
+			(match_operand:I 3 "arith10_operand" "rM")
+			(match_operand:I 4 "register_operand" "0")))]
   "TARGET_ARCH64"
-  "@
-   movr%D1\t%2, %r3, %0
-   movr%d1\t%2, %r4, %0"
+  "movr%D1\t%2, %r3, %0"
   [(set_attr "type" "cmove")])
 
 (define_insn "*movsf_cc_v9"
-  [(set (match_operand:SF 0 "register_operand" "=f,f")
+  [(set (match_operand:SF 0 "register_operand" "=f")
 	(if_then_else:SF (match_operator 1 "comparison_operator"
-				[(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+				[(match_operand 2 "icc_or_fcc_register_operand" "X")
 				 (const_int 0)])
-			 (match_operand:SF 3 "register_operand" "f,0")
-			 (match_operand:SF 4 "register_operand" "0,f")))]
+			 (match_operand:SF 3 "register_operand" "f")
+			 (match_operand:SF 4 "register_operand" "0")))]
   "TARGET_V9 && TARGET_FPU"
-  "@
-   fmovs%C1\t%x2, %3, %0
-   fmovs%c1\t%x2, %4, %0"
+  "fmovs%C1\t%x2, %3, %0"
   [(set_attr "type" "fpcmove")])
 
 (define_insn "*movsf_cc_reg_sp64"
-  [(set (match_operand:SF 0 "register_operand" "=f,f")
+  [(set (match_operand:SF 0 "register_operand" "=f")
 	(if_then_else:SF (match_operator 1 "v9_register_compare_operator"
-				[(match_operand:DI 2 "register_operand" "r,r")
+				[(match_operand:DI 2 "register_operand" "r")
 				 (const_int 0)])
-			 (match_operand:SF 3 "register_operand" "f,0")
-			 (match_operand:SF 4 "register_operand" "0,f")))]
+			 (match_operand:SF 3 "register_operand" "f")
+			 (match_operand:SF 4 "register_operand" "0")))]
   "TARGET_ARCH64 && TARGET_FPU"
-  "@
-   fmovrs%D1\t%2, %3, %0
-   fmovrs%d1\t%2, %4, %0"
+  "fmovrs%D1\t%2, %3, %0"
   [(set_attr "type" "fpcrmove")])
 
 ;; Named because invoked by movtf_cc_v9
 (define_insn "movdf_cc_v9"
-  [(set (match_operand:DF 0 "register_operand" "=e,e")
+  [(set (match_operand:DF 0 "register_operand" "=e")
 	(if_then_else:DF (match_operator 1 "comparison_operator"
-				[(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+				[(match_operand 2 "icc_or_fcc_register_operand" "X")
 				 (const_int 0)])
-			 (match_operand:DF 3 "register_operand" "e,0")
-			 (match_operand:DF 4 "register_operand" "0,e")))]
+			 (match_operand:DF 3 "register_operand" "e")
+			 (match_operand:DF 4 "register_operand" "0")))]
   "TARGET_V9 && TARGET_FPU"
-  "@
-   fmovd%C1\t%x2, %3, %0
-   fmovd%c1\t%x2, %4, %0"
+  "fmovd%C1\t%x2, %3, %0"
   [(set_attr "type" "fpcmove")
    (set_attr "fptype" "double")])
 
 ;; Named because invoked by movtf_cc_reg_sp64
 (define_insn "movdf_cc_reg_sp64"
-  [(set (match_operand:DF 0 "register_operand" "=e,e")
+  [(set (match_operand:DF 0 "register_operand" "=e")
 	(if_then_else:DF (match_operator 1 "v9_register_compare_operator"
-				[(match_operand:DI 2 "register_operand" "r,r")
+				[(match_operand:DI 2 "register_operand" "r")
 				 (const_int 0)])
-			 (match_operand:DF 3 "register_operand" "e,0")
-			 (match_operand:DF 4 "register_operand" "0,e")))]
+			 (match_operand:DF 3 "register_operand" "e")
+			 (match_operand:DF 4 "register_operand" "0")))]
   "TARGET_ARCH64 && TARGET_FPU"
-  "@
-   fmovrd%D1\t%2, %3, %0
-   fmovrd%d1\t%2, %4, %0"
+  "fmovrd%D1\t%2, %3, %0"
   [(set_attr "type" "fpcrmove")
    (set_attr "fptype" "double")])
 
 (define_insn "*movtf_cc_hq_v9"
-  [(set (match_operand:TF 0 "register_operand" "=e,e")
+  [(set (match_operand:TF 0 "register_operand" "=e")
 	(if_then_else:TF (match_operator 1 "comparison_operator"
-				[(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+				[(match_operand 2 "icc_or_fcc_register_operand" "X")
 				 (const_int 0)])
-			 (match_operand:TF 3 "register_operand" "e,0")
-			 (match_operand:TF 4 "register_operand" "0,e")))]
+			 (match_operand:TF 3 "register_operand" "e")
+			 (match_operand:TF 4 "register_operand" "0")))]
   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
-  "@
-   fmovq%C1\t%x2, %3, %0
-   fmovq%c1\t%x2, %4, %0"
+  "fmovq%C1\t%x2, %3, %0"
   [(set_attr "type" "fpcmove")])
 
 (define_insn "*movtf_cc_reg_hq_sp64"
-  [(set (match_operand:TF 0 "register_operand" "=e,e")
+  [(set (match_operand:TF 0 "register_operand" "=e")
 	(if_then_else:TF (match_operator 1 "v9_register_compare_operator"
-				[(match_operand:DI 2 "register_operand" "r,r")
+				[(match_operand:DI 2 "register_operand" "r")
 				 (const_int 0)])
-			 (match_operand:TF 3 "register_operand" "e,0")
-			 (match_operand:TF 4 "register_operand" "0,e")))]
+			 (match_operand:TF 3 "register_operand" "e")
+			 (match_operand:TF 4 "register_operand" "0")))]
   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
-  "@
-   fmovrq%D1\t%2, %3, %0
-   fmovrq%d1\t%2, %4, %0"
+  "fmovrq%D1\t%2, %3, %0"
   [(set_attr "type" "fpcrmove")])
 
 (define_insn_and_split "*movtf_cc_v9"
-  [(set (match_operand:TF 0 "register_operand" "=e,e")
+  [(set (match_operand:TF 0 "register_operand" "=e")
 	(if_then_else:TF (match_operator 1 "comparison_operator"
-			    [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+			    [(match_operand 2 "icc_or_fcc_register_operand" "X")
 			     (const_int 0)])
-			 (match_operand:TF 3 "register_operand" "e,0")
-			 (match_operand:TF 4 "register_operand" "0,e")))]
+			 (match_operand:TF 3 "register_operand" "e")
+			 (match_operand:TF 4 "register_operand" "0")))]
   "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
   "#"
   "&& reload_completed"
@@ -2641,42 +2592,35 @@ 
 {
   rtx set_dest = operands[0];
   rtx set_srca = operands[3];
-  rtx set_srcb = operands[4];
-  int third = rtx_equal_p (set_dest, set_srca);
   rtx dest1, dest2;
-  rtx srca1, srca2, srcb1, srcb2;
+  rtx srca1, srca2;
 
   dest1 = gen_df_reg (set_dest, 0);
   dest2 = gen_df_reg (set_dest, 1);
   srca1 = gen_df_reg (set_srca, 0);
   srca2 = gen_df_reg (set_srca, 1);
-  srcb1 = gen_df_reg (set_srcb, 0);
-  srcb2 = gen_df_reg (set_srcb, 1);
 
-  /* Now emit using the real source and destination we found, swapping
-     the order if we detect overlap.  */
-  if ((third && reg_overlap_mentioned_p (dest1, srcb2))
-      || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+  if (reg_overlap_mentioned_p (dest1, srca2))
     {
-      emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2));
-      emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1));
+      emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, dest2));
+      emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, dest1));
     }
   else
     {
-      emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1));
-      emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2));
+      emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, dest1));
+      emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, dest2));
     }
   DONE;
 }
   [(set_attr "length" "2")])
 
 (define_insn_and_split "*movtf_cc_reg_sp64"
-  [(set (match_operand:TF 0 "register_operand" "=e,e")
+  [(set (match_operand:TF 0 "register_operand" "=e")
 	(if_then_else:TF (match_operator 1 "v9_register_compare_operator"
-				[(match_operand:DI 2 "register_operand" "r,r")
+				[(match_operand:DI 2 "register_operand" "r")
 				 (const_int 0)])
-			 (match_operand:TF 3 "register_operand" "e,0")
-			 (match_operand:TF 4 "register_operand" "0,e")))]
+			 (match_operand:TF 3 "register_operand" "e")
+			 (match_operand:TF 4 "register_operand" "0")))]
   "TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
   "#"
   "&& reload_completed"
@@ -2684,30 +2628,23 @@ 
 {
   rtx set_dest = operands[0];
   rtx set_srca = operands[3];
-  rtx set_srcb = operands[4];
-  int third = rtx_equal_p (set_dest, set_srca);
   rtx dest1, dest2;
-  rtx srca1, srca2, srcb1, srcb2;
+  rtx srca1, srca2;
 
   dest1 = gen_df_reg (set_dest, 0);
   dest2 = gen_df_reg (set_dest, 1);
   srca1 = gen_df_reg (set_srca, 0);
   srca2 = gen_df_reg (set_srca, 1);
-  srcb1 = gen_df_reg (set_srcb, 0);
-  srcb2 = gen_df_reg (set_srcb, 1);
 
-  /* Now emit using the real source and destination we found, swapping
-     the order if we detect overlap.  */
-  if ((third && reg_overlap_mentioned_p (dest1, srcb2))
-      || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+  if (reg_overlap_mentioned_p (dest1, srca2))
     {
-      emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
-      emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+      emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, dest2));
+      emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, dest1));
     }
   else
     {
-      emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
-      emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+      emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, dest1));
+      emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, dest2));
     }
   DONE;
 }