[x86, p4] fix compile/20000804-1.c

Richard Henderson rth@redhat.com
Thu Mar 1 16:37:00 GMT 2007


The failure was caused by emit_move_complex trying to use the
TImode move pattern that becomes available when SSE is enabled.
Except that this pattern does not accept a general register
destination, which causes a reload failure.

I tried extending movti a bit, to accept a general register 
destination and split it after reload as with the other long
move splits we do, but that merely encouraged reload to choose
an SSE register as the preferred class for the TImode pseudo,
which resulted in a lot more pointless moves.

In the end it seemed easiest to emit the same code that we do
when SSE (and the TImode move) is not available.


r~


        * expr.c (emit_move_complex_push): Export.
        (emit_move_complex_parts): Split out from ...
        (emit_move_complex): ... here.
        * expr.h (emit_move_complex_push, emit_move_complex_parts): Declare.
        * config/i386/i386.md (movcdi): New.

Index: expr.c
===================================================================
--- expr.c	(revision 122422)
+++ expr.c	(working copy)
@@ -2987,7 +2987,7 @@ emit_move_resolve_push (enum machine_mod
    X is known to satisfy push_operand, and MODE is known to be complex.
    Returns the last instruction emitted.  */
 
-static rtx
+rtx
 emit_move_complex_push (enum machine_mode mode, rtx x, rtx y)
 {
   enum machine_mode submode = GET_MODE_INNER (mode);
@@ -3027,6 +3027,25 @@ emit_move_complex_push (enum machine_mod
 			 read_complex_part (y, !imag_first));
 }
 
+/* A subroutine of emit_move_complex.  Perform the move from Y to X
+   via two moves of the parts.  Returns the last instruction emitted.  */
+
+rtx
+emit_move_complex_parts (rtx x, rtx y)
+{
+  /* Show the output dies here.  This is necessary for SUBREGs
+     of pseudos since we cannot track their lifetimes correctly;
+     hard regs shouldn't appear here except as return values.  */
+  if (!reload_completed && !reload_in_progress
+      && REG_P (x) && !reg_overlap_mentioned_p (x, y))
+    emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+
+  write_complex_part (x, read_complex_part (y, false), false);
+  write_complex_part (x, read_complex_part (y, true), true);
+
+  return get_last_insn ();
+}
+
 /* A subroutine of emit_move_insn_1.  Generate a move from Y into X.
    MODE is known to be complex.  Returns the last instruction emitted.  */
 
@@ -3081,16 +3100,7 @@ emit_move_complex (enum machine_mode mod
 	return ret;
     }
 
-  /* Show the output dies here.  This is necessary for SUBREGs
-     of pseudos since we cannot track their lifetimes correctly;
-     hard regs shouldn't appear here except as return values.  */
-  if (!reload_completed && !reload_in_progress
-      && REG_P (x) && !reg_overlap_mentioned_p (x, y))
-    emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
-
-  write_complex_part (x, read_complex_part (y, false), false);
-  write_complex_part (x, read_complex_part (y, true), true);
-  return get_last_insn ();
+  return emit_move_complex_parts (x, y);
 }
 
 /* A subroutine of emit_move_insn_1.  Generate a move from Y into X.
Index: expr.h
===================================================================
--- expr.h	(revision 122422)
+++ expr.h	(working copy)
@@ -465,6 +465,9 @@ extern rtx emit_move_insn (rtx, rtx);
 /* Emit insns to set X from Y, with no frills.  */
 extern rtx emit_move_insn_1 (rtx, rtx);
 
+extern rtx emit_move_complex_push (enum machine_mode, rtx, rtx);
+extern rtx emit_move_complex_parts (rtx, rtx);
+
 /* Push a block of length SIZE (perhaps variable)
    and return an rtx to address the beginning of the block.  */
 extern rtx push_block (rtx, int, int);
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 122422)
+++ config/i386/i386.md	(working copy)
@@ -2266,6 +2266,22 @@
   [(const_int 0)]
   "ix86_split_long_move (operands); DONE;")
 
+;; This expands to what emit_move_complex would generate if we didn't
+;; have a movti pattern.  Having this avoids problems with reload on
+;; 32-bit targets when SSE is present, but doesn't seem to be harmful
+;; to have around all the time.
+(define_expand "movcdi"
+  [(set (match_operand:CDI 0 "nonimmediate_operand" "")
+	(match_operand:CDI 1 "general_operand" ""))]
+  ""
+{
+  if (push_operand (operands[0], CDImode))
+    emit_move_complex_push (CDImode, operands[0], operands[1]);
+  else
+    emit_move_complex_parts (operands[0], operands[1]);
+  DONE;
+})
+
 (define_expand "movsf"
   [(set (match_operand:SF 0 "nonimmediate_operand" "")
 	(match_operand:SF 1 "general_operand" ""))]



More information about the Gcc-patches mailing list